@agentick/cli 0.0.1

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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +353 -0
  3. package/dist/bin.d.ts +6 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +44 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/chat-session.d.ts +37 -0
  8. package/dist/chat-session.d.ts.map +1 -0
  9. package/dist/chat-session.js +201 -0
  10. package/dist/chat-session.js.map +1 -0
  11. package/dist/cli.d.ts +84 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +147 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/commands/chat.d.ts +13 -0
  16. package/dist/commands/chat.d.ts.map +1 -0
  17. package/dist/commands/chat.js +22 -0
  18. package/dist/commands/chat.js.map +1 -0
  19. package/dist/commands/send.d.ts +14 -0
  20. package/dist/commands/send.d.ts.map +1 -0
  21. package/dist/commands/send.js +77 -0
  22. package/dist/commands/send.js.map +1 -0
  23. package/dist/commands/status.d.ts +11 -0
  24. package/dist/commands/status.d.ts.map +1 -0
  25. package/dist/commands/status.js +22 -0
  26. package/dist/commands/status.js.map +1 -0
  27. package/dist/config.d.ts +36 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +83 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/index.d.ts +12 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +12 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/ui/renderer.d.ts +85 -0
  36. package/dist/ui/renderer.d.ts.map +1 -0
  37. package/dist/ui/renderer.js +163 -0
  38. package/dist/ui/renderer.js.map +1 -0
  39. package/package.json +47 -0
  40. package/src/bin.ts +50 -0
  41. package/src/chat-session.ts +244 -0
  42. package/src/cli.ts +206 -0
  43. package/src/commands/chat.ts +34 -0
  44. package/src/commands/send.ts +95 -0
  45. package/src/commands/status.ts +32 -0
  46. package/src/config.ts +123 -0
  47. package/src/index.ts +12 -0
  48. package/src/types.d.ts +33 -0
  49. package/src/ui/renderer.ts +194 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Renderer - Terminal output rendering
3
+ */
4
+ export interface RendererOptions {
5
+ /** Enable markdown rendering */
6
+ markdown?: boolean;
7
+ /** Enable debug output */
8
+ debug?: boolean;
9
+ /** Enable colors (default: true) */
10
+ colors?: boolean;
11
+ }
12
+ /**
13
+ * Terminal renderer with markdown support
14
+ */
15
+ export declare class Renderer {
16
+ private options;
17
+ private marked;
18
+ private _isStreaming;
19
+ private streamBuffer;
20
+ private _isDebug;
21
+ constructor(options?: RendererOptions);
22
+ get isDebug(): boolean;
23
+ toggleDebug(): void;
24
+ /**
25
+ * Render markdown text
26
+ */
27
+ markdown(text: string): string;
28
+ /**
29
+ * Print an info message
30
+ */
31
+ info(message: string): void;
32
+ /**
33
+ * Print an error message
34
+ */
35
+ error(message: string): void;
36
+ /**
37
+ * Print a debug message
38
+ */
39
+ debug(message: string, data?: unknown): void;
40
+ /**
41
+ * Start streaming output
42
+ */
43
+ streamStart(): void;
44
+ /**
45
+ * Add delta to stream
46
+ */
47
+ streamDelta(text: string): void;
48
+ /**
49
+ * End streaming and render final output
50
+ */
51
+ streamEnd(): void;
52
+ /**
53
+ * Show tool execution start
54
+ */
55
+ toolStart(name: string, args: Record<string, unknown>): void;
56
+ /**
57
+ * Show tool execution end
58
+ */
59
+ toolEnd(name: string, _result: unknown): void;
60
+ /**
61
+ * Render a complete response (non-streaming)
62
+ */
63
+ response(text: string): void;
64
+ /**
65
+ * Render user input echo
66
+ */
67
+ userInput(text: string): void;
68
+ /**
69
+ * Print a separator line
70
+ */
71
+ separator(): void;
72
+ /**
73
+ * Clear the screen
74
+ */
75
+ clear(): void;
76
+ /**
77
+ * Print JSON output
78
+ */
79
+ json(data: unknown): void;
80
+ /**
81
+ * Print plain text
82
+ */
83
+ plain(text: string): void;
84
+ }
85
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/ui/renderer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,eAAe;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAU;gBAEd,OAAO,GAAE,eAAoB;IA4BzC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAW9B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAS5C;;OAEG;IACH,WAAW,IAAI,IAAI;IAMnB;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM/B;;OAEG;IACH,SAAS,IAAI,IAAI;IAUjB;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM5D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAI7C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI7B;;OAEG;IACH,SAAS,IAAI,IAAI;IAIjB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIzB;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG1B"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Renderer - Terminal output rendering
3
+ */
4
+ import chalk from "chalk";
5
+ import { Marked } from "marked";
6
+ import { markedTerminal } from "marked-terminal";
7
+ /**
8
+ * Terminal renderer with markdown support
9
+ */
10
+ export class Renderer {
11
+ options;
12
+ marked;
13
+ _isStreaming = false;
14
+ streamBuffer = "";
15
+ _isDebug;
16
+ constructor(options = {}) {
17
+ this.options = options;
18
+ this._isDebug = options.debug ?? false;
19
+ // Set up marked with terminal renderer
20
+ this.marked = new Marked();
21
+ this.marked.use(markedTerminal({
22
+ // Customize terminal rendering
23
+ code: chalk.cyan,
24
+ blockquote: chalk.gray.italic,
25
+ html: chalk.gray,
26
+ heading: chalk.bold,
27
+ firstHeading: chalk.bold.underline,
28
+ hr: chalk.gray,
29
+ listitem: chalk.reset,
30
+ table: chalk.reset,
31
+ paragraph: chalk.reset,
32
+ strong: chalk.bold,
33
+ em: chalk.italic,
34
+ codespan: chalk.cyan,
35
+ del: chalk.strikethrough,
36
+ link: chalk.blue.underline,
37
+ href: chalk.blue.underline,
38
+ }));
39
+ }
40
+ get isDebug() {
41
+ return this._isDebug;
42
+ }
43
+ toggleDebug() {
44
+ this._isDebug = !this._isDebug;
45
+ }
46
+ /**
47
+ * Render markdown text
48
+ */
49
+ markdown(text) {
50
+ if (!this.options.markdown) {
51
+ return text;
52
+ }
53
+ try {
54
+ return this.marked.parse(text);
55
+ }
56
+ catch {
57
+ return text;
58
+ }
59
+ }
60
+ /**
61
+ * Print an info message
62
+ */
63
+ info(message) {
64
+ console.log(chalk.gray(message));
65
+ }
66
+ /**
67
+ * Print an error message
68
+ */
69
+ error(message) {
70
+ console.error(chalk.red(`Error: ${message}`));
71
+ }
72
+ /**
73
+ * Print a debug message
74
+ */
75
+ debug(message, data) {
76
+ if (!this._isDebug)
77
+ return;
78
+ if (data !== undefined) {
79
+ console.log(chalk.dim(`[DEBUG] ${message}`), data);
80
+ }
81
+ else {
82
+ console.log(chalk.dim(`[DEBUG] ${message}`));
83
+ }
84
+ }
85
+ /**
86
+ * Start streaming output
87
+ */
88
+ streamStart() {
89
+ this._isStreaming = true;
90
+ this.streamBuffer = "";
91
+ process.stdout.write(chalk.green("\nAgent: "));
92
+ }
93
+ /**
94
+ * Add delta to stream
95
+ */
96
+ streamDelta(text) {
97
+ if (!this._isStreaming)
98
+ return;
99
+ this.streamBuffer += text;
100
+ process.stdout.write(text);
101
+ }
102
+ /**
103
+ * End streaming and render final output
104
+ */
105
+ streamEnd() {
106
+ if (!this._isStreaming)
107
+ return;
108
+ this._isStreaming = false;
109
+ // Move to new line after stream
110
+ console.log("\n");
111
+ this.streamBuffer = "";
112
+ }
113
+ /**
114
+ * Show tool execution start
115
+ */
116
+ toolStart(name, args) {
117
+ const argsStr = Object.keys(args).length > 0 ? ` ${chalk.dim(JSON.stringify(args).slice(0, 50))}...` : "";
118
+ console.log(chalk.yellow(`\n[tool: ${name}]${argsStr}`));
119
+ }
120
+ /**
121
+ * Show tool execution end
122
+ */
123
+ toolEnd(name, _result) {
124
+ this.debug(`Tool ${name} completed`);
125
+ }
126
+ /**
127
+ * Render a complete response (non-streaming)
128
+ */
129
+ response(text) {
130
+ console.log(chalk.green("\nAgent: ") + this.markdown(text) + "\n");
131
+ }
132
+ /**
133
+ * Render user input echo
134
+ */
135
+ userInput(text) {
136
+ console.log(chalk.blue("You: ") + text);
137
+ }
138
+ /**
139
+ * Print a separator line
140
+ */
141
+ separator() {
142
+ console.log(chalk.dim("─".repeat(50)));
143
+ }
144
+ /**
145
+ * Clear the screen
146
+ */
147
+ clear() {
148
+ console.clear();
149
+ }
150
+ /**
151
+ * Print JSON output
152
+ */
153
+ json(data) {
154
+ console.log(JSON.stringify(data, null, 2));
155
+ }
156
+ /**
157
+ * Print plain text
158
+ */
159
+ plain(text) {
160
+ console.log(text);
161
+ }
162
+ }
163
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/ui/renderer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@agentick/cli",
3
+ "version": "0.0.1",
4
+ "description": "Terminal client for Agentick agents",
5
+ "bin": {
6
+ "agentick": "./dist/bin.js"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "src"
11
+ ],
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
+ }
20
+ },
21
+ "dependencies": {
22
+ "chalk": "^5.3.0",
23
+ "commander": "^12.1.0",
24
+ "eventsource": "^2.0.2",
25
+ "marked": "^15.0.4",
26
+ "marked-terminal": "^7.2.1",
27
+ "@agentick/client": "0.0.1",
28
+ "@agentick/shared": "0.0.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/eventsource": "^1.1.15",
32
+ "@types/node": "^22.10.5",
33
+ "tsx": "^4.19.2",
34
+ "typescript": "^5.7.3",
35
+ "vitest": "^3.0.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.build.json",
39
+ "dev": "tsc --watch",
40
+ "typecheck": "tsc --noEmit",
41
+ "clean": "rm -rf dist",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest",
44
+ "start": "tsx src/bin.ts",
45
+ "cli": "tsx src/bin.ts"
46
+ }
47
+ }
package/src/bin.ts ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agentick CLI - Entry point
4
+ */
5
+
6
+ import { program } from "commander";
7
+ import { chatCommand } from "./commands/chat.js";
8
+ import { sendCommand } from "./commands/send.js";
9
+ import { statusCommand } from "./commands/status.js";
10
+
11
+ program.name("agentick").description("Terminal client for Agentick agents").version("0.0.1");
12
+
13
+ // Chat command (interactive)
14
+ program
15
+ .command("chat")
16
+ .description("Interactive chat with a Agentick agent")
17
+ .option("-u, --url <url>", "Server URL (e.g., http://localhost:3000/api/agent)")
18
+ .option("-s, --session <id>", "Session ID")
19
+ .option("-t, --token <token>", "Authentication token")
20
+ .option("--no-stream", "Disable streaming (wait for complete response)")
21
+ .option("--debug", "Enable debug mode")
22
+ .action(chatCommand);
23
+
24
+ // Send command (non-interactive)
25
+ program
26
+ .command("send <message>")
27
+ .description("Send a single message and print the response")
28
+ .option("-u, --url <url>", "Server URL")
29
+ .option("-s, --session <id>", "Session ID")
30
+ .option("-t, --token <token>", "Authentication token")
31
+ .option("--stdin", "Read additional context from stdin")
32
+ .option("-f, --format <format>", "Output format: plain, json, markdown", "plain")
33
+ .option("--no-stream", "Disable streaming")
34
+ .action(sendCommand);
35
+
36
+ // Status command
37
+ program
38
+ .command("status")
39
+ .description("Show server and session status")
40
+ .option("-u, --url <url>", "Server URL")
41
+ .option("-s, --session <id>", "Session ID")
42
+ .option("-t, --token <token>", "Authentication token")
43
+ .action(statusCommand);
44
+
45
+ // Default to chat if no command specified
46
+ program.action(() => {
47
+ program.help();
48
+ });
49
+
50
+ program.parse();
@@ -0,0 +1,244 @@
1
+ /**
2
+ * ChatSession - Interactive chat session
3
+ */
4
+
5
+ import * as readline from "readline";
6
+ import { CLI, type CLIConfig } from "./cli.js";
7
+ import { Renderer } from "./ui/renderer.js";
8
+
9
+ export interface ChatSessionOptions extends CLIConfig {
10
+ /** Custom prompt (default: "You: ") */
11
+ prompt?: string;
12
+
13
+ /** Enable markdown rendering (default: true) */
14
+ markdown?: boolean;
15
+ }
16
+
17
+ interface SlashCommand {
18
+ name: string;
19
+ aliases?: string[];
20
+ description: string;
21
+ handler: (args: string[]) => Promise<boolean> | boolean; // Return true to continue, false to exit
22
+ }
23
+
24
+ /**
25
+ * Interactive chat session
26
+ */
27
+ export class ChatSession {
28
+ private cli: CLI;
29
+ private renderer: Renderer;
30
+ private options: ChatSessionOptions;
31
+ private rl?: readline.Interface;
32
+ private isRunning = false;
33
+ private commands: Map<string, SlashCommand> = new Map();
34
+
35
+ constructor(options: ChatSessionOptions) {
36
+ this.options = options;
37
+ this.cli = new CLI(options);
38
+ this.renderer = new Renderer({
39
+ markdown: options.markdown ?? true,
40
+ debug: options.debug,
41
+ });
42
+
43
+ this.setupCommands();
44
+ this.setupEventHandlers();
45
+ }
46
+
47
+ private setupCommands(): void {
48
+ const commands: SlashCommand[] = [
49
+ {
50
+ name: "help",
51
+ aliases: ["h", "?"],
52
+ description: "Show available commands",
53
+ handler: () => {
54
+ this.showHelp();
55
+ return true;
56
+ },
57
+ },
58
+ {
59
+ name: "quit",
60
+ aliases: ["exit", "q"],
61
+ description: "Exit the chat",
62
+ handler: () => false,
63
+ },
64
+ {
65
+ name: "status",
66
+ description: "Show session status",
67
+ handler: () => {
68
+ this.showStatus();
69
+ return true;
70
+ },
71
+ },
72
+ {
73
+ name: "clear",
74
+ aliases: ["cls"],
75
+ description: "Clear the screen",
76
+ handler: () => {
77
+ console.clear();
78
+ return true;
79
+ },
80
+ },
81
+ {
82
+ name: "debug",
83
+ description: "Toggle debug mode",
84
+ handler: () => {
85
+ this.renderer.toggleDebug();
86
+ this.renderer.info(`Debug mode: ${this.renderer.isDebug ? "on" : "off"}`);
87
+ return true;
88
+ },
89
+ },
90
+ ];
91
+
92
+ for (const cmd of commands) {
93
+ this.commands.set(cmd.name, cmd);
94
+ if (cmd.aliases) {
95
+ for (const alias of cmd.aliases) {
96
+ this.commands.set(alias, cmd);
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ private setupEventHandlers(): void {
103
+ this.cli.on("stream:delta", ({ text }) => {
104
+ this.renderer.streamDelta(text);
105
+ });
106
+
107
+ this.cli.on("stream:start", () => {
108
+ this.renderer.streamStart();
109
+ });
110
+
111
+ this.cli.on("stream:end", () => {
112
+ this.renderer.streamEnd();
113
+ });
114
+
115
+ this.cli.on("tool:start", ({ name, args }) => {
116
+ this.renderer.toolStart(name, args);
117
+ });
118
+
119
+ this.cli.on("tool:end", ({ name, result }) => {
120
+ this.renderer.toolEnd(name, result);
121
+ });
122
+
123
+ this.cli.on("error", (error) => {
124
+ this.renderer.error(error.message);
125
+ });
126
+ }
127
+
128
+ private showHelp(): void {
129
+ const uniqueCommands = new Map<string, SlashCommand>();
130
+ for (const [name, cmd] of this.commands) {
131
+ if (!uniqueCommands.has(cmd.name)) {
132
+ uniqueCommands.set(cmd.name, cmd);
133
+ }
134
+ }
135
+
136
+ this.renderer.info("\nAvailable commands:");
137
+ for (const [name, cmd] of uniqueCommands) {
138
+ const aliases = cmd.aliases?.length ? ` (${cmd.aliases.join(", ")})` : "";
139
+ this.renderer.info(` /${name}${aliases} - ${cmd.description}`);
140
+ }
141
+ console.log();
142
+ }
143
+
144
+ private showStatus(): void {
145
+ const sessionId = this.cli.sessionId ?? "not connected";
146
+ const connected = this.cli.isConnected ? "yes" : "no";
147
+
148
+ this.renderer.info("\nSession Status:");
149
+ this.renderer.info(` Session ID: ${sessionId}`);
150
+ this.renderer.info(` Connected: ${connected}`);
151
+ this.renderer.info(` URL: ${this.options.url}`);
152
+ console.log();
153
+ }
154
+
155
+ private async handleCommand(input: string): Promise<boolean> {
156
+ const [cmdName, ...args] = input.slice(1).split(/\s+/);
157
+ const cmd = this.commands.get(cmdName.toLowerCase());
158
+
159
+ if (!cmd) {
160
+ this.renderer.error(`Unknown command: /${cmdName}. Type /help for available commands.`);
161
+ return true;
162
+ }
163
+
164
+ return cmd.handler(args);
165
+ }
166
+
167
+ private async handleMessage(message: string): Promise<void> {
168
+ try {
169
+ await this.cli.send(message);
170
+ } catch (error) {
171
+ this.renderer.error(error instanceof Error ? error.message : String(error));
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Start the interactive session
177
+ */
178
+ async start(): Promise<void> {
179
+ if (this.isRunning) return;
180
+ this.isRunning = true;
181
+
182
+ this.rl = readline.createInterface({
183
+ input: process.stdin,
184
+ output: process.stdout,
185
+ });
186
+
187
+ // Print welcome message
188
+ this.renderer.info(`Connected to ${this.options.url}`);
189
+ if (this.cli.sessionId) {
190
+ this.renderer.info(`Session: ${this.cli.sessionId}`);
191
+ }
192
+ this.renderer.info("Type /help for commands, /quit to exit\n");
193
+
194
+ const prompt = this.options.prompt ?? "You: ";
195
+
196
+ const promptForInput = (): void => {
197
+ if (!this.isRunning) return;
198
+
199
+ this.rl!.question(prompt, async (input) => {
200
+ const trimmed = input.trim();
201
+
202
+ if (!trimmed) {
203
+ promptForInput();
204
+ return;
205
+ }
206
+
207
+ // Handle commands
208
+ if (trimmed.startsWith("/")) {
209
+ const shouldContinue = await this.handleCommand(trimmed);
210
+ if (!shouldContinue) {
211
+ this.stop();
212
+ return;
213
+ }
214
+ promptForInput();
215
+ return;
216
+ }
217
+
218
+ // Handle regular message
219
+ await this.handleMessage(trimmed);
220
+ promptForInput();
221
+ });
222
+ };
223
+
224
+ // Handle Ctrl+C
225
+ this.rl.on("close", () => {
226
+ this.stop();
227
+ });
228
+
229
+ promptForInput();
230
+ }
231
+
232
+ /**
233
+ * Stop the session
234
+ */
235
+ stop(): void {
236
+ if (!this.isRunning) return;
237
+ this.isRunning = false;
238
+
239
+ this.renderer.info("\nGoodbye!");
240
+ this.rl?.close();
241
+ this.cli.destroy();
242
+ process.exit(0);
243
+ }
244
+ }