@mariozechner/pi-coding-agent 0.6.2

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 (78) hide show
  1. package/README.md +485 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +21 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/export-html.d.ts +7 -0
  7. package/dist/export-html.d.ts.map +1 -0
  8. package/dist/export-html.js +650 -0
  9. package/dist/export-html.js.map +1 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/main.d.ts +2 -0
  15. package/dist/main.d.ts.map +1 -0
  16. package/dist/main.js +514 -0
  17. package/dist/main.js.map +1 -0
  18. package/dist/session-manager.d.ts +70 -0
  19. package/dist/session-manager.d.ts.map +1 -0
  20. package/dist/session-manager.js +323 -0
  21. package/dist/session-manager.js.map +1 -0
  22. package/dist/tools/bash.d.ts +7 -0
  23. package/dist/tools/bash.d.ts.map +1 -0
  24. package/dist/tools/bash.js +130 -0
  25. package/dist/tools/bash.js.map +1 -0
  26. package/dist/tools/edit.d.ts +9 -0
  27. package/dist/tools/edit.d.ts.map +1 -0
  28. package/dist/tools/edit.js +207 -0
  29. package/dist/tools/edit.js.map +1 -0
  30. package/dist/tools/index.d.ts +19 -0
  31. package/dist/tools/index.d.ts.map +1 -0
  32. package/dist/tools/index.js +10 -0
  33. package/dist/tools/index.js.map +1 -0
  34. package/dist/tools/read.d.ts +9 -0
  35. package/dist/tools/read.d.ts.map +1 -0
  36. package/dist/tools/read.js +165 -0
  37. package/dist/tools/read.js.map +1 -0
  38. package/dist/tools/write.d.ts +8 -0
  39. package/dist/tools/write.d.ts.map +1 -0
  40. package/dist/tools/write.js +81 -0
  41. package/dist/tools/write.js.map +1 -0
  42. package/dist/tui/assistant-message.d.ts +11 -0
  43. package/dist/tui/assistant-message.d.ts.map +1 -0
  44. package/dist/tui/assistant-message.js +53 -0
  45. package/dist/tui/assistant-message.js.map +1 -0
  46. package/dist/tui/custom-editor.d.ts +10 -0
  47. package/dist/tui/custom-editor.d.ts.map +1 -0
  48. package/dist/tui/custom-editor.js +24 -0
  49. package/dist/tui/custom-editor.js.map +1 -0
  50. package/dist/tui/footer.d.ts +11 -0
  51. package/dist/tui/footer.d.ts.map +1 -0
  52. package/dist/tui/footer.js +101 -0
  53. package/dist/tui/footer.js.map +1 -0
  54. package/dist/tui/model-selector.d.ts +23 -0
  55. package/dist/tui/model-selector.d.ts.map +1 -0
  56. package/dist/tui/model-selector.js +157 -0
  57. package/dist/tui/model-selector.js.map +1 -0
  58. package/dist/tui/session-selector.d.ts +37 -0
  59. package/dist/tui/session-selector.d.ts.map +1 -0
  60. package/dist/tui/session-selector.js +176 -0
  61. package/dist/tui/session-selector.js.map +1 -0
  62. package/dist/tui/thinking-selector.d.ts +11 -0
  63. package/dist/tui/thinking-selector.d.ts.map +1 -0
  64. package/dist/tui/thinking-selector.js +48 -0
  65. package/dist/tui/thinking-selector.js.map +1 -0
  66. package/dist/tui/tool-execution.d.ts +26 -0
  67. package/dist/tui/tool-execution.d.ts.map +1 -0
  68. package/dist/tui/tool-execution.js +246 -0
  69. package/dist/tui/tool-execution.js.map +1 -0
  70. package/dist/tui/tui-renderer.d.ts +44 -0
  71. package/dist/tui/tui-renderer.d.ts.map +1 -0
  72. package/dist/tui/tui-renderer.js +539 -0
  73. package/dist/tui/tui-renderer.js.map +1 -0
  74. package/dist/tui/user-message.d.ts +9 -0
  75. package/dist/tui/user-message.d.ts.map +1 -0
  76. package/dist/tui/user-message.js +18 -0
  77. package/dist/tui/user-message.js.map +1 -0
  78. package/package.json +53 -0
package/dist/main.js ADDED
@@ -0,0 +1,514 @@
1
+ import { Agent, ProviderTransport } from "@mariozechner/pi-agent";
2
+ import { getModel } from "@mariozechner/pi-ai";
3
+ import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
4
+ import chalk from "chalk";
5
+ import { existsSync, readFileSync } from "fs";
6
+ import { homedir } from "os";
7
+ import { dirname, join, resolve } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import { SessionManager } from "./session-manager.js";
10
+ import { codingTools } from "./tools/index.js";
11
+ import { SessionSelectorComponent } from "./tui/session-selector.js";
12
+ import { TuiRenderer } from "./tui/tui-renderer.js";
13
+ // Get version from package.json
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
17
+ const VERSION = packageJson.version;
18
+ const envApiKeyMap = {
19
+ google: ["GEMINI_API_KEY"],
20
+ openai: ["OPENAI_API_KEY"],
21
+ anthropic: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"],
22
+ xai: ["XAI_API_KEY"],
23
+ groq: ["GROQ_API_KEY"],
24
+ cerebras: ["CEREBRAS_API_KEY"],
25
+ openrouter: ["OPENROUTER_API_KEY"],
26
+ zai: ["ZAI_API_KEY"],
27
+ };
28
+ function parseArgs(args) {
29
+ const result = {
30
+ messages: [],
31
+ };
32
+ for (let i = 0; i < args.length; i++) {
33
+ const arg = args[i];
34
+ if (arg === "--help" || arg === "-h") {
35
+ result.help = true;
36
+ }
37
+ else if (arg === "--mode" && i + 1 < args.length) {
38
+ const mode = args[++i];
39
+ if (mode === "text" || mode === "json" || mode === "rpc") {
40
+ result.mode = mode;
41
+ }
42
+ }
43
+ else if (arg === "--continue" || arg === "-c") {
44
+ result.continue = true;
45
+ }
46
+ else if (arg === "--resume" || arg === "-r") {
47
+ result.resume = true;
48
+ }
49
+ else if (arg === "--provider" && i + 1 < args.length) {
50
+ result.provider = args[++i];
51
+ }
52
+ else if (arg === "--model" && i + 1 < args.length) {
53
+ result.model = args[++i];
54
+ }
55
+ else if (arg === "--api-key" && i + 1 < args.length) {
56
+ result.apiKey = args[++i];
57
+ }
58
+ else if (arg === "--system-prompt" && i + 1 < args.length) {
59
+ result.systemPrompt = args[++i];
60
+ }
61
+ else if (arg === "--no-session") {
62
+ result.noSession = true;
63
+ }
64
+ else if (arg === "--session" && i + 1 < args.length) {
65
+ result.session = args[++i];
66
+ }
67
+ else if (!arg.startsWith("-")) {
68
+ result.messages.push(arg);
69
+ }
70
+ }
71
+ return result;
72
+ }
73
+ function printHelp() {
74
+ console.log(`${chalk.bold("coding-agent")} - AI coding assistant with read, bash, edit, write tools
75
+
76
+ ${chalk.bold("Usage:")}
77
+ coding-agent [options] [messages...]
78
+
79
+ ${chalk.bold("Options:")}
80
+ --provider <name> Provider name (default: google)
81
+ --model <id> Model ID (default: gemini-2.5-flash)
82
+ --api-key <key> API key (defaults to env vars)
83
+ --system-prompt <text> System prompt (default: coding assistant prompt)
84
+ --mode <mode> Output mode: text (default), json, or rpc
85
+ --continue, -c Continue previous session
86
+ --resume, -r Select a session to resume
87
+ --session <path> Use specific session file
88
+ --no-session Don't save session (ephemeral)
89
+ --help, -h Show this help
90
+
91
+ ${chalk.bold("Examples:")}
92
+ # Interactive mode (no messages = interactive TUI)
93
+ coding-agent
94
+
95
+ # Single message
96
+ coding-agent "List all .ts files in src/"
97
+
98
+ # Multiple messages
99
+ coding-agent "Read package.json" "What dependencies do we have?"
100
+
101
+ # Continue previous session
102
+ coding-agent --continue "What did we discuss?"
103
+
104
+ # Use different model
105
+ coding-agent --provider openai --model gpt-4o-mini "Help me refactor this code"
106
+
107
+ ${chalk.bold("Environment Variables:")}
108
+ GEMINI_API_KEY - Google Gemini API key
109
+ OPENAI_API_KEY - OpenAI API key
110
+ ANTHROPIC_API_KEY - Anthropic API key
111
+ CODING_AGENT_DIR - Session storage directory (default: ~/.coding-agent)
112
+
113
+ ${chalk.bold("Available Tools:")}
114
+ read - Read file contents
115
+ bash - Execute bash commands
116
+ edit - Edit files with find/replace
117
+ write - Write files (creates/overwrites)
118
+ `);
119
+ }
120
+ function buildSystemPrompt(customPrompt) {
121
+ // Check if customPrompt is a file path that exists
122
+ if (customPrompt && existsSync(customPrompt)) {
123
+ try {
124
+ customPrompt = readFileSync(customPrompt, "utf-8");
125
+ }
126
+ catch (error) {
127
+ console.error(chalk.yellow(`Warning: Could not read system prompt file ${customPrompt}: ${error}`));
128
+ // Fall through to use as literal string
129
+ }
130
+ }
131
+ if (customPrompt) {
132
+ // Use custom prompt as base, then add context/datetime
133
+ const now = new Date();
134
+ const dateTime = now.toLocaleString("en-US", {
135
+ weekday: "long",
136
+ year: "numeric",
137
+ month: "long",
138
+ day: "numeric",
139
+ hour: "2-digit",
140
+ minute: "2-digit",
141
+ second: "2-digit",
142
+ timeZoneName: "short",
143
+ });
144
+ let prompt = customPrompt;
145
+ // Append project context files
146
+ const contextFiles = loadProjectContextFiles();
147
+ if (contextFiles.length > 0) {
148
+ prompt += "\n\n# Project Context\n\n";
149
+ prompt += "The following project context files have been loaded:\n\n";
150
+ for (const { path: filePath, content } of contextFiles) {
151
+ prompt += `## ${filePath}\n\n${content}\n\n`;
152
+ }
153
+ }
154
+ // Add date/time and working directory last
155
+ prompt += `\nCurrent date and time: ${dateTime}`;
156
+ prompt += `\nCurrent working directory: ${process.cwd()}`;
157
+ return prompt;
158
+ }
159
+ const now = new Date();
160
+ const dateTime = now.toLocaleString("en-US", {
161
+ weekday: "long",
162
+ year: "numeric",
163
+ month: "long",
164
+ day: "numeric",
165
+ hour: "2-digit",
166
+ minute: "2-digit",
167
+ second: "2-digit",
168
+ timeZoneName: "short",
169
+ });
170
+ let prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.
171
+
172
+ Available tools:
173
+ - read: Read file contents
174
+ - bash: Execute bash commands (ls, grep, find, etc.)
175
+ - edit: Make surgical edits to files (find exact text and replace)
176
+ - write: Create or overwrite files
177
+
178
+ Guidelines:
179
+ - Always use bash tool for file operations like ls, grep, find
180
+ - Use read to examine files before editing
181
+ - Use edit for precise changes (old text must match exactly)
182
+ - Use write only for new files or complete rewrites
183
+ - Be concise in your responses
184
+ - Show file paths clearly when working with files`;
185
+ // Append project context files
186
+ const contextFiles = loadProjectContextFiles();
187
+ if (contextFiles.length > 0) {
188
+ prompt += "\n\n# Project Context\n\n";
189
+ prompt += "The following project context files have been loaded:\n\n";
190
+ for (const { path: filePath, content } of contextFiles) {
191
+ prompt += `## ${filePath}\n\n${content}\n\n`;
192
+ }
193
+ }
194
+ // Add date/time and working directory last
195
+ prompt += `\nCurrent date and time: ${dateTime}`;
196
+ prompt += `\nCurrent working directory: ${process.cwd()}`;
197
+ return prompt;
198
+ }
199
+ /**
200
+ * Look for AGENT.md or CLAUDE.md in a directory (prefers AGENT.md)
201
+ */
202
+ function loadContextFileFromDir(dir) {
203
+ const candidates = ["AGENT.md", "CLAUDE.md"];
204
+ for (const filename of candidates) {
205
+ const filePath = join(dir, filename);
206
+ if (existsSync(filePath)) {
207
+ try {
208
+ return {
209
+ path: filePath,
210
+ content: readFileSync(filePath, "utf-8"),
211
+ };
212
+ }
213
+ catch (error) {
214
+ console.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));
215
+ }
216
+ }
217
+ }
218
+ return null;
219
+ }
220
+ /**
221
+ * Load all project context files in order:
222
+ * 1. Global: ~/.pi/agent/AGENT.md or CLAUDE.md
223
+ * 2. Parent directories (top-most first) down to cwd
224
+ * Each returns {path, content} for separate messages
225
+ */
226
+ function loadProjectContextFiles() {
227
+ const contextFiles = [];
228
+ // 1. Load global context from ~/.pi/agent/
229
+ const homeDir = homedir();
230
+ const globalContextDir = resolve(process.env.CODING_AGENT_DIR || join(homeDir, ".pi/agent/"));
231
+ const globalContext = loadContextFileFromDir(globalContextDir);
232
+ if (globalContext) {
233
+ contextFiles.push(globalContext);
234
+ }
235
+ // 2. Walk up from cwd to root, collecting all context files
236
+ const cwd = process.cwd();
237
+ const ancestorContextFiles = [];
238
+ let currentDir = cwd;
239
+ const root = resolve("/");
240
+ while (true) {
241
+ const contextFile = loadContextFileFromDir(currentDir);
242
+ if (contextFile) {
243
+ // Add to beginning so we get top-most parent first
244
+ ancestorContextFiles.unshift(contextFile);
245
+ }
246
+ // Stop if we've reached root
247
+ if (currentDir === root)
248
+ break;
249
+ // Move up one directory
250
+ const parentDir = resolve(currentDir, "..");
251
+ if (parentDir === currentDir)
252
+ break; // Safety check
253
+ currentDir = parentDir;
254
+ }
255
+ // Add ancestor files in order (top-most → cwd)
256
+ contextFiles.push(...ancestorContextFiles);
257
+ return contextFiles;
258
+ }
259
+ async function selectSession(sessionManager) {
260
+ return new Promise((resolve) => {
261
+ const ui = new TUI(new ProcessTerminal());
262
+ let resolved = false;
263
+ const selector = new SessionSelectorComponent(sessionManager, (path) => {
264
+ if (!resolved) {
265
+ resolved = true;
266
+ ui.stop();
267
+ resolve(path);
268
+ }
269
+ }, () => {
270
+ if (!resolved) {
271
+ resolved = true;
272
+ ui.stop();
273
+ resolve(null);
274
+ }
275
+ });
276
+ ui.addChild(selector);
277
+ ui.setFocus(selector.getSessionList());
278
+ ui.start();
279
+ });
280
+ }
281
+ async function runInteractiveMode(agent, sessionManager, version) {
282
+ const renderer = new TuiRenderer(agent, sessionManager, version);
283
+ // Initialize TUI
284
+ await renderer.init();
285
+ // Set interrupt callback
286
+ renderer.setInterruptCallback(() => {
287
+ agent.abort();
288
+ });
289
+ // Render any existing messages (from --continue mode)
290
+ renderer.renderInitialMessages(agent.state);
291
+ // Subscribe to agent events
292
+ agent.subscribe(async (event) => {
293
+ // Pass all events to the renderer
294
+ await renderer.handleEvent(event, agent.state);
295
+ });
296
+ // Interactive loop
297
+ while (true) {
298
+ const userInput = await renderer.getUserInput();
299
+ // Process the message - agent.prompt will add user message and trigger state updates
300
+ try {
301
+ await agent.prompt(userInput);
302
+ }
303
+ catch (error) {
304
+ // Display error in the TUI by adding an error message to the chat
305
+ renderer.showError(error.message || "Unknown error occurred");
306
+ }
307
+ }
308
+ }
309
+ async function runSingleShotMode(agent, _sessionManager, messages, mode) {
310
+ if (mode === "json") {
311
+ // Subscribe to all events and output as JSON
312
+ agent.subscribe((event) => {
313
+ // Output event as JSON (same format as session manager)
314
+ console.log(JSON.stringify(event));
315
+ });
316
+ }
317
+ for (const message of messages) {
318
+ await agent.prompt(message);
319
+ }
320
+ // In text mode, only output the final assistant message
321
+ if (mode === "text") {
322
+ const lastMessage = agent.state.messages[agent.state.messages.length - 1];
323
+ if (lastMessage.role === "assistant") {
324
+ for (const content of lastMessage.content) {
325
+ if (content.type === "text") {
326
+ console.log(content.text);
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ async function runRpcMode(agent, _sessionManager) {
333
+ // Subscribe to all events and output as JSON
334
+ agent.subscribe((event) => {
335
+ console.log(JSON.stringify(event));
336
+ });
337
+ // Listen for JSON input on stdin
338
+ const readline = await import("readline");
339
+ const rl = readline.createInterface({
340
+ input: process.stdin,
341
+ output: process.stdout,
342
+ terminal: false,
343
+ });
344
+ rl.on("line", async (line) => {
345
+ try {
346
+ const input = JSON.parse(line);
347
+ // Handle different RPC commands
348
+ if (input.type === "prompt" && input.message) {
349
+ await agent.prompt(input.message);
350
+ }
351
+ else if (input.type === "abort") {
352
+ agent.abort();
353
+ }
354
+ }
355
+ catch (error) {
356
+ // Output error as JSON
357
+ console.log(JSON.stringify({ type: "error", error: error.message }));
358
+ }
359
+ });
360
+ // Keep process alive
361
+ return new Promise(() => { });
362
+ }
363
+ export async function main(args) {
364
+ const parsed = parseArgs(args);
365
+ if (parsed.help) {
366
+ printHelp();
367
+ return;
368
+ }
369
+ // Setup session manager
370
+ const sessionManager = new SessionManager(parsed.continue && !parsed.resume, parsed.session);
371
+ // Disable session saving if --no-session flag is set
372
+ if (parsed.noSession) {
373
+ sessionManager.disable();
374
+ }
375
+ // Handle --resume flag: show session selector
376
+ if (parsed.resume) {
377
+ const selectedSession = await selectSession(sessionManager);
378
+ if (!selectedSession) {
379
+ console.log(chalk.dim("No session selected"));
380
+ return;
381
+ }
382
+ // Set the selected session as the active session
383
+ sessionManager.setSessionFile(selectedSession);
384
+ }
385
+ // Determine provider and model
386
+ const provider = (parsed.provider || "anthropic");
387
+ const modelId = parsed.model || "claude-sonnet-4-5";
388
+ // Helper function to get API key for a provider
389
+ const getApiKeyForProvider = (providerName) => {
390
+ // Check if API key was provided via command line
391
+ if (parsed.apiKey) {
392
+ return parsed.apiKey;
393
+ }
394
+ const envVars = envApiKeyMap[providerName];
395
+ // Check each environment variable in priority order
396
+ for (const envVar of envVars) {
397
+ const key = process.env[envVar];
398
+ if (key) {
399
+ return key;
400
+ }
401
+ }
402
+ return undefined;
403
+ };
404
+ // Get initial API key
405
+ const initialApiKey = getApiKeyForProvider(provider);
406
+ if (!initialApiKey) {
407
+ const envVars = envApiKeyMap[provider];
408
+ const envVarList = envVars.join(" or ");
409
+ console.error(chalk.red(`Error: No API key found for provider "${provider}"`));
410
+ console.error(chalk.dim(`Set ${envVarList} environment variable or use --api-key flag`));
411
+ process.exit(1);
412
+ }
413
+ // Create agent
414
+ const model = getModel(provider, modelId);
415
+ const systemPrompt = buildSystemPrompt(parsed.systemPrompt);
416
+ const agent = new Agent({
417
+ initialState: {
418
+ systemPrompt,
419
+ model,
420
+ thinkingLevel: "off",
421
+ tools: codingTools,
422
+ },
423
+ transport: new ProviderTransport({
424
+ // Dynamic API key lookup based on current model's provider
425
+ getApiKey: async () => {
426
+ const currentProvider = agent.state.model.provider;
427
+ const key = getApiKeyForProvider(currentProvider);
428
+ if (!key) {
429
+ throw new Error(`No API key found for provider "${currentProvider}". Please set the appropriate environment variable.`);
430
+ }
431
+ return key;
432
+ },
433
+ }),
434
+ });
435
+ // Determine mode early to know if we should print messages
436
+ const isInteractive = parsed.messages.length === 0;
437
+ const mode = parsed.mode || "text";
438
+ const shouldPrintMessages = isInteractive || mode === "text";
439
+ // Load previous messages if continuing or resuming
440
+ if (parsed.continue || parsed.resume) {
441
+ const messages = sessionManager.loadMessages();
442
+ if (messages.length > 0) {
443
+ if (shouldPrintMessages) {
444
+ console.log(chalk.dim(`Loaded ${messages.length} messages from previous session`));
445
+ }
446
+ agent.replaceMessages(messages);
447
+ }
448
+ // Load and restore model
449
+ const savedModel = sessionManager.loadModel();
450
+ if (savedModel) {
451
+ // Parse provider/modelId from saved model string (format: "provider/modelId")
452
+ const [savedProvider, savedModelId] = savedModel.split("/");
453
+ if (savedProvider && savedModelId) {
454
+ try {
455
+ const restoredModel = getModel(savedProvider, savedModelId);
456
+ agent.setModel(restoredModel);
457
+ if (shouldPrintMessages) {
458
+ console.log(chalk.dim(`Restored model: ${savedModel}`));
459
+ }
460
+ }
461
+ catch (error) {
462
+ if (shouldPrintMessages) {
463
+ console.error(chalk.yellow(`Warning: Could not restore model ${savedModel}: ${error.message}`));
464
+ }
465
+ }
466
+ }
467
+ }
468
+ // Load and restore thinking level
469
+ const thinkingLevel = sessionManager.loadThinkingLevel();
470
+ if (thinkingLevel) {
471
+ agent.setThinkingLevel(thinkingLevel);
472
+ if (shouldPrintMessages) {
473
+ console.log(chalk.dim(`Restored thinking level: ${thinkingLevel}`));
474
+ }
475
+ }
476
+ }
477
+ // Note: Session will be started lazily after first user+assistant message exchange
478
+ // (unless continuing/resuming, in which case it's already initialized)
479
+ // Log loaded context files (they're already in the system prompt)
480
+ if (shouldPrintMessages && !parsed.continue && !parsed.resume) {
481
+ const contextFiles = loadProjectContextFiles();
482
+ if (contextFiles.length > 0) {
483
+ console.log(chalk.dim("Loaded project context from:"));
484
+ for (const { path: filePath } of contextFiles) {
485
+ console.log(chalk.dim(` - ${filePath}`));
486
+ }
487
+ }
488
+ }
489
+ // Subscribe to agent events to save messages
490
+ agent.subscribe((event) => {
491
+ // Save messages on completion
492
+ if (event.type === "message_end") {
493
+ sessionManager.saveMessage(event.message);
494
+ // Check if we should initialize session now (after first user+assistant exchange)
495
+ if (sessionManager.shouldInitializeSession(agent.state.messages)) {
496
+ sessionManager.startSession(agent.state);
497
+ }
498
+ }
499
+ });
500
+ // Route to appropriate mode
501
+ if (mode === "rpc") {
502
+ // RPC mode - headless operation
503
+ await runRpcMode(agent, sessionManager);
504
+ }
505
+ else if (isInteractive) {
506
+ // No messages and not RPC - use TUI
507
+ await runInteractiveMode(agent, sessionManager, VERSION);
508
+ }
509
+ else {
510
+ // CLI mode with messages
511
+ await runSingleShotMode(agent, sessionManager, parsed.messages, mode);
512
+ }
513
+ }
514
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { Agent, ProviderTransport, type ThinkingLevel } from \"@mariozechner/pi-agent\";\nimport { getModel, type KnownProvider } from \"@mariozechner/pi-ai\";\nimport { ProcessTerminal, TUI } from \"@mariozechner/pi-tui\";\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, resolve } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { codingTools } from \"./tools/index.js\";\nimport { SessionSelectorComponent } from \"./tui/session-selector.js\";\nimport { TuiRenderer } from \"./tui/tui-renderer.js\";\n\n// Get version from package.json\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(readFileSync(join(__dirname, \"../package.json\"), \"utf-8\"));\nconst VERSION = packageJson.version;\n\nconst envApiKeyMap: Record<KnownProvider, string[]> = {\n\tgoogle: [\"GEMINI_API_KEY\"],\n\topenai: [\"OPENAI_API_KEY\"],\n\tanthropic: [\"ANTHROPIC_OAUTH_TOKEN\", \"ANTHROPIC_API_KEY\"],\n\txai: [\"XAI_API_KEY\"],\n\tgroq: [\"GROQ_API_KEY\"],\n\tcerebras: [\"CEREBRAS_API_KEY\"],\n\topenrouter: [\"OPENROUTER_API_KEY\"],\n\tzai: [\"ZAI_API_KEY\"],\n};\n\ntype Mode = \"text\" | \"json\" | \"rpc\";\n\ninterface Args {\n\tprovider?: string;\n\tmodel?: string;\n\tapiKey?: string;\n\tsystemPrompt?: string;\n\tcontinue?: boolean;\n\tresume?: boolean;\n\thelp?: boolean;\n\tmode?: Mode;\n\tnoSession?: boolean;\n\tsession?: string;\n\tmessages: string[];\n}\n\nfunction parseArgs(args: string[]): Args {\n\tconst result: Args = {\n\t\tmessages: [],\n\t};\n\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\tresult.help = true;\n\t\t} else if (arg === \"--mode\" && i + 1 < args.length) {\n\t\t\tconst mode = args[++i];\n\t\t\tif (mode === \"text\" || mode === \"json\" || mode === \"rpc\") {\n\t\t\t\tresult.mode = mode;\n\t\t\t}\n\t\t} else if (arg === \"--continue\" || arg === \"-c\") {\n\t\t\tresult.continue = true;\n\t\t} else if (arg === \"--resume\" || arg === \"-r\") {\n\t\t\tresult.resume = true;\n\t\t} else if (arg === \"--provider\" && i + 1 < args.length) {\n\t\t\tresult.provider = args[++i];\n\t\t} else if (arg === \"--model\" && i + 1 < args.length) {\n\t\t\tresult.model = args[++i];\n\t\t} else if (arg === \"--api-key\" && i + 1 < args.length) {\n\t\t\tresult.apiKey = args[++i];\n\t\t} else if (arg === \"--system-prompt\" && i + 1 < args.length) {\n\t\t\tresult.systemPrompt = args[++i];\n\t\t} else if (arg === \"--no-session\") {\n\t\t\tresult.noSession = true;\n\t\t} else if (arg === \"--session\" && i + 1 < args.length) {\n\t\t\tresult.session = args[++i];\n\t\t} else if (!arg.startsWith(\"-\")) {\n\t\t\tresult.messages.push(arg);\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction printHelp() {\n\tconsole.log(`${chalk.bold(\"coding-agent\")} - AI coding assistant with read, bash, edit, write tools\n\n${chalk.bold(\"Usage:\")}\n coding-agent [options] [messages...]\n\n${chalk.bold(\"Options:\")}\n --provider <name> Provider name (default: google)\n --model <id> Model ID (default: gemini-2.5-flash)\n --api-key <key> API key (defaults to env vars)\n --system-prompt <text> System prompt (default: coding assistant prompt)\n --mode <mode> Output mode: text (default), json, or rpc\n --continue, -c Continue previous session\n --resume, -r Select a session to resume\n --session <path> Use specific session file\n --no-session Don't save session (ephemeral)\n --help, -h Show this help\n\n${chalk.bold(\"Examples:\")}\n # Interactive mode (no messages = interactive TUI)\n coding-agent\n\n # Single message\n coding-agent \"List all .ts files in src/\"\n\n # Multiple messages\n coding-agent \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n coding-agent --continue \"What did we discuss?\"\n\n # Use different model\n coding-agent --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n${chalk.bold(\"Environment Variables:\")}\n GEMINI_API_KEY - Google Gemini API key\n OPENAI_API_KEY - OpenAI API key\n ANTHROPIC_API_KEY - Anthropic API key\n CODING_AGENT_DIR - Session storage directory (default: ~/.coding-agent)\n\n${chalk.bold(\"Available Tools:\")}\n read - Read file contents\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n`);\n}\n\nfunction buildSystemPrompt(customPrompt?: string): string {\n\t// Check if customPrompt is a file path that exists\n\tif (customPrompt && existsSync(customPrompt)) {\n\t\ttry {\n\t\t\tcustomPrompt = readFileSync(customPrompt, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.yellow(`Warning: Could not read system prompt file ${customPrompt}: ${error}`));\n\t\t\t// Fall through to use as literal string\n\t\t}\n\t}\n\n\tif (customPrompt) {\n\t\t// Use custom prompt as base, then add context/datetime\n\t\tconst now = new Date();\n\t\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\t\tweekday: \"long\",\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"long\",\n\t\t\tday: \"numeric\",\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t\tsecond: \"2-digit\",\n\t\t\ttimeZoneName: \"short\",\n\t\t});\n\n\t\tlet prompt = customPrompt;\n\n\t\t// Append project context files\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\t\treturn prompt;\n\t}\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tlet prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n- read: Read file contents\n- bash: Execute bash commands (ls, grep, find, etc.)\n- edit: Make surgical edits to files (find exact text and replace)\n- write: Create or overwrite files\n\nGuidelines:\n- Always use bash tool for file operations like ls, grep, find\n- Use read to examine files before editing\n- Use edit for precise changes (old text must match exactly)\n- Use write only for new files or complete rewrites\n- Be concise in your responses\n- Show file paths clearly when working with files`;\n\n\t// Append project context files\n\tconst contextFiles = loadProjectContextFiles();\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\treturn prompt;\n}\n\n/**\n * Look for AGENT.md or CLAUDE.md in a directory (prefers AGENT.md)\n */\nfunction loadContextFileFromDir(dir: string): { path: string; content: string } | null {\n\tconst candidates = [\"AGENT.md\", \"CLAUDE.md\"];\n\tfor (const filename of candidates) {\n\t\tconst filePath = join(dir, filename);\n\t\tif (existsSync(filePath)) {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tcontent: readFileSync(filePath, \"utf-8\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Load all project context files in order:\n * 1. Global: ~/.pi/agent/AGENT.md or CLAUDE.md\n * 2. Parent directories (top-most first) down to cwd\n * Each returns {path, content} for separate messages\n */\nfunction loadProjectContextFiles(): Array<{ path: string; content: string }> {\n\tconst contextFiles: Array<{ path: string; content: string }> = [];\n\n\t// 1. Load global context from ~/.pi/agent/\n\tconst homeDir = homedir();\n\tconst globalContextDir = resolve(process.env.CODING_AGENT_DIR || join(homeDir, \".pi/agent/\"));\n\tconst globalContext = loadContextFileFromDir(globalContextDir);\n\tif (globalContext) {\n\t\tcontextFiles.push(globalContext);\n\t}\n\n\t// 2. Walk up from cwd to root, collecting all context files\n\tconst cwd = process.cwd();\n\tconst ancestorContextFiles: Array<{ path: string; content: string }> = [];\n\n\tlet currentDir = cwd;\n\tconst root = resolve(\"/\");\n\n\twhile (true) {\n\t\tconst contextFile = loadContextFileFromDir(currentDir);\n\t\tif (contextFile) {\n\t\t\t// Add to beginning so we get top-most parent first\n\t\t\tancestorContextFiles.unshift(contextFile);\n\t\t}\n\n\t\t// Stop if we've reached root\n\t\tif (currentDir === root) break;\n\n\t\t// Move up one directory\n\t\tconst parentDir = resolve(currentDir, \"..\");\n\t\tif (parentDir === currentDir) break; // Safety check\n\t\tcurrentDir = parentDir;\n\t}\n\n\t// Add ancestor files in order (top-most → cwd)\n\tcontextFiles.push(...ancestorContextFiles);\n\n\treturn contextFiles;\n}\n\nasync function selectSession(sessionManager: SessionManager): Promise<string | null> {\n\treturn new Promise((resolve) => {\n\t\tconst ui = new TUI(new ProcessTerminal());\n\t\tlet resolved = false;\n\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\tsessionManager,\n\t\t\t(path: string) => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(path);\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(null);\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\tui.addChild(selector);\n\t\tui.setFocus(selector.getSessionList());\n\t\tui.start();\n\t});\n}\n\nasync function runInteractiveMode(agent: Agent, sessionManager: SessionManager, version: string): Promise<void> {\n\tconst renderer = new TuiRenderer(agent, sessionManager, version);\n\n\t// Initialize TUI\n\tawait renderer.init();\n\n\t// Set interrupt callback\n\trenderer.setInterruptCallback(() => {\n\t\tagent.abort();\n\t});\n\n\t// Render any existing messages (from --continue mode)\n\trenderer.renderInitialMessages(agent.state);\n\n\t// Subscribe to agent events\n\tagent.subscribe(async (event) => {\n\t\t// Pass all events to the renderer\n\t\tawait renderer.handleEvent(event, agent.state);\n\t});\n\n\t// Interactive loop\n\twhile (true) {\n\t\tconst userInput = await renderer.getUserInput();\n\n\t\t// Process the message - agent.prompt will add user message and trigger state updates\n\t\ttry {\n\t\t\tawait agent.prompt(userInput);\n\t\t} catch (error: any) {\n\t\t\t// Display error in the TUI by adding an error message to the chat\n\t\t\trenderer.showError(error.message || \"Unknown error occurred\");\n\t\t}\n\t}\n}\n\nasync function runSingleShotMode(\n\tagent: Agent,\n\t_sessionManager: SessionManager,\n\tmessages: string[],\n\tmode: \"text\" | \"json\",\n): Promise<void> {\n\tif (mode === \"json\") {\n\t\t// Subscribe to all events and output as JSON\n\t\tagent.subscribe((event) => {\n\t\t\t// Output event as JSON (same format as session manager)\n\t\t\tconsole.log(JSON.stringify(event));\n\t\t});\n\t}\n\n\tfor (const message of messages) {\n\t\tawait agent.prompt(message);\n\t}\n\n\t// In text mode, only output the final assistant message\n\tif (mode === \"text\") {\n\t\tconst lastMessage = agent.state.messages[agent.state.messages.length - 1];\n\t\tif (lastMessage.role === \"assistant\") {\n\t\t\tfor (const content of lastMessage.content) {\n\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\tconsole.log(content.text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nasync function runRpcMode(agent: Agent, _sessionManager: SessionManager): Promise<void> {\n\t// Subscribe to all events and output as JSON\n\tagent.subscribe((event) => {\n\t\tconsole.log(JSON.stringify(event));\n\t});\n\n\t// Listen for JSON input on stdin\n\tconst readline = await import(\"readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\tterminal: false,\n\t});\n\n\trl.on(\"line\", async (line: string) => {\n\t\ttry {\n\t\t\tconst input = JSON.parse(line);\n\n\t\t\t// Handle different RPC commands\n\t\t\tif (input.type === \"prompt\" && input.message) {\n\t\t\t\tawait agent.prompt(input.message);\n\t\t\t} else if (input.type === \"abort\") {\n\t\t\t\tagent.abort();\n\t\t\t}\n\t\t} catch (error: any) {\n\t\t\t// Output error as JSON\n\t\t\tconsole.log(JSON.stringify({ type: \"error\", error: error.message }));\n\t\t}\n\t});\n\n\t// Keep process alive\n\treturn new Promise(() => {});\n}\n\nexport async function main(args: string[]) {\n\tconst parsed = parseArgs(args);\n\n\tif (parsed.help) {\n\t\tprintHelp();\n\t\treturn;\n\t}\n\n\t// Setup session manager\n\tconst sessionManager = new SessionManager(parsed.continue && !parsed.resume, parsed.session);\n\n\t// Disable session saving if --no-session flag is set\n\tif (parsed.noSession) {\n\t\tsessionManager.disable();\n\t}\n\n\t// Handle --resume flag: show session selector\n\tif (parsed.resume) {\n\t\tconst selectedSession = await selectSession(sessionManager);\n\t\tif (!selectedSession) {\n\t\t\tconsole.log(chalk.dim(\"No session selected\"));\n\t\t\treturn;\n\t\t}\n\t\t// Set the selected session as the active session\n\t\tsessionManager.setSessionFile(selectedSession);\n\t}\n\n\t// Determine provider and model\n\tconst provider = (parsed.provider || \"anthropic\") as any;\n\tconst modelId = parsed.model || \"claude-sonnet-4-5\";\n\n\t// Helper function to get API key for a provider\n\tconst getApiKeyForProvider = (providerName: string): string | undefined => {\n\t\t// Check if API key was provided via command line\n\t\tif (parsed.apiKey) {\n\t\t\treturn parsed.apiKey;\n\t\t}\n\n\t\tconst envVars = envApiKeyMap[providerName as KnownProvider];\n\n\t\t// Check each environment variable in priority order\n\t\tfor (const envVar of envVars) {\n\t\t\tconst key = process.env[envVar];\n\t\t\tif (key) {\n\t\t\t\treturn key;\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t};\n\n\t// Get initial API key\n\tconst initialApiKey = getApiKeyForProvider(provider);\n\tif (!initialApiKey) {\n\t\tconst envVars = envApiKeyMap[provider as KnownProvider];\n\t\tconst envVarList = envVars.join(\" or \");\n\t\tconsole.error(chalk.red(`Error: No API key found for provider \"${provider}\"`));\n\t\tconsole.error(chalk.dim(`Set ${envVarList} environment variable or use --api-key flag`));\n\t\tprocess.exit(1);\n\t}\n\n\t// Create agent\n\tconst model = getModel(provider, modelId);\n\tconst systemPrompt = buildSystemPrompt(parsed.systemPrompt);\n\n\tconst agent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt,\n\t\t\tmodel,\n\t\t\tthinkingLevel: \"off\",\n\t\t\ttools: codingTools,\n\t\t},\n\t\ttransport: new ProviderTransport({\n\t\t\t// Dynamic API key lookup based on current model's provider\n\t\t\tgetApiKey: async () => {\n\t\t\t\tconst currentProvider = agent.state.model.provider;\n\t\t\t\tconst key = getApiKeyForProvider(currentProvider);\n\t\t\t\tif (!key) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`No API key found for provider \"${currentProvider}\". Please set the appropriate environment variable.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn key;\n\t\t\t},\n\t\t}),\n\t});\n\n\t// Determine mode early to know if we should print messages\n\tconst isInteractive = parsed.messages.length === 0;\n\tconst mode = parsed.mode || \"text\";\n\tconst shouldPrintMessages = isInteractive || mode === \"text\";\n\n\t// Load previous messages if continuing or resuming\n\tif (parsed.continue || parsed.resume) {\n\t\tconst messages = sessionManager.loadMessages();\n\t\tif (messages.length > 0) {\n\t\t\tif (shouldPrintMessages) {\n\t\t\t\tconsole.log(chalk.dim(`Loaded ${messages.length} messages from previous session`));\n\t\t\t}\n\t\t\tagent.replaceMessages(messages);\n\t\t}\n\n\t\t// Load and restore model\n\t\tconst savedModel = sessionManager.loadModel();\n\t\tif (savedModel) {\n\t\t\t// Parse provider/modelId from saved model string (format: \"provider/modelId\")\n\t\t\tconst [savedProvider, savedModelId] = savedModel.split(\"/\");\n\t\t\tif (savedProvider && savedModelId) {\n\t\t\t\ttry {\n\t\t\t\t\tconst restoredModel = getModel(savedProvider as any, savedModelId);\n\t\t\t\t\tagent.setModel(restoredModel);\n\t\t\t\t\tif (shouldPrintMessages) {\n\t\t\t\t\t\tconsole.log(chalk.dim(`Restored model: ${savedModel}`));\n\t\t\t\t\t}\n\t\t\t\t} catch (error: any) {\n\t\t\t\t\tif (shouldPrintMessages) {\n\t\t\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not restore model ${savedModel}: ${error.message}`));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Load and restore thinking level\n\t\tconst thinkingLevel = sessionManager.loadThinkingLevel() as ThinkingLevel;\n\t\tif (thinkingLevel) {\n\t\t\tagent.setThinkingLevel(thinkingLevel);\n\t\t\tif (shouldPrintMessages) {\n\t\t\t\tconsole.log(chalk.dim(`Restored thinking level: ${thinkingLevel}`));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Note: Session will be started lazily after first user+assistant message exchange\n\t// (unless continuing/resuming, in which case it's already initialized)\n\n\t// Log loaded context files (they're already in the system prompt)\n\tif (shouldPrintMessages && !parsed.continue && !parsed.resume) {\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tconsole.log(chalk.dim(\"Loaded project context from:\"));\n\t\t\tfor (const { path: filePath } of contextFiles) {\n\t\t\t\tconsole.log(chalk.dim(` - ${filePath}`));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Subscribe to agent events to save messages\n\tagent.subscribe((event) => {\n\t\t// Save messages on completion\n\t\tif (event.type === \"message_end\") {\n\t\t\tsessionManager.saveMessage(event.message);\n\n\t\t\t// Check if we should initialize session now (after first user+assistant exchange)\n\t\t\tif (sessionManager.shouldInitializeSession(agent.state.messages)) {\n\t\t\t\tsessionManager.startSession(agent.state);\n\t\t\t}\n\t\t}\n\t});\n\n\t// Route to appropriate mode\n\tif (mode === \"rpc\") {\n\t\t// RPC mode - headless operation\n\t\tawait runRpcMode(agent, sessionManager);\n\t} else if (isInteractive) {\n\t\t// No messages and not RPC - use TUI\n\t\tawait runInteractiveMode(agent, sessionManager, VERSION);\n\t} else {\n\t\t// CLI mode with messages\n\t\tawait runSingleShotMode(agent, sessionManager, parsed.messages, mode);\n\t}\n}\n"]}
@@ -0,0 +1,70 @@
1
+ import type { AgentState } from "@mariozechner/pi-agent";
2
+ export interface SessionHeader {
3
+ type: "session";
4
+ id: string;
5
+ timestamp: string;
6
+ cwd: string;
7
+ model: string;
8
+ thinkingLevel: string;
9
+ }
10
+ export interface SessionMessageEntry {
11
+ type: "message";
12
+ timestamp: string;
13
+ message: any;
14
+ }
15
+ export interface ThinkingLevelChangeEntry {
16
+ type: "thinking_level_change";
17
+ timestamp: string;
18
+ thinkingLevel: string;
19
+ }
20
+ export interface ModelChangeEntry {
21
+ type: "model_change";
22
+ timestamp: string;
23
+ model: string;
24
+ }
25
+ export declare class SessionManager {
26
+ private sessionId;
27
+ private sessionFile;
28
+ private sessionDir;
29
+ private enabled;
30
+ private sessionInitialized;
31
+ private pendingMessages;
32
+ constructor(continueSession?: boolean, customSessionPath?: string);
33
+ /** Disable session saving (for --no-session mode) */
34
+ disable(): void;
35
+ private getSessionDirectory;
36
+ private initNewSession;
37
+ private findMostRecentlyModifiedSession;
38
+ private loadSessionId;
39
+ startSession(state: AgentState): void;
40
+ saveMessage(message: any): void;
41
+ saveThinkingLevelChange(thinkingLevel: string): void;
42
+ saveModelChange(model: string): void;
43
+ loadMessages(): any[];
44
+ loadThinkingLevel(): string;
45
+ loadModel(): string | null;
46
+ getSessionId(): string;
47
+ getSessionFile(): string;
48
+ /**
49
+ * Load all sessions for the current directory with metadata
50
+ */
51
+ loadAllSessions(): Array<{
52
+ path: string;
53
+ id: string;
54
+ created: Date;
55
+ modified: Date;
56
+ messageCount: number;
57
+ firstMessage: string;
58
+ allMessagesText: string;
59
+ }>;
60
+ /**
61
+ * Set the session file to an existing session
62
+ */
63
+ setSessionFile(path: string): void;
64
+ /**
65
+ * Check if we should initialize the session based on message history.
66
+ * Session is initialized when we have at least 1 user message and 1 assistant message.
67
+ */
68
+ shouldInitializeSession(messages: any[]): boolean;
69
+ }
70
+ //# sourceMappingURL=session-manager.d.ts.map