apex-dev 1.0.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.
- package/.config/amp/settings.json +3 -0
- package/.config/opencode/oh-my-opencode.json +58 -0
- package/.config/opencode/opencode.json +6 -0
- package/.local/share/amp/device-id.json +3 -0
- package/.local/share/amp/history.jsonl +33 -0
- package/.local/share/amp/session.json +6 -0
- package/.local/share/amp/threads/T-019c93b8-fce7-7083-aab9-d5f1c88a9545.json +2528 -0
- package/.local/share/amp/threads/T-019c93c8-4b7a-71df-94ac-867d8236a288.json +7 -0
- package/.local/share/amp/threads/T-019c93cd-5a7d-728e-8289-02e0ef4ca2ff.json +680 -0
- package/.local/share/amp/threads/T-019c93e7-83ca-7633-9eed-12bdcc118163.json +873 -0
- package/.local/share/amp/threads/T-019c93ea-ccd3-765a-88c9-42d7b631e977.json +620 -0
- package/.local/share/amp/threads/T-019c93ee-5977-71af-9ab7-c4611004b703.json +1000 -0
- package/.local/share/amp/threads/T-019c93f0-8328-71ed-a250-6da169cebfe1.json +829 -0
- package/.local/share/amp/threads/T-019c93f5-7bdd-703b-b2cd-0a04da64441a.json +459 -0
- package/.local/share/amp/threads/T-019c93f8-2b2e-733b-8249-9876546d9b5b.json +764 -0
- package/.local/share/amp/threads/T-019c93fd-fade-7195-a3b7-358f180d40b8.json +7 -0
- package/.local/share/amp/threads/T-019c93fe-2e56-705e-827e-eb99bd02e257.json +3593 -0
- package/.local/share/amp/threads/T-019c9408-6e64-77e1-9519-b913e3b24a03.json +1559 -0
- package/.local/share/amp/threads/T-019c9409-feeb-736d-b92c-4f7a263a643c.json +7 -0
- package/.local/share/amp/threads/T-019c940b-8d11-755b-b9e1-f923d8a5e6ba.json +7 -0
- package/.local/share/amp/threads/T-019c943a-6c5e-76a5-bf4e-170f7ad452ce.json +979 -0
- package/.local/share/amp/threads/T-019c94b2-1c8f-76d8-96d0-82449a028849.json +1584 -0
- package/.local/share/amp/threads/T-019c94b6-68f0-726e-92dd-90c5411ca28c.json +7 -0
- package/.local/share/amp/threads/T-019c94bf-a589-72a3-b3c2-a81359d9e0a6.json +7 -0
- package/.local/share/amp/threads/T-019c94e1-1bd9-70ab-b6f2-abd5cab4f4ce.json +1035 -0
- package/.local/share/amp/threads/T-019c94fd-cc4a-714b-896a-74f94020f6eb.json +1310 -0
- package/.local/share/amp/threads/T-019c9501-8976-7138-aca6-245a01a8fe9b.json +7 -0
- package/.local/share/amp/threads/T-019c9504-4b51-763e-8a9f-5d4cdfcf0cfa.json +496 -0
- package/.local/share/amp/threads/T-019c9506-4e3b-74fd-8eda-cedbf3793598.json +2679 -0
- package/.local/share/amp/threads/T-019c9508-178c-718c-88d2-caf816d64f65.json +965 -0
- package/.local/share/amp/threads/T-019c9509-2812-71fd-8fd2-923e29ad34fa.json +7 -0
- package/.local/share/kilo/kilo.db +0 -0
- package/.local/share/kilo/kilo.db-shm +0 -0
- package/.local/share/kilo/kilo.db-wal +0 -0
- package/.local/share/kilo/storage/migration +1 -0
- package/.local/share/kilo/storage/session_diff/ses_36bea4cb9ffe1b0j5HEL14KEaU.json +1 -0
- package/.local/share/kilo/storage/session_diff/ses_36beaa8f2ffeeZ3Y39SQ9UDWQQ.json +1 -0
- package/.local/share/kilo/telemetry-id +1 -0
- package/.local/share/opencode/auth.json +6 -0
- package/.local/share/opencode/opencode.db +0 -0
- package/.local/share/opencode/opencode.db-shm +0 -0
- package/.local/share/opencode/opencode.db-wal +0 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36bee9f1effeJbiHHLWLR6O3WJ.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36c25e50affef2nhaXq9aSgKH3.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36c260708ffel4wG4yhdo0knDD.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36c261531ffeoVcvqXxry2bN9H.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36c291bddffePWRiaFLLJAC1y7.json +6 -0
- package/.local/share/opencode/storage/migration +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36bee9f1effeJbiHHLWLR6O3WJ.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c25e50affef2nhaXq9aSgKH3.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c260708ffel4wG4yhdo0knDD.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c261531ffeoVcvqXxry2bN9H.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c291bddffePWRiaFLLJAC1y7.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c2af1c5ffegxEaOZOGcVykyy.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36c2be235ffeOa6x8UCk1HW4kU.json +1 -0
- package/.local/share/opencode/tool-output/tool_c93da840c0016GrdyAkOnHGezU +2330 -0
- package/.local/share/opencode/tool-output/tool_c9411e784001cRoQqwVDb1a6lY +1017 -0
- package/.replit +21 -0
- package/.upm/store.json +1 -0
- package/bun.lock +237 -0
- package/generated-icon.png +0 -0
- package/index.js +1587 -0
- package/package.json +24 -0
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
{
|
|
2
|
+
"v": 2022,
|
|
3
|
+
"id": "T-019c93f8-2b2e-733b-8249-9876546d9b5b",
|
|
4
|
+
"created": 1772009040693,
|
|
5
|
+
"messages": [
|
|
6
|
+
{
|
|
7
|
+
"role": "user",
|
|
8
|
+
"messageId": 0,
|
|
9
|
+
"content": [
|
|
10
|
+
{
|
|
11
|
+
"type": "text",
|
|
12
|
+
"text": "after it responded to my request, the CLI tool just exits"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"userState": {
|
|
16
|
+
"currentlyVisibleFiles": []
|
|
17
|
+
},
|
|
18
|
+
"agentMode": "smart",
|
|
19
|
+
"meta": {
|
|
20
|
+
"sentAt": 1772009063630
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"role": "assistant",
|
|
25
|
+
"messageId": 1,
|
|
26
|
+
"content": [
|
|
27
|
+
{
|
|
28
|
+
"type": "text",
|
|
29
|
+
"text": "\n\n"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": "thinking",
|
|
33
|
+
"thinking": "The user is having an issue with their CLI tool exiting after responding to a request. Let me look at the codebase to understand what's going on.",
|
|
34
|
+
"signature": "ErwCCkgICxACGAIqQIAUzjO/+7ccOPu24S6LM85t1csQCEnp9EVmmjgp+ap0DUUsv4ZhGxEdMT/IJTjq4esxS4RRaUYUd9o+TO/azeASDCp3ucrnEz1WIyUOzRoM8P2+Gz0FDwMj++sWIjDcRzf+XcMgWbmCZsWWBvxiIdc7XThkt3vkC0P8r/hy/xaPfUXoeSWkxTvnRkJLKDcqoQEffIPBDLeBF5wlPtOSgWIW6FWBsjebIwuvtjdeC9FIQyGVYwWWjiuzQEY3oSQ1cTVgE5lBBsRLySLjPxFcVfvpFKO9NDg6VI8HnjLQcCXYZESE/ciGaJMrObORgrIyD6DtDDx4ySnVSZ8C1TKT6WTUaf4n+it+sh394qTo5osiq4e+K0/z7oga3UDFTjOInyJbhcTMldHc+OxydaW7g9VnVxgB",
|
|
35
|
+
"provider": "anthropic"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"type": "tool_use",
|
|
39
|
+
"complete": true,
|
|
40
|
+
"id": "toolu_vrtx_01QAYKYpLHbuvgB7o4YNGLuy",
|
|
41
|
+
"name": "Read",
|
|
42
|
+
"input": {
|
|
43
|
+
"path": "/home/runner/workspace/index.js"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "tool_use",
|
|
48
|
+
"complete": true,
|
|
49
|
+
"id": "toolu_vrtx_0195x5TaXb86NpyiKr9UCqX8",
|
|
50
|
+
"name": "Read",
|
|
51
|
+
"input": {
|
|
52
|
+
"path": "/home/runner/workspace/package.json"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"state": {
|
|
57
|
+
"type": "complete",
|
|
58
|
+
"stopReason": "tool_use"
|
|
59
|
+
},
|
|
60
|
+
"usage": {
|
|
61
|
+
"model": "claude-opus-4-6",
|
|
62
|
+
"maxInputTokens": 168000,
|
|
63
|
+
"inputTokens": 3,
|
|
64
|
+
"outputTokens": 152,
|
|
65
|
+
"cacheCreationInputTokens": 1196,
|
|
66
|
+
"cacheReadInputTokens": 13086,
|
|
67
|
+
"totalInputTokens": 14285,
|
|
68
|
+
"timestamp": "2026-02-25T08:44:27.193Z"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"role": "user",
|
|
73
|
+
"messageId": 2,
|
|
74
|
+
"content": [
|
|
75
|
+
{
|
|
76
|
+
"type": "tool_result",
|
|
77
|
+
"toolUseID": "toolu_vrtx_01QAYKYpLHbuvgB7o4YNGLuy",
|
|
78
|
+
"run": {
|
|
79
|
+
"status": "done",
|
|
80
|
+
"progress": {},
|
|
81
|
+
"result": {
|
|
82
|
+
"absolutePath": "/home/runner/workspace/index.js",
|
|
83
|
+
"content": "1: #!/usr/bin/env node\n2: 'use strict';\n3: \n4: const chalk = require('chalk');\n5: const ora = require('ora');\n6: const boxen = require('boxen');\n7: const figures = require('figures');\n8: const readline = require('readline');\n9: const { highlight } = require('cli-highlight');\n10: const OpenAI = require('openai');\n11: const fs = require('fs');\n12: const path = require('path');\n13: const { execSync, exec } = require('child_process');\n14: const { promisify } = require('util');\n15: const execAsync = promisify(exec);\n16: \n17: // ===== Config =====\n18: const NVIDIA_MODEL = 'meta/llama-3.1-70b-instruct';\n19: const MAX_TOOL_ITERATIONS = 50;\n20: const MAX_OUTPUT_LEN = 12000;\n21: const TOOL_TIMEOUT = 60000;\n22: const PROJECT_ROOT = process.cwd();\n23: \n24: const nvidiaClient = new OpenAI({\n25: apiKey: process.env.NVIDIA_API_KEY || '',\n26: baseURL: 'https://integrate.api.nvidia.com/v1',\n27: });\n28: \n29: // ===== Session State =====\n30: const session = {\n31: conversationHistory: [],\n32: totalTokens: 0,\n33: totalCost: 0,\n34: toolCallCount: 0,\n35: filesModified: new Set(),\n36: filesRead: new Set(),\n37: commandsRun: [],\n38: editHistory: [], // { path, before, after, timestamp }\n39: startTime: Date.now(),\n40: turnCount: 0,\n41: };\n42: \n43: // ===== Agentic System Prompt =====\n44: function buildSystemPrompt() {\n45: let gitInfo = '';\n46: try {\n47: const branch = execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', { encoding: 'utf-8', cwd: PROJECT_ROOT }).trim();\n48: const status = execSync('git status --short 2>/dev/null', { encoding: 'utf-8', cwd: PROJECT_ROOT }).trim();\n49: const remoteUrl = execSync('git config --get remote.origin.url 2>/dev/null', { encoding: 'utf-8', cwd: PROJECT_ROOT }).trim();\n50: gitInfo = `\\nGit branch: ${branch}\\nGit remote: ${remoteUrl}\\nGit status:\\n${status || '(clean)'}`;\n51: } catch {}\n52: \n53: let projectInfo = '';\n54: try {\n55: const pkg = JSON.parse(fs.readFileSync(path.join(PROJECT_ROOT, 'package.json'), 'utf-8'));\n56: projectInfo = `\\nProject: ${pkg.name || 'unknown'} v${pkg.version || '0.0.0'}`;\n57: if (pkg.dependencies) projectInfo += `\\nDependencies: ${Object.keys(pkg.dependencies).join(', ')}`;\n58: if (pkg.devDependencies) projectInfo += `\\nDev dependencies: ${Object.keys(pkg.devDependencies).join(', ')}`;\n59: if (pkg.scripts) projectInfo += `\\nScripts: ${Object.keys(pkg.scripts).join(', ')}`;\n60: } catch {}\n61: \n62: return `You are Apex AI, a friendly and approachable coding assistant. You're warm, helpful, and conversational — like a knowledgeable friend who loves coding.\n63: \n64: # Personality\n65: \n66: - Be friendly, warm, and encouraging. Use a casual but professional tone.\n67: - When a user asks a question that doesn't need any tools (like general knowledge, advice, greetings, or casual chat), just answer directly and naturally. You do NOT always need to use tools — only use them when the task actually requires reading, writing, or executing something on the filesystem.\n68: - NEVER say things like \"I don't have any tool to call\" or \"I don't have the tools for that.\" Just respond helpfully with what you know.\n69: - If you're unsure, say so honestly, but still try your best to help.\n70: \n71: # Core Principles\n72: \n73: 1. **Take initiative.** When asked to do something, DO it — don't just explain how. Use your tools to read, write, edit, and execute code until the task is COMPLETE.\n74: 2. **Read before you edit.** NEVER modify a file you haven't read first. Always understand existing code before making changes.\n75: 3. **Work incrementally.** Make small changes, verify they work (run tests, check syntax), then continue. Don't make huge changes blind.\n76: 4. **Verify your work.** After making changes, run the relevant tests, linter, or type checker. If something fails, fix it before responding.\n77: 5. **Follow conventions.** Match the existing code style, frameworks, libraries, and patterns. Check imports and neighboring files first.\n78: 6. **Minimal changes.** Only change what's needed. Don't refactor, add features, or \"improve\" code beyond what was asked.\n79: 7. **Keep going.** If a tool call fails, try to recover. If you need more context, read more files. Don't give up after one attempt.\n80: \n81: # Tool Usage\n82: \n83: - Use Bash for running commands (tests, builds, linters, git operations)\n84: - Use Read to understand files before modifying them\n85: - Use Grep/Glob/ListDir to explore the codebase and find relevant code\n86: - Use Edit for surgical changes to existing files (preferred over Write for existing files)\n87: - Use Write only for creating new files\n88: - Use Patch for making multiple edits to the same file at once\n89: - Execute multiple independent tool calls in parallel when possible\n90: - After editing code, verify with: syntax check, run tests, or at minimum read the changed section\n91: \n92: # Workflow for Code Tasks\n93: \n94: 1. Explore: Use ListDir, Glob, Grep to understand the codebase structure\n95: 2. Read: Read relevant files to understand context, conventions, dependencies\n96: 3. Plan: Think about what changes are needed (briefly)\n97: 4. Implement: Make changes using Edit/Write\n98: 5. Verify: Run tests or check the result with Bash\n99: 6. Iterate: If verification fails, fix and re-verify\n100: \n101: # Environment\n102: Working directory: ${PROJECT_ROOT}\n103: OS: ${process.platform}\n104: Node: ${process.version}${projectInfo}${gitInfo}\n105: \n106: # Important\n107: - You can call multiple tools at once — do so when the calls are independent\n108: - Don't ask for permission to use tools — just use them\n109: - Don't explain what you're going to do in detail — just do it and summarize what you did\n110: - If the user asks you to fix something, find the bug AND fix it\n111: - If the user asks you to build something, build it completely and verify it works\n112: - Maximum tool iterations per turn: ${MAX_TOOL_ITERATIONS}`;\n113: }\n114: \n115: // ===== Tool Definitions =====\n116: const toolDefs = [\n117: {\n118: type: 'function',\n119: function: {\n120: name: 'Read',\n121: description: 'Read the contents of a file. Returns line-numbered content. Always read a file before editing it.',\n122: parameters: {\n123: type: 'object',\n124: properties: {\n125: path: { type: 'string', description: 'File path to read (absolute or relative to project root).' },\n126: start_line: { type: 'number', description: 'Start line (1-indexed). Omit to read from beginning.' },\n127: end_line: { type: 'number', description: 'End line (1-indexed). Omit to read to end (max 500 lines).' },\n128: },\n129: required: ['path'],\n130: },\n131: },\n132: },\n133: {\n134: type: 'function',\n135: function: {\n136: name: 'Write',\n137: description: 'Create a new file or completely overwrite an existing file. For modifying existing files, prefer Edit instead.',\n138: parameters: {\n139: type: 'object',\n140: properties: {\n141: path: { type: 'string', description: 'File path to write.' },\n142: content: { type: 'string', description: 'Full content to write.' },\n143: },\n144: required: ['path', 'content'],\n145: },\n146: },\n147: },\n148: {\n149: type: 'function',\n150: function: {\n151: name: 'Edit',\n152: description: 'Replace an exact string in a file with new content. The old_str must match exactly (including whitespace). For existing files, this is preferred over Write.',\n153: parameters: {\n154: type: 'object',\n155: properties: {\n156: path: { type: 'string', description: 'File path to edit.' },\n157: old_str: { type: 'string', description: 'Exact string to find (must be unique in the file).' },\n158: new_str: { type: 'string', description: 'Replacement string.' },\n159: },\n160: required: ['path', 'old_str', 'new_str'],\n161: },\n162: },\n163: },\n164: {\n165: type: 'function',\n166: function: {\n167: name: 'Patch',\n168: description: 'Apply multiple find-and-replace edits to a single file atomically. Use when you need to make several changes to the same file.',\n169: parameters: {\n170: type: 'object',\n171: properties: {\n172: path: { type: 'string', description: 'File path to patch.' },\n173: edits: {\n174: type: 'array',\n175: description: 'Array of edits to apply in order.',\n176: items: {\n177: type: 'object',\n178: properties: {\n179: old_str: { type: 'string', description: 'Exact string to find.' },\n180: new_str: { type: 'string', description: 'Replacement string.' },\n181: },\n182: required: ['old_str', 'new_str'],\n183: },\n184: },\n185: },\n186: required: ['path', 'edits'],\n187: },\n188: },\n189: },\n190: {\n191: type: 'function',\n192: function: {\n193: name: 'Bash',\n194: description: 'Execute a shell command. Use for running tests, builds, git commands, installing packages, checking syntax, etc. Commands have a 60-second timeout.',\n195: parameters: {\n196: type: 'object',\n197: properties: {\n198: command: { type: 'string', description: 'Shell command to execute.' },\n199: cwd: { type: 'string', description: 'Working directory (defaults to project root).' },\n200: },\n201: required: ['command'],\n202: },\n203: },\n204: },\n205: {\n206: type: 'function',\n207: function: {\n208: name: 'Grep',\n209: description: 'Search for a pattern across files using regex. Returns matching lines with file paths and line numbers.',\n210: parameters: {\n211: type: 'object',\n212: properties: {\n213: pattern: { type: 'string', description: 'Regex pattern to search for.' },\n214: path: { type: 'string', description: 'Directory or file to search in (defaults to project root).' },\n215: include: { type: 'string', description: 'File glob pattern to include, e.g. \"*.js\" or \"*.ts\"' },\n216: case_sensitive: { type: 'boolean', description: 'Case-sensitive search (default: false).' },\n217: },\n218: required: ['pattern'],\n219: },\n220: },\n221: },\n222: {\n223: type: 'function',\n224: function: {\n225: name: 'Glob',\n226: description: 'Find files matching a glob pattern. Returns file paths sorted by modification time.',\n227: parameters: {\n228: type: 'object',\n229: properties: {\n230: pattern: { type: 'string', description: 'Glob pattern like \"**/*.js\", \"src/**/*.ts\", \"*.json\"' },\n231: cwd: { type: 'string', description: 'Base directory for the search (defaults to project root).' },\n232: },\n233: required: ['pattern'],\n234: },\n235: },\n236: },\n237: {\n238: type: 'function',\n239: function: {\n240: name: 'ListDir',\n241: description: 'List the contents of a directory. Shows files and subdirectories with type indicators.',\n242: parameters: {\n243: type: 'object',\n244: properties: {\n245: path: { type: 'string', description: 'Directory path to list (defaults to project root).' },\n246: recursive: { type: 'boolean', description: 'If true, list recursively (max depth 3).' },\n247: },\n248: required: [],\n249: },\n250: },\n[... omitted lines 251 to 902 ...]\n903: \n904: // No tool calls — final text response\n905: if (msg.content) {\n906: showAssistantMessage(msg.content);\n907: session.conversationHistory.push({ role: 'assistant', content: msg.content });\n908: }\n909: break;\n910: }\n911: \n912: if (iterations >= MAX_TOOL_ITERATIONS) {\n913: console.log(indent(t.yellow(`⚠ Reached maximum tool iterations (${MAX_TOOL_ITERATIONS}). Stopping.`)));\n914: console.log();\n915: }\n916: \n917: const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n918: session.totalTokens += turnTokens;\n919: showTurnSummary(turnTokens, duration, turnToolCalls);\n920: } catch (err) {\n921: console.log();\n922: console.log(indent(t.red('✗ Error: ') + t.text(err.message)));\n923: if (!process.env.NVIDIA_API_KEY) {\n924: console.log(indent(t.yellow('Set the NVIDIA_API_KEY environment variable with your API key from build.nvidia.com')));\n925: }\n926: console.log();\n927: }\n928: \n929: console.log(indent(hr()));\n930: isProcessing = false;\n931: if (rlClosed) process.exit(0);\n932: }\n933: \n934: // ===== Utilities =====\n935: function timestamp() {\n936: return new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n937: }\n938: \n939: function sleep(ms) {\n940: return new Promise(r => setTimeout(r, ms));\n941: }\n942: \n943: // ===== Main Loop =====\n944: async function main() {\n945: showHeader();\n946: showWelcome();\n947: \n948: const rl = createPrompt();\n949: \n950: rl.on('close', () => {\n951: rlClosed = true;\n952: if (isProcessing) return;\n953: console.log();\n954: showSessionSummary();\n955: console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n956: console.log();\n957: process.exit(0);\n958: });\n959: \n960: const askQuestion = () => {\n961: if (rlClosed) return;\n962: const promptStr = showPrompt();\n963: \n964: rl.question(promptStr, async (answer) => {\n965: if (answer === null || answer === undefined) {\n966: process.exit(0);\n967: }\n968: const input = answer.trim();\n969: \n970: if (!input) { askQuestion(); return; }\n971: \n972: // Slash commands\n973: if (input.startsWith('/')) {\n974: handleSlashCommand(input, rl);\n975: askQuestion();\n976: return;\n977: }\n978: \n979: if (input === 'exit' || input === 'quit') {\n980: console.log();\n981: showSessionSummary();\n982: console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n983: console.log();\n984: process.exit(0);\n985: }\n986: \n987: try {\n988: await handleUserInput(input);\n989: } catch (err) {\n990: console.log(indent(t.red('✗ Unexpected error: ') + t.text(err.message)));\n991: console.log();\n992: }\n993: askQuestion();\n994: });\n995: };\n996: \n997: askQuestion();\n998: }\n999: \n1000: // ===== Slash Commands =====\n1001: function handleSlashCommand(input, rl) {\n1002: const [cmd, ...rest] = input.split(' ');\n1003: const arg = rest.join(' ');\n1004: \n1005: switch (cmd) {\n1006: case '/help':\n1007: showHelpMenu();\n1008: break;\n1009: \n1010: case '/clear':\n1011: session.conversationHistory = [];\n1012: showHeader();\n1013: console.log(indent(t.green('✓ ') + t.muted('Conversation cleared.')));\n1014: console.log();\n1015: break;\n1016: \n1017: case '/files':\n1018: case '/ls': {\n1019: const dirPath = arg ? resolvePath(arg) : PROJECT_ROOT;\n1020: console.log();\n1021: console.log(indent(t.text.bold('Project Files')));\n1022: console.log();\n1023: const result = executeTool('ListDir', { path: dirPath, recursive: true });\n1024: console.log(indent(t.dim(result), 4));\n1025: console.log();\n1026: break;\n1027: }\n1028: \n1029: case '/cost':\n1030: case '/status':\n1031: showSessionSummary();\n1032: break;\n1033: \n1034: case '/undo': {\n1035: if (session.editHistory.length === 0) {\n1036: console.log(indent(t.yellow('No edits to undo.')));\n1037: } else {\n1038: const last = session.editHistory[session.editHistory.length - 1];\n1039: fs.writeFileSync(last.path, last.before, 'utf-8');\n1040: session.editHistory.pop();\n1041: console.log(indent(t.green('✓ ') + t.muted(`Undone last edit to ${path.basename(last.path)}`)));\n1042: }\n1043: console.log();\n1044: break;\n1045: }\n1046: \n1047: case '/diff': {\n1048: try {\n1049: const diff = execSync('git diff --stat 2>/dev/null', { encoding: 'utf-8', cwd: PROJECT_ROOT });\n1050: console.log();\n1051: console.log(indent(t.text.bold('Git Diff')));\n1052: console.log(indent(t.dim(diff || '(no changes)'), 4));\n1053: console.log();\n1054: } catch {\n1055: console.log(indent(t.yellow('Not a git repository.')));\n1056: console.log();\n1057: }\n1058: break;\n1059: }\n1060: \n1061: case '/git': {\n1062: if (!arg) {\n1063: console.log(indent(t.yellow('Usage: /git <command>')));\n1064: console.log();\n1065: break;\n1066: }\n1067: try {\n1068: const output = execSync(`git ${arg}`, { encoding: 'utf-8', cwd: PROJECT_ROOT });\n1069: console.log();\n1070: console.log(indent(t.dim(output), 4));\n1071: console.log();\n1072: } catch (err) {\n1073: console.log(indent(t.red(err.stderr || err.message)));\n1074: console.log();\n1075: }\n1076: break;\n1077: }\n1078: \n1079: case '/quit':\n1080: console.log();\n1081: showSessionSummary();\n1082: console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n1083: console.log();\n1084: process.exit(0);\n1085: \n1086: default:\n1087: console.log(indent(t.yellow(`Unknown command: ${cmd}. Type /help for available commands.`)));\n1088: console.log();\n1089: }\n1090: }\n1091: \n1092: // ===== Session Summary =====\n1093: function showSessionSummary() {\n1094: const elapsed = ((Date.now() - session.startTime) / 1000 / 60).toFixed(1);\n1095: const items = [\n1096: t.dim('Session ') + t.text(`${elapsed} min`),\n1097: t.dim('Turns ') + t.text(session.turnCount.toString()),\n1098: t.dim('Tool calls ') + t.text(session.toolCallCount.toString()),\n1099: t.dim('Tokens ') + t.text(session.totalTokens.toLocaleString()),\n1100: t.dim('Cost ') + t.text('$' + session.totalCost.toFixed(4)),\n1101: ];\n1102: \n1103: if (session.filesModified.size > 0) {\n1104: items.push(t.dim('Modified ') + t.text(`${session.filesModified.size} files`));\n1105: }\n1106: if (session.commandsRun.length > 0) {\n1107: items.push(t.dim('Commands ') + t.text(`${session.commandsRun.length} executed`));\n1108: }\n1109: \n1110: console.log();\n1111: const box = boxen(items.join('\\n'), {\n1112: title: 'Session Summary',\n1113: titleAlignment: 'center',\n1114: padding: { left: 1, right: 1, top: 0, bottom: 0 },\n1115: borderColor: '#818cf8',\n1116: borderStyle: 'round',\n1117: });\n1118: console.log(indent(box, 2));\n1119: console.log();\n1120: }\n1121: \n1122: // ===== Help =====\n1123: function showHelpMenu() {\n1124: console.log();\n1125: console.log(indent(t.text.bold('Slash Commands')));\n1126: console.log();\n1127: console.log(indent(` ${t.brand('/help')} ${t.muted('Show this menu')}`));\n1128: console.log(indent(` ${t.brand('/files')} ${t.dim('[path]')} ${t.muted('Show project file tree')}`));\n1129: console.log(indent(` ${t.brand('/clear')} ${t.muted('Clear conversation history')}`));\n1130: console.log(indent(` ${t.brand('/cost')} ${t.muted('Show session statistics')}`));\n1131: console.log(indent(` ${t.brand('/undo')} ${t.muted('Undo last file edit')}`));\n1132: console.log(indent(` ${t.brand('/diff')} ${t.muted('Show git diff summary')}`));\n1133: console.log(indent(` ${t.brand('/git')} ${t.dim('<cmd>')} ${t.muted('Run a git command')}`));\n1134: console.log(indent(` ${t.brand('/quit')} ${t.muted('Exit with session summary')}`));\n1135: console.log();\n1136: console.log(indent(t.text.bold('Available Tools')));\n1137: console.log();\n1138: console.log(indent(` ${toolBadge('Read')} ${t.muted('Read file contents')}`));\n1139: console.log(indent(` ${toolBadge('Write')} ${t.muted('Create or overwrite files')}`));\n1140: console.log(indent(` ${toolBadge('Edit')} ${t.muted('Find-and-replace in files')}`));\n1141: console.log(indent(` ${toolBadge('Patch')} ${t.muted('Multiple edits to one file')}`));\n1142: console.log(indent(` ${toolBadge('Bash')} ${t.muted('Execute shell commands')}`));\n1143: console.log(indent(` ${toolBadge('Grep')} ${t.muted('Search code with regex')}`));\n1144: console.log(indent(` ${toolBadge('Glob')} ${t.muted('Find files by pattern')}`));\n1145: console.log(indent(` ${toolBadge('ListDir')} ${t.muted('List directory contents')}`));\n1146: console.log(indent(` ${toolBadge('UndoEdit')}${t.muted(' Revert last file edit')}`));\n1147: console.log(indent(` ${toolBadge('Task')} ${t.muted('Run multi-step sub-tasks')}`));\n1148: console.log();\n1149: }\n1150: \n1151: // ===== Run =====\n1152: main().catch(console.error);"
|
|
84
|
+
},
|
|
85
|
+
"trackFiles": [
|
|
86
|
+
"file:///home/runner/workspace/index.js"
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"type": "tool_result",
|
|
92
|
+
"toolUseID": "toolu_vrtx_0195x5TaXb86NpyiKr9UCqX8",
|
|
93
|
+
"run": {
|
|
94
|
+
"status": "done",
|
|
95
|
+
"progress": {},
|
|
96
|
+
"result": {
|
|
97
|
+
"absolutePath": "/home/runner/workspace/package.json",
|
|
98
|
+
"content": "1: {\n2: \"name\": \"nodejs\",\n3: \"version\": \"1.0.0\",\n4: \"description\": \"\",\n5: \"main\": \"index.js\",\n6: \"scripts\": {\n7: \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n8: },\n9: \"keywords\": [],\n10: \"author\": \"\",\n11: \"license\": \"ISC\",\n12: \"dependencies\": {\n13: \"@sourcegraph/amp\": \"^0.0.1772003388-gaa1ef1\",\n14: \"@types/node\": \"^22.13.11\",\n15: \"boxen\": \"^5.1.2\",\n16: \"chalk\": \"^4.1.2\",\n17: \"cli-highlight\": \"^2.1.11\",\n18: \"figures\": \"^3.2.0\",\n19: \"openai\": \"^6.25.0\",\n20: \"opencode-ai\": \"^1.2.12\",\n21: \"ora\": \"^5.4.1\",\n22: \"readline\": \"^1.3.0\"\n23: }\n24: }"
|
|
99
|
+
},
|
|
100
|
+
"trackFiles": [
|
|
101
|
+
"file:///home/runner/workspace/package.json"
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"role": "assistant",
|
|
109
|
+
"messageId": 3,
|
|
110
|
+
"content": [
|
|
111
|
+
{
|
|
112
|
+
"type": "thinking",
|
|
113
|
+
"thinking": "Let me look at the `handleUserInput` function more carefully - specifically around how it processes the API response, handles tool calls, and returns. The issue might be related to the process exiting unexpectedly. Let me read the middle section of the file.",
|
|
114
|
+
"signature": "Eq0DCkgICxACGAIqQEzjHmT7wcmN/uYuDK9Z1Iasam61AgPb8LaK6uFzWwy8CXjGjsPtpLYElbkFj8OF+VJbOoZcqnxpgGn+1tIkiLgSDDIu9pyjuE5YwKslqBoMVOw3w+cHp+RflU/UIjCfWHQ2v72KpFQyXTieoi0MAz200DhWujqrpn6a1pZV+J7kbhIcLZAhFknnl8TDFW4qkgJ07g/Cu/iYbmRv0GzVoEMqkaw6z5baWW36R9AHk0Vlyr/CQcZuwdaRvEqb34X8kdaO1TCYAri30xfne4puU6fV1gq8ViGueZBk/1ZaaJDD5S6QnNZsmgFV1h3lCyuKD/iRxrosvLZ2DKskTDE/1P3B1+CUdTq20domtgilNnau+jMnJoHhwpaGcXZhA2GXIU+y+mn7q2Q8AvLPLxYY12xNDZHKr1PDaPcXtAg2bXyUhUvbbsXFxDr0mGKcpnWBPluGYj0/zz2TdNdYQj3XezF9gbKha3wXBNBzZZ5pN9jOyK2CT1LaF1w3ZMU5+4iBKKA6wKFLChv6it2A/s3kWAYAGt/T3JJM3CXT2lwsF1NTv1a7GAE=",
|
|
115
|
+
"provider": "anthropic"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"type": "tool_use",
|
|
119
|
+
"complete": true,
|
|
120
|
+
"id": "toolu_vrtx_01SUbUCKqn666EizdozGwuzB",
|
|
121
|
+
"name": "Read",
|
|
122
|
+
"input": {
|
|
123
|
+
"path": "/home/runner/workspace/index.js",
|
|
124
|
+
"read_range": [
|
|
125
|
+
251,
|
|
126
|
+
500
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"state": {
|
|
132
|
+
"type": "complete",
|
|
133
|
+
"stopReason": "tool_use"
|
|
134
|
+
},
|
|
135
|
+
"usage": {
|
|
136
|
+
"model": "claude-opus-4-6",
|
|
137
|
+
"maxInputTokens": 168000,
|
|
138
|
+
"inputTokens": 1,
|
|
139
|
+
"outputTokens": 153,
|
|
140
|
+
"cacheCreationInputTokens": 8717,
|
|
141
|
+
"cacheReadInputTokens": 13086,
|
|
142
|
+
"totalInputTokens": 21804,
|
|
143
|
+
"timestamp": "2026-02-25T08:44:33.538Z"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"role": "user",
|
|
148
|
+
"messageId": 4,
|
|
149
|
+
"content": [
|
|
150
|
+
{
|
|
151
|
+
"type": "tool_result",
|
|
152
|
+
"toolUseID": "toolu_vrtx_01SUbUCKqn666EizdozGwuzB",
|
|
153
|
+
"run": {
|
|
154
|
+
"status": "done",
|
|
155
|
+
"progress": {},
|
|
156
|
+
"result": {
|
|
157
|
+
"absolutePath": "/home/runner/workspace/index.js",
|
|
158
|
+
"content": "[... omitted lines 1 to 250 ...]\n251: },\n252: {\n253: type: 'function',\n254: function: {\n255: name: 'UndoEdit',\n256: description: 'Undo the last edit made to a specific file, restoring its previous content.',\n257: parameters: {\n258: type: 'object',\n259: properties: {\n260: path: { type: 'string', description: 'File path to undo the last edit for.' },\n261: },\n262: required: ['path'],\n263: },\n264: },\n265: },\n266: {\n267: type: 'function',\n268: function: {\n269: name: 'Task',\n270: description: 'Spawn a sub-task by executing a sequence of shell commands for a complex multi-step operation. Useful for build-test-fix cycles.',\n271: parameters: {\n272: type: 'object',\n273: properties: {\n274: description: { type: 'string', description: 'Brief description of the task.' },\n275: commands: {\n276: type: 'array',\n277: description: 'Shell commands to execute in sequence. Stops on first failure.',\n278: items: { type: 'string' },\n279: },\n280: },\n281: required: ['description', 'commands'],\n282: },\n283: },\n284: },\n285: ];\n286: \n287: // ===== Tool Executors =====\n288: function truncateOutput(str) {\n289: if (str.length > MAX_OUTPUT_LEN) {\n290: return str.slice(0, MAX_OUTPUT_LEN) + `\\n... (truncated, ${str.length} chars total)`;\n291: }\n292: return str;\n293: }\n294: \n295: function resolvePath(p) {\n296: if (!p) return PROJECT_ROOT;\n297: return path.isAbsolute(p) ? p : path.resolve(PROJECT_ROOT, p);\n298: }\n299: \n300: function executeTool(name, args) {\n301: try {\n302: switch (name) {\n303: case 'Read': {\n304: const filePath = resolvePath(args.path);\n305: const stat = fs.statSync(filePath, { throwIfNoEntry: false });\n306: if (!stat) return `Error: File not found: ${filePath}`;\n307: if (stat.isDirectory()) return `Error: ${filePath} is a directory. Use ListDir instead.`;\n308: const content = fs.readFileSync(filePath, 'utf-8');\n309: const lines = content.split('\\n');\n310: const start = Math.max(0, (args.start_line || 1) - 1);\n311: const end = args.end_line ? Math.min(lines.length, args.end_line) : Math.min(lines.length, start + 500);\n312: const slice = lines.slice(start, end);\n313: const numbered = slice.map((l, i) => `${start + i + 1}: ${l}`).join('\\n');\n314: session.filesRead.add(filePath);\n315: if (end < lines.length) {\n316: return truncateOutput(numbered) + `\\n(showing lines ${start + 1}-${end} of ${lines.length})`;\n317: }\n318: return truncateOutput(numbered);\n319: }\n320: \n321: case 'Write': {\n322: const filePath = resolvePath(args.path);\n323: const dir = path.dirname(filePath);\n324: if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n325: const existed = fs.existsSync(filePath);\n326: const before = existed ? fs.readFileSync(filePath, 'utf-8') : null;\n327: fs.writeFileSync(filePath, args.content, 'utf-8');\n328: if (before !== null) {\n329: session.editHistory.push({ path: filePath, before, after: args.content, timestamp: Date.now() });\n330: }\n331: session.filesModified.add(filePath);\n332: const lines = args.content.split('\\n').length;\n333: return `${existed ? 'Overwritten' : 'Created'}: ${filePath} (${lines} lines)`;\n334: }\n335: \n336: case 'Edit': {\n337: const filePath = resolvePath(args.path);\n338: if (!fs.existsSync(filePath)) return `Error: File not found: ${filePath}`;\n339: const content = fs.readFileSync(filePath, 'utf-8');\n340: const count = content.split(args.old_str).length - 1;\n341: if (count === 0) return `Error: old_str not found in ${path.basename(filePath)}. Make sure it matches exactly (including whitespace and indentation).`;\n342: if (count > 1) return `Error: old_str found ${count} times in ${path.basename(filePath)}. It must be unique. Add more surrounding context to make it unique.`;\n343: const updated = content.replace(args.old_str, args.new_str);\n344: fs.writeFileSync(filePath, updated, 'utf-8');\n345: session.editHistory.push({ path: filePath, before: content, after: updated, timestamp: Date.now() });\n346: session.filesModified.add(filePath);\n347: // Generate a mini diff\n348: const oldLines = args.old_str.split('\\n');\n349: const newLines = args.new_str.split('\\n');\n350: let diff = `Edited: ${filePath}\\n`;\n351: oldLines.forEach(l => diff += `- ${l}\\n`);\n352: newLines.forEach(l => diff += `+ ${l}\\n`);\n353: return diff;\n354: }\n355: \n356: case 'Patch': {\n357: const filePath = resolvePath(args.path);\n358: if (!fs.existsSync(filePath)) return `Error: File not found: ${filePath}`;\n359: let content = fs.readFileSync(filePath, 'utf-8');\n360: const before = content;\n361: const results = [];\n362: for (let i = 0; i < args.edits.length; i++) {\n363: const edit = args.edits[i];\n364: if (!content.includes(edit.old_str)) {\n365: results.push(`Edit ${i + 1}: FAILED - old_str not found`);\n366: continue;\n367: }\n368: content = content.replace(edit.old_str, edit.new_str);\n369: results.push(`Edit ${i + 1}: OK`);\n370: }\n371: fs.writeFileSync(filePath, content, 'utf-8');\n372: session.editHistory.push({ path: filePath, before, after: content, timestamp: Date.now() });\n373: session.filesModified.add(filePath);\n374: return `Patched: ${filePath}\\n${results.join('\\n')}`;\n375: }\n376: \n377: case 'Bash': {\n378: const cwd = args.cwd ? resolvePath(args.cwd) : PROJECT_ROOT;\n379: session.commandsRun.push(args.command);\n380: try {\n381: const output = execSync(args.command, {\n382: encoding: 'utf-8',\n383: timeout: TOOL_TIMEOUT,\n384: cwd,\n385: maxBuffer: 1024 * 1024 * 5,\n386: stdio: ['pipe', 'pipe', 'pipe'],\n387: });\n388: return truncateOutput(output || '(no output)');\n389: } catch (err) {\n390: // Return both stdout and stderr on failure\n391: const stdout = err.stdout || '';\n392: const stderr = err.stderr || '';\n393: const exitCode = err.status || 1;\n394: return truncateOutput(`Exit code: ${exitCode}\\n${stdout}\\n${stderr}`.trim());\n395: }\n396: }\n397: \n398: case 'Grep': {\n399: const searchPath = resolvePath(args.path);\n400: const flags = args.case_sensitive ? '' : '-i';\n401: const include = args.include ? `--include='${args.include}'` : '';\n402: try {\n403: const cmd = `grep -rn ${flags} ${include} --color=never \"${args.pattern.replace(/\"/g, '\\\\\"')}\" \"${searchPath}\" 2>/dev/null | head -80`;\n404: const output = execSync(cmd, { encoding: 'utf-8', timeout: 15000 });\n405: return truncateOutput(output || 'No matches found.');\n406: } catch {\n407: return 'No matches found.';\n408: }\n409: }\n410: \n411: case 'Glob': {\n412: const cwd = args.cwd ? resolvePath(args.cwd) : PROJECT_ROOT;\n413: try {\n414: // Use find command to simulate glob\n415: const pattern = args.pattern;\n416: let cmd;\n417: if (pattern.includes('**')) {\n418: const namePattern = pattern.replace(/\\*\\*\\//g, '').replace(/\\*/g, '*');\n419: cmd = `find \"${cwd}\" -name \"${namePattern}\" -not -path \"*/node_modules/*\" -not -path \"*/.git/*\" 2>/dev/null | head -100`;\n420: } else {\n421: cmd = `find \"${cwd}\" -name \"${pattern}\" -not -path \"*/node_modules/*\" -not -path \"*/.git/*\" 2>/dev/null | head -100`;\n422: }\n423: const output = execSync(cmd, { encoding: 'utf-8', timeout: 10000 });\n424: if (!output.trim()) return 'No files found matching pattern.';\n425: // Make paths relative\n426: const files = output.trim().split('\\n').map(f => path.relative(cwd, f)).sort();\n427: return files.join('\\n');\n428: } catch {\n429: return 'No files found matching pattern.';\n430: }\n431: }\n432: \n433: case 'ListDir': {\n434: const dirPath = resolvePath(args.path);\n435: if (!fs.existsSync(dirPath)) return `Error: Directory not found: ${dirPath}`;\n436: const stat = fs.statSync(dirPath);\n437: if (!stat.isDirectory()) return `Error: ${dirPath} is not a directory.`;\n438: \n439: function listRecursive(dir, depth, maxDepth) {\n440: const entries = fs.readdirSync(dir, { withFileTypes: true })\n441: .filter(e => !e.name.startsWith('.') && e.name !== 'node_modules')\n442: .sort((a, b) => {\n443: if (a.isDirectory() && !b.isDirectory()) return -1;\n444: if (!a.isDirectory() && b.isDirectory()) return 1;\n445: return a.name.localeCompare(b.name);\n446: });\n447: const lines = [];\n448: for (const entry of entries) {\n449: const prefix = ' '.repeat(depth);\n450: if (entry.isDirectory()) {\n451: lines.push(`${prefix}${entry.name}/`);\n452: if (depth < maxDepth) {\n453: lines.push(...listRecursive(path.join(dir, entry.name), depth + 1, maxDepth));\n454: }\n455: } else {\n456: const size = fs.statSync(path.join(dir, entry.name)).size;\n457: const sizeStr = size < 1024 ? `${size}B` : size < 1024 * 1024 ? `${(size / 1024).toFixed(1)}K` : `${(size / (1024 * 1024)).toFixed(1)}M`;\n458: lines.push(`${prefix}${entry.name} (${sizeStr})`);\n459: }\n460: }\n461: return lines;\n462: }\n463: \n464: const maxDepth = args.recursive ? 3 : 0;\n465: const lines = listRecursive(dirPath, 0, maxDepth);\n466: return truncateOutput(lines.join('\\n') || '(empty directory)');\n467: }\n468: \n469: case 'UndoEdit': {\n470: const filePath = resolvePath(args.path);\n471: const lastEdit = [...session.editHistory].reverse().find(e => e.path === filePath);\n472: if (!lastEdit) return `Error: No edit history for ${filePath}`;\n473: fs.writeFileSync(filePath, lastEdit.before, 'utf-8');\n474: session.editHistory = session.editHistory.filter(e => e !== lastEdit);\n475: return `Undone last edit to ${filePath}`;\n476: }\n477: \n478: case 'Task': {\n479: const results = [];\n480: for (const cmd of args.commands) {\n481: try {\n482: const output = execSync(cmd, {\n483: encoding: 'utf-8',\n484: timeout: TOOL_TIMEOUT,\n485: cwd: PROJECT_ROOT,\n486: maxBuffer: 1024 * 1024 * 5,\n487: stdio: ['pipe', 'pipe', 'pipe'],\n488: });\n489: results.push(`✓ ${cmd}\\n${output.trim()}`);\n490: session.commandsRun.push(cmd);\n491: } catch (err) {\n492: results.push(`✗ ${cmd}\\nExit code: ${err.status}\\n${(err.stdout || '').trim()}\\n${(err.stderr || '').trim()}`);\n493: session.commandsRun.push(cmd);\n494: break; // Stop on first failure\n495: }\n496: }\n497: return truncateOutput(`Task: ${args.description}\\n${'─'.repeat(40)}\\n${results.join('\\n\\n')}`);\n498: }\n499: \n500: default:\n[... omitted lines 501 to 1152 ...]"
|
|
159
|
+
},
|
|
160
|
+
"trackFiles": [
|
|
161
|
+
"file:///home/runner/workspace/index.js"
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"role": "assistant",
|
|
169
|
+
"messageId": 5,
|
|
170
|
+
"content": [
|
|
171
|
+
{
|
|
172
|
+
"type": "tool_use",
|
|
173
|
+
"complete": true,
|
|
174
|
+
"id": "toolu_vrtx_019DrDQZAGa4EhRGsJj3SGAv",
|
|
175
|
+
"name": "Read",
|
|
176
|
+
"input": {
|
|
177
|
+
"path": "/home/runner/workspace/index.js",
|
|
178
|
+
"read_range": [
|
|
179
|
+
800,
|
|
180
|
+
935
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"state": {
|
|
186
|
+
"type": "complete",
|
|
187
|
+
"stopReason": "tool_use"
|
|
188
|
+
},
|
|
189
|
+
"usage": {
|
|
190
|
+
"model": "claude-opus-4-6",
|
|
191
|
+
"maxInputTokens": 168000,
|
|
192
|
+
"inputTokens": 1,
|
|
193
|
+
"outputTokens": 84,
|
|
194
|
+
"cacheCreationInputTokens": 3966,
|
|
195
|
+
"cacheReadInputTokens": 21803,
|
|
196
|
+
"totalInputTokens": 25770,
|
|
197
|
+
"timestamp": "2026-02-25T08:44:37.081Z"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"role": "user",
|
|
202
|
+
"messageId": 6,
|
|
203
|
+
"content": [
|
|
204
|
+
{
|
|
205
|
+
"type": "tool_result",
|
|
206
|
+
"toolUseID": "toolu_vrtx_019DrDQZAGa4EhRGsJj3SGAv",
|
|
207
|
+
"run": {
|
|
208
|
+
"status": "done",
|
|
209
|
+
"progress": {},
|
|
210
|
+
"result": {
|
|
211
|
+
"absolutePath": "/home/runner/workspace/index.js",
|
|
212
|
+
"content": "[... omitted lines 1 to 799 ...]\n800: { role: 'system', content: systemPrompt },\n801: ...session.conversationHistory,\n802: ];\n803: \n804: let iterations = 0;\n805: \n806: // Agentic tool-use loop\n807: while (iterations < MAX_TOOL_ITERATIONS) {\n808: iterations++;\n809: \n810: // Show thinking spinner while waiting for API\n811: const thinkSpinner = ora({\n812: text: t.dim(iterations === 1 ? 'Thinking...' : 'Reasoning...'),\n813: prefixText: ' ',\n814: spinner: 'dots',\n815: color: 'magenta',\n816: }).start();\n817: \n818: let response;\n819: try {\n820: response = await nvidiaClient.chat.completions.create({\n821: model: NVIDIA_MODEL,\n822: messages,\n823: max_tokens: 2048,\n824: temperature: 0.5,\n825: tools: toolDefs,\n826: tool_choice: 'auto',\n827: });\n828: } catch (apiErr) {\n829: thinkSpinner.stop();\n830: throw apiErr;\n831: }\n832: \n833: thinkSpinner.stop();\n834: \n835: const choice = response.choices[0];\n836: const msg = choice.message;\n837: turnTokens += response.usage?.total_tokens || 0;\n838: \n839: // If the model wants to call tools\n840: if (msg.tool_calls && msg.tool_calls.length > 0) {\n841: messages.push(msg);\n842: \n843: // Show intermediate reasoning if present\n844: if (msg.content && msg.content.trim()) {\n845: console.log(indent(t.dim.italic(msg.content.trim()), 6));\n846: console.log();\n847: }\n848: \n849: // Execute tool calls (parallel for independent calls)\n850: const toolPromises = msg.tool_calls.map(async (toolCall) => {\n851: const toolName = toolCall.function.name;\n852: let toolArgs;\n853: try {\n854: toolArgs = JSON.parse(toolCall.function.arguments);\n855: } catch {\n856: toolArgs = {};\n857: }\n858: \n859: const detail = toolDetail(toolName, toolArgs);\n860: const callStart = Date.now();\n861: const spinner = await showToolCall(toolName, detail, callStart);\n862: \n863: // Execute\n864: const result = executeTool(toolName, toolArgs);\n865: const success = !result.startsWith('Error');\n866: \n867: finishToolCall(spinner, toolName, detail, callStart, success);\n868: session.toolCallCount++;\n869: turnToolCalls++;\n870: \n871: // Show result preview\n872: const resultLines = result.split('\\n');\n873: let preview;\n874: if (toolName === 'Edit' || toolName === 'Patch') {\n875: // Show diff\n876: showDiff(toolArgs.path, result);\n877: } else if (resultLines.length > 5) {\n878: preview = resultLines.slice(0, 4).join('\\n') + `\\n... (${resultLines.length} lines)`;\n879: console.log(indent(t.dim(preview), 8));\n880: console.log();\n881: } else if (result.trim() && result !== '(no output)') {\n882: console.log(indent(t.dim(result.length > 300 ? result.slice(0, 297) + '...' : result), 8));\n883: console.log();\n884: }\n885: \n886: return { id: toolCall.id, result };\n887: });\n888: \n889: const toolResults = await Promise.all(toolPromises);\n890: \n891: for (const { id, result } of toolResults) {\n892: messages.push({\n893: role: 'tool',\n894: tool_call_id: id,\n895: content: result,\n896: });\n897: }\n898: \n899: // Check for stop condition\n900: if (choice.finish_reason === 'stop') break;\n901: continue;\n902: }\n903: \n904: // No tool calls — final text response\n905: if (msg.content) {\n906: showAssistantMessage(msg.content);\n907: session.conversationHistory.push({ role: 'assistant', content: msg.content });\n908: }\n909: break;\n910: }\n911: \n912: if (iterations >= MAX_TOOL_ITERATIONS) {\n913: console.log(indent(t.yellow(`⚠ Reached maximum tool iterations (${MAX_TOOL_ITERATIONS}). Stopping.`)));\n914: console.log();\n915: }\n916: \n917: const duration = ((Date.now() - startTime) / 1000).toFixed(1);\n918: session.totalTokens += turnTokens;\n919: showTurnSummary(turnTokens, duration, turnToolCalls);\n920: } catch (err) {\n921: console.log();\n922: console.log(indent(t.red('✗ Error: ') + t.text(err.message)));\n923: if (!process.env.NVIDIA_API_KEY) {\n924: console.log(indent(t.yellow('Set the NVIDIA_API_KEY environment variable with your API key from build.nvidia.com')));\n925: }\n926: console.log();\n927: }\n928: \n929: console.log(indent(hr()));\n930: isProcessing = false;\n931: if (rlClosed) process.exit(0);\n932: }\n933: \n934: // ===== Utilities =====\n935: function timestamp() {\n[... omitted lines 936 to 1152 ...]"
|
|
213
|
+
},
|
|
214
|
+
"trackFiles": [
|
|
215
|
+
"file:///home/runner/workspace/index.js"
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"role": "assistant",
|
|
223
|
+
"messageId": 7,
|
|
224
|
+
"content": [
|
|
225
|
+
{
|
|
226
|
+
"type": "thinking",
|
|
227
|
+
"thinking": "The issue is on line 900: when the model returns tool calls AND has `finish_reason === 'stop'`, it breaks out of the loop without continuing to get the final text response. But that's not really the process-exiting problem.\n\nLet me look more carefully. The process exiting could be related to readline. Let me check the `createPrompt` function and the readline setup.",
|
|
228
|
+
"signature": "EpgECkgICxACGAIqQJvn1Zu29S9wmjE8wW0YcdWrOO453A5XETOR6at6jZYFCZow2cgShG8JNcEW19QAOz3M9pRY2ToqiJ32ZTxpGkcSDD46Ni+zcWEe45xxThoMUg8BBGnRb0T7A9L5IjD3lq7I5auir44x3l4Z1WSHvavwJLlBQClno30T3lKFVnY5vnrXUNhrwzjwObgF10Iq/QInPpbjcNE4ljdODFGV3MsOeQg5oMM2VD2TfOI/HIBF2YbwDpfRwbmfVKJS3hET9FN1mi/g1fH91o4REV70i04HWBVT8M8kw+0QQEUkmFhZntq2a8vOWfPe6YNAqlnmWy/cw9MuM9oh2gjZd0WlgRuKLqetcw26e6YpgVLdwXrnRdLbEeHGrWPVfCBVyF0of2BwTfN0I5WXs1XQjkVSJhagdsz19fjhsrPZrTvG4ncyQ+NmfGX5PgkFY/yYXAQFEUTr96XPC1Ry0VOKn0K5w6YnRdboG3JojjhS83wVr51W7EvSHCFyZF9V4/wtYxyfPpTwKpD994grmUJ6UPozzWx1Pi7/a8Na7mqB9kg9K77wWFfSzupwwlKS5BZzA+FxhkiquwcIhWzoIklCsot/2LpspaIfC10FqIhIPc2CWzfebOrU/uaCqsraoIbNXRsnG539dIyBDqz3F0YZa1uOB24JzduICQ7MZa4OppAvTEqPIV/TO3i1C9gX3ZKiea0YAQ==",
|
|
229
|
+
"provider": "anthropic"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"type": "tool_use",
|
|
233
|
+
"complete": true,
|
|
234
|
+
"id": "toolu_vrtx_01JbEKQBsj7Ckikat71mRwFh",
|
|
235
|
+
"name": "Read",
|
|
236
|
+
"input": {
|
|
237
|
+
"path": "/home/runner/workspace/index.js",
|
|
238
|
+
"read_range": [
|
|
239
|
+
500,
|
|
240
|
+
800
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
"state": {
|
|
246
|
+
"type": "complete",
|
|
247
|
+
"stopReason": "tool_use"
|
|
248
|
+
},
|
|
249
|
+
"usage": {
|
|
250
|
+
"model": "claude-opus-4-6",
|
|
251
|
+
"maxInputTokens": 168000,
|
|
252
|
+
"inputTokens": 1,
|
|
253
|
+
"outputTokens": 184,
|
|
254
|
+
"cacheCreationInputTokens": 1695,
|
|
255
|
+
"cacheReadInputTokens": 25769,
|
|
256
|
+
"totalInputTokens": 27465,
|
|
257
|
+
"timestamp": "2026-02-25T08:44:42.749Z"
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"role": "user",
|
|
262
|
+
"messageId": 8,
|
|
263
|
+
"content": [
|
|
264
|
+
{
|
|
265
|
+
"type": "tool_result",
|
|
266
|
+
"toolUseID": "toolu_vrtx_01JbEKQBsj7Ckikat71mRwFh",
|
|
267
|
+
"run": {
|
|
268
|
+
"status": "done",
|
|
269
|
+
"progress": {},
|
|
270
|
+
"result": {
|
|
271
|
+
"absolutePath": "/home/runner/workspace/index.js",
|
|
272
|
+
"content": "[... omitted lines 1 to 499 ...]\n500: default:\n501: return `Unknown tool: ${name}`;\n502: }\n503: } catch (err) {\n504: return `Error executing ${name}: ${err.message}`;\n505: }\n506: }\n507: \n508: // ===== Theme =====\n509: const t = {\n510: brand: chalk.hex('#818cf8'),\n511: brandBold:chalk.hex('#818cf8').bold,\n512: accent: chalk.hex('#a78bfa'),\n513: dim: chalk.hex('#5a5a72'),\n514: muted: chalk.hex('#8888a0'),\n515: text: chalk.hex('#e4e4ed'),\n516: green: chalk.hex('#22c55e'),\n517: greenBg: chalk.bgHex('#22c55e').hex('#000'),\n518: yellow: chalk.hex('#eab308'),\n519: yellowBg: chalk.bgHex('#eab308').hex('#000'),\n520: red: chalk.hex('#ef4444'),\n521: redBg: chalk.bgHex('#ef4444').hex('#fff'),\n522: blue: chalk.hex('#3b82f6'),\n523: blueBg: chalk.bgHex('#3b82f6').hex('#fff'),\n524: cyan: chalk.hex('#22d3ee'),\n525: orange: chalk.hex('#f97316'),\n526: orangeBg: chalk.bgHex('#f97316').hex('#000'),\n527: purple: chalk.hex('#a855f7'),\n528: purpleBg: chalk.bgHex('#a855f7').hex('#fff'),\n529: bar: chalk.hex('#2a2a3a'),\n530: codeBg: chalk.bgHex('#16161f'),\n531: };\n532: \n533: // ===== Layout Helpers =====\n534: const COLS = Math.min(process.stdout.columns || 80, 120);\n535: \n536: function hr(char = '─', color = t.bar) {\n537: return color(char.repeat(COLS));\n538: }\n539: \n540: function stripAnsi(str) {\n541: return str.replace(/\\x1b\\[[0-9;]*m/g, '');\n542: }\n543: \n544: function indent(str, n = 2) {\n545: const prefix = ' '.repeat(n);\n546: return str.split('\\n').map(l => prefix + l).join('\\n');\n547: }\n548: \n549: // ===== Header =====\n550: function showHeader() {\n551: console.clear();\n552: let branch = 'main';\n553: try { branch = execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', { encoding: 'utf-8', cwd: PROJECT_ROOT }).trim(); } catch {}\n554: \n555: const logo = t.brandBold('⬡ Apex') + t.accent(' AI');\n556: const model = t.dim('model: ') + t.text(NVIDIA_MODEL);\n557: const branchLabel = t.brand('⎇') + t.accent(` ${branch}`);\n558: const status = t.green(figures.bullet) + t.dim(' connected');\n559: \n560: console.log();\n561: console.log(indent(`${logo} ${t.bar('│')} ${model} ${t.bar('│')} ${branchLabel} ${t.bar('│')} ${status}`));\n562: console.log(indent(hr()));\n563: console.log();\n564: }\n565: \n566: // ===== Welcome =====\n567: function showWelcome() {\n568: const title = t.text.bold('What can I help you build?');\n569: const subtitle = t.muted('I can read, write, execute code, and autonomously complete tasks in your project.');\n570: \n571: console.log(indent(title));\n572: console.log(indent(subtitle));\n573: console.log();\n574: \n575: const actions = [\n576: [t.blue(figures.info), t.muted('Explore & explain the codebase')],\n577: [t.red(figures.cross), t.muted('Find & fix bugs autonomously')],\n578: [t.green(figures.tick), t.muted('Write & run tests')],\n579: [t.yellow(figures.warning), t.muted('Refactor & optimize')],\n580: [t.cyan('⚡'), t.muted('Build features end-to-end')],\n581: [t.purple('⎇'), t.muted('Git operations & code review')],\n582: ];\n583: \n584: actions.forEach(([icon, label]) => {\n585: console.log(indent(` ${icon} ${label}`));\n586: });\n587: console.log();\n588: console.log(indent(t.dim(`Tools: Read, Write, Edit, Patch, Bash, Grep, Glob, ListDir, UndoEdit, Task`)));\n589: console.log(indent(t.dim(`Max ${MAX_TOOL_ITERATIONS} autonomous tool calls per turn`)));\n590: console.log();\n591: console.log(indent(hr()));\n592: console.log();\n593: }\n594: \n595: // ===== Message Display =====\n596: function showUserMessage(text) {\n597: const header = t.blueBg(' U ') + ' ' + chalk.white.bold('You') + ' ' + t.dim(timestamp());\n598: console.log(indent(header));\n599: console.log(indent(t.text(text), 6));\n600: console.log();\n601: }\n602: \n603: function showAssistantHeader() {\n604: const header = t.brand('✦') + ' ' + t.brandBold('Apex AI') + ' ' + t.dim(timestamp());\n605: console.log(indent(header));\n606: }\n607: \n608: function showAssistantMessage(text) {\n609: const lines = text.split('\\n');\n610: const formatted = [];\n611: let inCodeBlock = false;\n612: let codeLines = [];\n613: let codeLang = '';\n614: \n615: for (const line of lines) {\n616: if (line.startsWith('```') && !inCodeBlock) {\n617: inCodeBlock = true;\n618: codeLang = line.slice(3).trim() || 'code';\n619: codeLines = [];\n620: } else if (line.startsWith('```') && inCodeBlock) {\n621: inCodeBlock = false;\n622: formatted.push(renderCodeBlock(codeLines.join('\\n'), codeLang));\n623: } else if (inCodeBlock) {\n624: codeLines.push(line);\n625: } else {\n626: const processed = line.replace(/`([^`]+)`/g, (_, code) => t.cyan(code));\n627: formatted.push(t.text(processed));\n628: }\n629: }\n630: \n631: console.log(indent(formatted.join('\\n'), 4));\n632: console.log();\n633: }\n634: \n635: // ===== Code Block =====\n636: function renderCodeBlock(code, lang) {\n637: const width = Math.min(COLS - 8, 80);\n638: const topBar = t.dim('┌─') + t.accent(` ${lang} `) + t.dim('─'.repeat(Math.max(0, width - lang.length - 4)) + '┐');\n639: const bottomBar = t.dim('└' + '─'.repeat(width) + '┘');\n640: \n641: let highlighted;\n642: try {\n643: highlighted = highlight(code, { language: lang, ignoreIllegals: true });\n644: } catch {\n645: highlighted = t.text(code);\n646: }\n647: \n648: const cLines = highlighted.split('\\n').map((line, i) => {\n649: const lineNo = t.dim(String(i + 1).padStart(3) + ' │ ');\n650: return t.dim('│') + lineNo + line;\n651: });\n652: \n653: return [topBar, ...cLines, bottomBar].join('\\n');\n654: }\n655: \n656: // ===== Tool Badges =====\n657: function toolBadge(name) {\n658: const badges = {\n659: 'Read': t.blueBg(` ${name} `),\n660: 'Edit': t.yellowBg(` ${name} `),\n661: 'Write': t.yellowBg(` ${name} `),\n662: 'Patch': t.orangeBg(` ${name} `),\n663: 'Bash': t.greenBg(` ${name} `),\n664: 'Grep': t.purpleBg(` ${name} `),\n665: 'Glob': t.purpleBg(` ${name} `),\n666: 'ListDir': chalk.bgHex('#06b6d4').hex('#000')(` ${name} `),\n667: 'UndoEdit': t.redBg(` ${name} `),\n668: 'Task': t.orangeBg(` ${name} `),\n669: };\n670: return badges[name] || chalk.bgHex('#6366f1').hex('#fff')(` ${name} `);\n671: }\n672: \n673: function toolDetail(name, args) {\n674: switch (name) {\n675: case 'Bash': return args.command || '';\n676: case 'Grep': return `\"${args.pattern}\"${args.path ? ` in ${args.path}` : ''}`;\n677: case 'Glob': return args.pattern || '';\n678: case 'ListDir': return args.path || '.';\n679: case 'Read': {\n680: let d = args.path || '';\n681: if (args.start_line) d += `:${args.start_line}-${args.end_line || ''}`;\n682: return d;\n683: }\n684: case 'Write': return args.path || '';\n685: case 'Edit': return args.path || '';\n686: case 'Patch': return `${args.path} (${(args.edits || []).length} edits)`;\n687: case 'UndoEdit': return args.path || '';\n688: case 'Task': return args.description || '';\n689: default: return JSON.stringify(args).slice(0, 80);\n690: }\n691: }\n692: \n693: // ===== Tool Call Display =====\n694: async function showToolCall(name, detail, startTime) {\n695: const spinner = ora({\n696: text: `${toolBadge(name)} ${t.muted(detail.length > 80 ? detail.slice(0, 77) + '...' : detail)}`,\n697: prefixText: ' ',\n698: spinner: 'dots',\n699: color: 'magenta',\n700: }).start();\n701: \n702: return spinner;\n703: }\n704: \n705: function finishToolCall(spinner, name, detail, startTime, success = true) {\n706: const elapsed = Date.now() - startTime;\n707: const icon = success ? t.green(figures.tick) : t.red(figures.cross);\n708: const timeStr = elapsed < 1000 ? `${elapsed}ms` : `${(elapsed / 1000).toFixed(1)}s`;\n709: \n710: spinner.stopAndPersist({\n711: symbol: icon,\n712: text: `${toolBadge(name)} ${t.dim(detail.length > 80 ? detail.slice(0, 77) + '...' : detail)} ${t.dim(timeStr)}`,\n713: prefixText: ' ',\n714: });\n715: }\n716: \n717: // ===== Diff Display =====\n718: function showDiff(filename, diffText) {\n719: const width = Math.min(COLS - 8, 80);\n720: console.log(indent(t.dim('┌─ ') + t.text.bold(path.basename(filename)) + t.dim(' ' + '─'.repeat(Math.max(0, width - path.basename(filename).length - 4)))));\n721: \n722: const lines = diffText.split('\\n');\n723: for (const line of lines) {\n724: if (line.startsWith('+')) {\n725: console.log(indent(chalk.green('│ ' + line)));\n726: } else if (line.startsWith('-')) {\n727: console.log(indent(chalk.red('│ ' + line)));\n728: }\n729: }\n730: \n731: console.log(indent(t.dim('└' + '─'.repeat(width))));\n732: console.log();\n733: }\n734: \n735: // ===== Cost Summary =====\n736: function showTurnSummary(tokens, duration, toolCalls) {\n737: const costPerToken = 0.000002;\n738: const cost = tokens * costPerToken;\n739: session.totalCost += cost;\n740: \n741: const items = [\n742: t.dim('Tokens ') + t.text(tokens.toLocaleString()),\n743: t.dim('Cost ') + t.text('$' + cost.toFixed(4)),\n744: t.dim('Duration ') + t.text(duration + 's'),\n745: t.dim('Tools ') + t.text(toolCalls.toString()),\n746: ];\n747: \n748: if (session.filesModified.size > 0) {\n749: items.push(t.dim('Modified ') + t.text([...session.filesModified].map(f => path.basename(f)).join(', ')));\n750: }\n751: \n752: const box = boxen(items.join('\\n'), {\n753: padding: { left: 1, right: 1, top: 0, bottom: 0 },\n754: borderColor: '#2a2a3a',\n755: borderStyle: 'round',\n756: dimBorder: true,\n757: });\n758: console.log(indent(box, 4));\n759: console.log();\n760: }\n761: \n762: // ===== Interactive Prompt =====\n763: function createPrompt() {\n764: const rl = readline.createInterface({\n765: input: process.stdin,\n766: output: process.stdout,\n767: prompt: '',\n768: });\n769: return rl;\n770: }\n771: \n772: function showPrompt() {\n773: console.log();\n774: console.log(' ' + t.dim('Enter to send · /help for commands'));\n775: return ' ' + t.brand('❯ ');\n776: }\n777: \n778: // ===== State =====\n779: let isProcessing = false;\n780: let rlClosed = false;\n781: \n782: // ===== AI Conversation — Agentic Loop =====\n783: async function handleUserInput(userInput) {\n784: isProcessing = true;\n785: session.turnCount++;\n786: showUserMessage(userInput);\n787: \n788: session.conversationHistory.push({ role: 'user', content: userInput });\n789: \n790: const startTime = Date.now();\n791: let turnTokens = 0;\n792: let turnToolCalls = 0;\n793: \n794: try {\n795: showAssistantHeader();\n796: console.log();\n797: \n798: const systemPrompt = buildSystemPrompt();\n799: let messages = [\n800: { role: 'system', content: systemPrompt },\n[... omitted lines 801 to 1152 ...]"
|
|
273
|
+
},
|
|
274
|
+
"trackFiles": [
|
|
275
|
+
"file:///home/runner/workspace/index.js"
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"role": "assistant",
|
|
283
|
+
"messageId": 9,
|
|
284
|
+
"content": [
|
|
285
|
+
{
|
|
286
|
+
"type": "thinking",
|
|
287
|
+
"thinking": "I can see the issue now. The `rl.question` callback on line 964 uses `async` but the `askQuestion` function doesn't await the async operation. However, the real problem is likely that when `rl.question` is called, the readline interface might be closing because there's nothing keeping the event loop alive, or the readline interface itself is being closed.\n\nWait, actually, looking more carefully at lines 960-994:\n\n```javascript\nconst askQuestion = () => {\n if (rlClosed) return;\n const promptStr = showPrompt();\n\n rl.question(promptStr, async (answer) => {\n\n\n```\n\nThe callback handles null/undefined answers by exiting, trims the input, and recursively calls `askQuestion` for empty inputs. It also processes slash commands and exit commands, with the exit path logging a session summary before closing.\n\nFor regular user input, it wraps the async `handleUserInput` call in a try-catch to gracefully handle errors, then loops back to `askQuestion`. I'm noticing the readline stays open through this pattern, but there might be an issue with the `rl.on('close')` event handler setting `rlClosed = true` if stdin closes unexpectedly, like in non-TTY environments.\n\nLooking more carefully at the logic: when the model returns tool calls with `finish_reason === 'stop'`, it processes those calls but breaks out of the loop without sending the results back to get a final response from the model. This means the user gets no final message and control returns to the prompt, though this wouldn't cause an exit by itself.\n\nThe real issue might be with how the readline 'close' event is being handled—I need to examine that more carefully to see if something's triggering stdin to close prematurely. ...awaited. But if there's an unhandled promise rejection or an error that causes the process to exit, that would explain it. Let me think about this differently—the user says the CLI exits right after responding, which means `handleUserInput` completes but then something closes the readline interface before `askQuestion()` can be called again. I'm wondering if `ora` is interfering with readline when it manipulates the TTY, or if there's an issue in the Bash tool executor that's causing an unexpected exit. I'm looking at how the readline interface is set up and how it handles stdin closure. When stdin ends, the readline emits a 'close' event that triggers `process.exit(0)`, but there's also a check at the end of `handleUserInput` that exits if the readline is already closed. Let me trace through what happens when the user provides input to see where the premature exit is occurring. set to true, and then when `handleUserInput` finishes processing, it calls `process.exit(0)`. So the ora spinner is likely interfering with readline's raw mode, causing it to close prematurely while the async operations are still running.\n\nThe fix is probably to either prevent ora from interfering with stdin, recreate the readline interface when it closes unexpectedly, or avoid exiting immediately when readline closes—instead checking whether the close was user-initiated or caused by external interference.\n\nBut I'm wondering if this could be a Replit-specific issue where stdin closes after the first input. The real problem might be in the async flow: when `rl.question`'s callback is async and `handleUserInput` throws an unexpected error, the process could crash without proper cleanup.\n\nLooking at the flow more carefully, I suspect `ora` is the culprit—it can interfere with readline by triggering a 'close' event. The solution would be to avoid calling `process.exit(0)` in the close handler and instead just flag that readline is closed, then check that flag before trying to prompt again. I'm wondering if the readline interface itself has a limitation with how it handles repeated `rl.question()` calls after async operations, or if something in the flow is inadvertently closing it—maybe ora or one of the tool calls is interfering with the stdin/stdout that readline depends on. I'm realizing the issue is that `rl` is scoped to the `main` function, so I can't easily recreate it from within `handleUserInput`. The cleanest approach would be to move the readline interface to a higher scope or refactor how we handle the input loop so we can properly reinitialize it when it closes unexpectedly. The readline 'close' event fires when the input stream ends, `rl.close()` is called, or the user presses Ctrl+D, so I need to figure out which scenario is actually happening here. I'm wondering if `execSync` with its pipe configuration might be interfering with the parent process's stdin in some edge case. Actually, I think the real issue might be that `askQuestion` isn't properly async-aware—the `rl.question` callback is async but doesn't return a promise, so after `handleUserInput` completes and `askQuestion` is called again, there's nothing keeping the event loop alive except the readline interface itself.\n\nIf the readline gets closed during processing, `rl.question` won't work and the process will exit naturally without needing `process.exit(0)`. The fix could be to either remove that explicit exit call and let `askQuestion` handle a closed readline by recreating it, or check the state before calling `rl.question` again. I'm reconsidering whether the real issue is that the process exits because there are no event listeners keeping it alive after `handleUserInput` completes. If `rlClosed` is false, the code should call `askQuestion()` again, but maybe something else is causing the process to terminate before that happens.\n\nThe most likely culprits are `ora` interfering with readline or the readline interface getting closed during tool execution. I should refactor this to use a loop-based approach instead of recursive `rl.question` calls, and make sure the readline interface is properly maintained throughout execution.\n\nLooking back at that `rlClosed` check on line 931—it's inside the callback, so if readline closes while the AI is thinking, it exits immediately. But the real question is whether `rl.question` even works after `handleUserInput` returns, or if something about the readline state is getting corrupted.\n\nLet me reconsider the ora library angle. It shouldn't touch stdin by default, but maybe there's a version-specific issue with how it handles the terminal state or if it's somehow interfering with the readline interface itself.\n\nActually, I'm probably overcomplicating this. Let me trace through what's happening after the user input is processed and see where things might be breaking down. I see the structure now—`main()` returns immediately since `rl.question()` is callback-based, but the readline interface keeps the event loop alive. After each user input is handled, `askQuestion()` gets called again to prompt for the next input, so the process should continue running unless something explicitly closes the readline interface or stdin.\n\nLet me step back and think about what might actually be causing the issue. I'm wondering if the problem is with the API call itself—if the NVIDIA API returns an error, the catch block re-throws it, which gets caught by the outer try-catch that logs the error. But then execution should continue normally through the loop. Let me trace through the catch block more carefully to see where the flow actually goes.\n\nActually, I think I've been overcomplicating this. The real issue might be that after the response completes, the process exits because there's nothing keeping the event loop alive. If readline is somehow closed or paused, even though `rlClosed` shows false, Node.js would exit once there are no active timers or I/O operations. I'm suspecting that either `process.stdin.unref()` is being called somewhere, or stdin is ending unexpectedly.\n\nLet me think about another angle: what if the callback in `readline.question` is async, and an unhandled promise rejection inside it is causing the process to exit? There's a try-catch around `handleUserInput`, but maybe that's not catching everything.\n\nI think the most practical solution is to make the main loop more resilient—either by using a while loop with `process.stdin.on('data')`, or as a safety net, adding a `setInterval` to keep the process alive and recreating readline if needed.\n\nActually, the simplest fix is to just recreate the readline interface instead of exiting. I'm setting up a module-level readline instance and a function to reinitialize it, then in the close handler, I check if stdin is still readable and reopen the prompt if the process isn't currently handling something.\n\nImplementing readline recreation logic...\n\nWait, I'm overcomplicating this. The real issue is probably that `execSync` is pausing stdin, which makes readline think the stream has ended. That's a much more likely culprit than the terminal actually closing during interactive use.\n\nThe fix is straightforward: when the readline 'close' event fires, I should check if stdin is actually destroyed or unreadable before exiting. If it's still functional, I can just suppress the close event and keep the CLI running. I'm realizing the current approach mirrors what's already there, so the issue must be elsewhere. Let me try configuring the spinner to write to stderr explicitly instead of interfering with stdin, which might be corrupting the readline interface's state.\n\nActually, ora already defaults to stderr, so that's not it. I'm wondering if this is a Node.js event loop problem—maybe the readline interface is getting closed prematurely and there are no active handles keeping the process alive. Let me test with a simple interval to see if that's what's draining the event loop, though that's more of a diagnostic hack than a real fix.\n\nFrom the user's perspective, the tool just exits after responding, which suggests the process is terminating when it shouldn't be. I'm noticing the `rl.on('close')` handler might be the culprit—it's calling `process.exit` in certain conditions, and if the readline is closing unexpectedly, that would explain why the CLI exits instead of waiting for the next input. the process exits at step 8. But this would happen between questions, not immediately after the response. The user's description of \"after it responded to my request\" suggests the first scenario where readline closes during processing. So I need to fix this by checking the `rlClosed` flag before setting `isProcessing` to false, rather than after. of exiting, re-create the readline and continue. Or I could figure out why readline closes during processing and prevent it from happening in the first place.\n\nSince I can't easily pinpoint whether it's ora, execSync, or something Replit-specific causing the closure, the safest approach is to just recreate readline when needed. I'll restructure the code to make `rl` and `askQuestion` accessible at the module level, add a setup function to reinitialize readline, and then call that instead of exiting at line 931.\n\nActually, let me think about this differently. What if the real issue is that `main()` returns before `rl.question` gets a chance to run? No, that doesn't make sense—`rl.question` is called synchronously within `askQuestion`, which happens before `main` returns, and readline keeps the event loop alive through its stdin reference.\n\nI think an unhandled promise rejection might be the culprit here. If an async callback throws and the caller doesn't properly handle promises, the rejection could silently crash things. The try-catch inside the callback should catch errors, but maybe something's slipping through after the catch block...\n\nExamining the error handling... I'm tracing through the execution flow—after `handleUserInput` completes, if `rlClosed` was set to true during that call, the process exits at line 931 before `askQuestion()` even gets invoked. So the real question is what's causing readline to close in the first place during `handleUserInput`.\n\nThe pragmatic solution is to make the readline interface recreatable so that when it closes unexpectedly during processing, we can rebuild it instead of letting the process terminate.\n\nRefactoring the code... me implement this.\n\nActually, let me step back and think about what the simplest effective fix is. I want to:\n1. Prevent readline from closing during processing (if possible)\n2. If it does close, re-create it\n\nFor (1), I can try `process.stdin.resume()` at strategic points.\nFor (2), I can restructure the code to re-create readline.\n\nActually, let me try a much simpler approach first. What if the issue is that `ora` spinner is somehow breaking readline, and the fix is to just not use ora? Or to use a simpler spinner?\n\nNo, that's too drastic. Let me try the re-create approach.\n\nHere's my plan:\n1. Move `rl` to module level\n2. Create a `setupReadline()` function\n3. In `handleUserInput`, at line 931, call `setupReadline()` instead of `process.exit(0)`\n4. Make `askQuestion` a module-level function\n\nActually, there's an even simpler fix. What if I just remove line 931 entirely? Then readline closes during processing, `rlClosed` gets set to true and the close handler returns since we're still processing, `handleUserInput` finishes and clears the flag, line 931 is gone so execution continues, `askQuestion()` gets called but returns immediately because readline is closed, and nothing keeps the event loop alive so the process exits naturally. But that means no goodbye message and a silent exit, which isn't great.\n\nThe best approach is definitely to re-create readline properly.\n\nActually, I'm now thinking about keeping stdin alive by calling `process.stdin.ref()` and then creating a new readline interface in the close handler. I'd need to be careful about how the handlers are attached, but this could work. Let me just implement the restructuring: I'll move readline to module level, create a function to set it up, and have the close handler re-create it if stdin is still available instead of exiting.\n\nBut this is getting complicated. The simpler approach is probably just to handle the `rlClosed` case by recreating readline...\n\nStill writing handler logic... I'm tracing through the execution flow to understand how `askQuestion` and `handleUserInput` interact. The key insight is that `askQuestion` is defined inside `main` and closes over the local `rl` variable, while `handleUserInput` is module-level and can't access it. When a user enters input, the callback fires `handleUserInput`, which then calls `askQuestion` again to prompt for the next question—so the readline instance stays alive throughout this cycle.\n\nBut I'm realizing the real problem might not be readline closing unexpectedly at all. The async callback in `rl.question` could be throwing an unhandled error that's crashing the process silently.\n\nActually, wait—there's a try-catch around `handleUserInput`, so that should be catching errors. Unless something's going wrong in `askQuestion` itself after the callback completes. Let me just test the readline re-creation approach since that's the most straightforward fix.\n\nBut first, I'm checking whether calling `rl.question()` on a closed readline interface throws an error. According to the Node.js docs, it does—it throws an `ERR_USE_AFTER_CLOSE` error. The `rlClosed` check prevents that, but then `askQuestion` returns early and nothing keeps the process alive. So I need to restructure this: move the readline instance to module level, create a setup function for it, and rebuild the interface when needed.\n\nActually, I'm realizing there might be a simpler root cause. The issue could be that `rl.question()` doesn't automatically resume stdin if it's been paused—maybe by ora or execSync cleanup. So the quickest fix might just be to explicitly resume stdin before calling `rl.question()`.\n\nWriting the fix...\n\nBut I should also consider the Replit environment specifically. Since Replit uses a web-based terminal over WebSocket, a brief connection interruption could cause stdin to receive an EOF and close readline unexpectedly. So the real solution needs to detect when readline closes while stdin is still available and reinitialize it.\n\nI'm going to refactor this by moving the readline interface and question handler to module level, then create a setup function that initializes the interface and handles reconnection if it closes. This way I can check if stdin is still usable and recreate the readline interface rather than exiting completely.\n\nImplementing the fix now...",
|
|
288
|
+
"signature": "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",
|
|
289
|
+
"provider": "anthropic"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"type": "text",
|
|
293
|
+
"text": "The issue is that if the readline interface closes during processing (e.g., due to terminal/environment quirks), the process exits at line 931 instead of re-prompting. Let me fix this by making readline re-creatable."
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"type": "tool_use",
|
|
297
|
+
"complete": true,
|
|
298
|
+
"id": "toolu_vrtx_01EpEEL8W8rc32JaDS9E6Y4q",
|
|
299
|
+
"name": "edit_file",
|
|
300
|
+
"input": {
|
|
301
|
+
"path": "/home/runner/workspace/index.js",
|
|
302
|
+
"old_str": "// ===== State =====\nlet isProcessing = false;\nlet rlClosed = false;",
|
|
303
|
+
"new_str": "// ===== State =====\nlet isProcessing = false;\nlet rlClosed = false;\nlet rl;\nlet askQuestion;"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
"state": {
|
|
308
|
+
"type": "complete",
|
|
309
|
+
"stopReason": "tool_use"
|
|
310
|
+
},
|
|
311
|
+
"usage": {
|
|
312
|
+
"model": "claude-opus-4-6",
|
|
313
|
+
"maxInputTokens": 168000,
|
|
314
|
+
"inputTokens": 1,
|
|
315
|
+
"outputTokens": 11531,
|
|
316
|
+
"cacheCreationInputTokens": 4407,
|
|
317
|
+
"cacheReadInputTokens": 27464,
|
|
318
|
+
"totalInputTokens": 31872,
|
|
319
|
+
"timestamp": "2026-02-25T08:48:12.805Z"
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"role": "user",
|
|
324
|
+
"messageId": 10,
|
|
325
|
+
"content": [
|
|
326
|
+
{
|
|
327
|
+
"type": "tool_result",
|
|
328
|
+
"toolUseID": "toolu_vrtx_01EpEEL8W8rc32JaDS9E6Y4q",
|
|
329
|
+
"run": {
|
|
330
|
+
"status": "done",
|
|
331
|
+
"progress": {},
|
|
332
|
+
"result": {
|
|
333
|
+
"diff": "```diff\nIndex: /home/runner/workspace/index.js\n===================================================================\n--- /home/runner/workspace/index.js\toriginal\n+++ /home/runner/workspace/index.js\tmodified\n@@ -777,8 +777,10 @@\n \n // ===== State =====\n let isProcessing = false;\n let rlClosed = false;\n+let rl;\n+let askQuestion;\n \n // ===== AI Conversation — Agentic Loop =====\n async function handleUserInput(userInput) {\n isProcessing = true;\n```",
|
|
334
|
+
"lineRange": [
|
|
335
|
+
778,
|
|
336
|
+
782
|
|
337
|
+
]
|
|
338
|
+
},
|
|
339
|
+
"trackFiles": [
|
|
340
|
+
"file:///home/runner/workspace/index.js"
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"role": "assistant",
|
|
348
|
+
"messageId": 11,
|
|
349
|
+
"content": [
|
|
350
|
+
{
|
|
351
|
+
"type": "tool_use",
|
|
352
|
+
"complete": true,
|
|
353
|
+
"id": "toolu_vrtx_01XN6ZijQ95qQ1guoX6UVKHL",
|
|
354
|
+
"name": "edit_file",
|
|
355
|
+
"input": {
|
|
356
|
+
"path": "/home/runner/workspace/index.js",
|
|
357
|
+
"old_str": " console.log(indent(hr()));\n isProcessing = false;\n if (rlClosed) process.exit(0);\n}",
|
|
358
|
+
"new_str": " console.log(indent(hr()));\n isProcessing = false;\n if (rlClosed) {\n // Readline closed during processing — re-create it if stdin is still usable\n if (!process.stdin.destroyed && process.stdin.readable) {\n setupInputLoop();\n askQuestion();\n return;\n }\n process.exit(0);\n }\n}"
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
],
|
|
362
|
+
"state": {
|
|
363
|
+
"type": "complete",
|
|
364
|
+
"stopReason": "tool_use"
|
|
365
|
+
},
|
|
366
|
+
"usage": {
|
|
367
|
+
"model": "claude-opus-4-6",
|
|
368
|
+
"maxInputTokens": 168000,
|
|
369
|
+
"inputTokens": 1,
|
|
370
|
+
"outputTokens": 224,
|
|
371
|
+
"cacheCreationInputTokens": 11493,
|
|
372
|
+
"cacheReadInputTokens": 31871,
|
|
373
|
+
"totalInputTokens": 43365,
|
|
374
|
+
"timestamp": "2026-02-25T08:48:17.862Z"
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"role": "user",
|
|
379
|
+
"messageId": 12,
|
|
380
|
+
"content": [
|
|
381
|
+
{
|
|
382
|
+
"type": "tool_result",
|
|
383
|
+
"toolUseID": "toolu_vrtx_01XN6ZijQ95qQ1guoX6UVKHL",
|
|
384
|
+
"run": {
|
|
385
|
+
"status": "done",
|
|
386
|
+
"progress": {},
|
|
387
|
+
"result": {
|
|
388
|
+
"diff": "```diff\nIndex: /home/runner/workspace/index.js\n===================================================================\n--- /home/runner/workspace/index.js\toriginal\n+++ /home/runner/workspace/index.js\tmodified\n@@ -929,10 +929,18 @@\n }\n \n console.log(indent(hr()));\n isProcessing = false;\n- if (rlClosed) process.exit(0);\n+ if (rlClosed) {\n+ // Readline closed during processing — re-create it if stdin is still usable\n+ if (!process.stdin.destroyed && process.stdin.readable) {\n+ setupInputLoop();\n+ askQuestion();\n+ return;\n }\n+ process.exit(0);\n+ }\n+}\n \n // ===== Utilities =====\n function timestamp() {\n return new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n```",
|
|
389
|
+
"lineRange": [
|
|
390
|
+
931,
|
|
391
|
+
942
|
|
392
|
+
]
|
|
393
|
+
},
|
|
394
|
+
"trackFiles": [
|
|
395
|
+
"file:///home/runner/workspace/index.js"
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"role": "assistant",
|
|
403
|
+
"messageId": 13,
|
|
404
|
+
"content": [
|
|
405
|
+
{
|
|
406
|
+
"type": "text",
|
|
407
|
+
"text": "Now refactor `main()` to use a `setupInputLoop` function:"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"type": "tool_use",
|
|
411
|
+
"complete": true,
|
|
412
|
+
"id": "toolu_vrtx_01RnzYS8fsPwqpnrEuA4kX8Z",
|
|
413
|
+
"name": "edit_file",
|
|
414
|
+
"input": {
|
|
415
|
+
"path": "/home/runner/workspace/index.js",
|
|
416
|
+
"old_str": "// ===== Main Loop =====\nasync function main() {\n showHeader();\n showWelcome();\n\n const rl = createPrompt();\n\n rl.on('close', () => {\n rlClosed = true;\n if (isProcessing) return;\n console.log();\n showSessionSummary();\n console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n console.log();\n process.exit(0);\n });\n\n const askQuestion = () => {\n if (rlClosed) return;\n const promptStr = showPrompt();\n\n rl.question(promptStr, async (answer) => {\n if (answer === null || answer === undefined) {\n process.exit(0);\n }\n const input = answer.trim();\n\n if (!input) { askQuestion(); return; }\n\n // Slash commands\n if (input.startsWith('/')) {\n handleSlashCommand(input, rl);\n askQuestion();\n return;\n }\n\n if (input === 'exit' || input === 'quit') {\n console.log();\n showSessionSummary();\n console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n console.log();\n process.exit(0);\n }\n\n try {\n await handleUserInput(input);\n } catch (err) {\n console.log(indent(t.red('✗ Unexpected error: ') + t.text(err.message)));\n console.log();\n }\n askQuestion();\n });\n };\n\n askQuestion();\n}",
|
|
417
|
+
"new_str": "// ===== Input Loop =====\nfunction setupInputLoop() {\n rlClosed = false;\n rl = createPrompt();\n\n rl.on('close', () => {\n rlClosed = true;\n if (isProcessing) return;\n // If stdin is still usable, re-create readline (e.g. terminal glitch)\n if (!process.stdin.destroyed && process.stdin.readable) {\n setupInputLoop();\n askQuestion();\n return;\n }\n console.log();\n showSessionSummary();\n console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n console.log();\n process.exit(0);\n });\n}\n\n// ===== Main Loop =====\nasync function main() {\n showHeader();\n showWelcome();\n\n setupInputLoop();\n\n askQuestion = () => {\n if (rlClosed) return;\n process.stdin.resume();\n const promptStr = showPrompt();\n\n rl.question(promptStr, async (answer) => {\n if (answer === null || answer === undefined) {\n process.exit(0);\n }\n const input = answer.trim();\n\n if (!input) { askQuestion(); return; }\n\n // Slash commands\n if (input.startsWith('/')) {\n handleSlashCommand(input, rl);\n askQuestion();\n return;\n }\n\n if (input === 'exit' || input === 'quit') {\n console.log();\n showSessionSummary();\n console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n console.log();\n process.exit(0);\n }\n\n try {\n await handleUserInput(input);\n } catch (err) {\n console.log(indent(t.red('✗ Unexpected error: ') + t.text(err.message)));\n console.log();\n }\n askQuestion();\n });\n };\n\n askQuestion();\n}"
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
"state": {
|
|
422
|
+
"type": "complete",
|
|
423
|
+
"stopReason": "tool_use"
|
|
424
|
+
},
|
|
425
|
+
"usage": {
|
|
426
|
+
"model": "claude-opus-4-6",
|
|
427
|
+
"maxInputTokens": 168000,
|
|
428
|
+
"inputTokens": 1,
|
|
429
|
+
"outputTokens": 1031,
|
|
430
|
+
"cacheCreationInputTokens": 496,
|
|
431
|
+
"cacheReadInputTokens": 43364,
|
|
432
|
+
"totalInputTokens": 43861,
|
|
433
|
+
"timestamp": "2026-02-25T08:48:31.580Z"
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"role": "user",
|
|
438
|
+
"messageId": 14,
|
|
439
|
+
"content": [
|
|
440
|
+
{
|
|
441
|
+
"type": "tool_result",
|
|
442
|
+
"toolUseID": "toolu_vrtx_01RnzYS8fsPwqpnrEuA4kX8Z",
|
|
443
|
+
"run": {
|
|
444
|
+
"status": "done",
|
|
445
|
+
"progress": {},
|
|
446
|
+
"result": {
|
|
447
|
+
"diff": "```diff\nIndex: /home/runner/workspace/index.js\n===================================================================\n--- /home/runner/workspace/index.js\toriginal\n+++ /home/runner/workspace/index.js\tmodified\n@@ -949,27 +949,40 @@\n function sleep(ms) {\n return new Promise(r => setTimeout(r, ms));\n }\n \n-// ===== Main Loop =====\n-async function main() {\n- showHeader();\n- showWelcome();\n+// ===== Input Loop =====\n+function setupInputLoop() {\n+ rlClosed = false;\n+ rl = createPrompt();\n \n- const rl = createPrompt();\n-\n rl.on('close', () => {\n rlClosed = true;\n if (isProcessing) return;\n+ // If stdin is still usable, re-create readline (e.g. terminal glitch)\n+ if (!process.stdin.destroyed && process.stdin.readable) {\n+ setupInputLoop();\n+ askQuestion();\n+ return;\n+ }\n console.log();\n showSessionSummary();\n console.log(indent(t.dim('Goodbye! ') + t.brand('✦')));\n console.log();\n process.exit(0);\n });\n+}\n \n- const askQuestion = () => {\n+// ===== Main Loop =====\n+async function main() {\n+ showHeader();\n+ showWelcome();\n+\n+ setupInputLoop();\n+\n+ askQuestion = () => {\n if (rlClosed) return;\n+ process.stdin.resume();\n const promptStr = showPrompt();\n \n rl.question(promptStr, async (answer) => {\n if (answer === null || answer === undefined) {\n```",
|
|
448
|
+
"lineRange": [
|
|
449
|
+
953,
|
|
450
|
+
1021
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
"trackFiles": [
|
|
454
|
+
"file:///home/runner/workspace/index.js"
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"role": "assistant",
|
|
462
|
+
"messageId": 15,
|
|
463
|
+
"content": [
|
|
464
|
+
{
|
|
465
|
+
"type": "text",
|
|
466
|
+
"text": "Now let's verify the syntax is valid:"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
"type": "tool_use",
|
|
470
|
+
"complete": true,
|
|
471
|
+
"id": "toolu_vrtx_0161nec85yDjZGRYStdkNWaH",
|
|
472
|
+
"name": "Bash",
|
|
473
|
+
"input": {
|
|
474
|
+
"cmd": "node --check index.js",
|
|
475
|
+
"cwd": "/home/runner/workspace"
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
],
|
|
479
|
+
"state": {
|
|
480
|
+
"type": "complete",
|
|
481
|
+
"stopReason": "tool_use"
|
|
482
|
+
},
|
|
483
|
+
"usage": {
|
|
484
|
+
"model": "claude-opus-4-6",
|
|
485
|
+
"maxInputTokens": 168000,
|
|
486
|
+
"inputTokens": 1,
|
|
487
|
+
"outputTokens": 75,
|
|
488
|
+
"cacheCreationInputTokens": 1515,
|
|
489
|
+
"cacheReadInputTokens": 43860,
|
|
490
|
+
"totalInputTokens": 45376,
|
|
491
|
+
"timestamp": "2026-02-25T08:48:34.243Z"
|
|
492
|
+
},
|
|
493
|
+
"originalToolUseInput": {
|
|
494
|
+
"toolu_vrtx_0161nec85yDjZGRYStdkNWaH": {
|
|
495
|
+
"cmd": "cd /home/runner/workspace && node --check index.js"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"role": "user",
|
|
501
|
+
"messageId": 16,
|
|
502
|
+
"content": [
|
|
503
|
+
{
|
|
504
|
+
"type": "tool_result",
|
|
505
|
+
"toolUseID": "toolu_vrtx_0161nec85yDjZGRYStdkNWaH",
|
|
506
|
+
"run": {
|
|
507
|
+
"status": "done",
|
|
508
|
+
"result": {
|
|
509
|
+
"output": "",
|
|
510
|
+
"exitCode": 0
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
]
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"role": "assistant",
|
|
518
|
+
"messageId": 17,
|
|
519
|
+
"content": [
|
|
520
|
+
{
|
|
521
|
+
"type": "text",
|
|
522
|
+
"text": "The fix addresses the issue where the readline interface closes unexpectedly during processing (common in web-based terminals like Replit). Three changes:\n\n1. **Moved `rl`/`askQuestion` to module scope** so they can be re-created\n2. **`setupInputLoop()`** — re-creates readline and handles unexpected closes by reopening if stdin is still alive\n3. **`process.stdin.resume()`** — ensures stdin stays active before each prompt"
|
|
523
|
+
}
|
|
524
|
+
],
|
|
525
|
+
"state": {
|
|
526
|
+
"type": "complete",
|
|
527
|
+
"stopReason": "end_turn"
|
|
528
|
+
},
|
|
529
|
+
"usage": {
|
|
530
|
+
"model": "claude-opus-4-6",
|
|
531
|
+
"maxInputTokens": 168000,
|
|
532
|
+
"inputTokens": 1,
|
|
533
|
+
"outputTokens": 108,
|
|
534
|
+
"cacheCreationInputTokens": 115,
|
|
535
|
+
"cacheReadInputTokens": 45375,
|
|
536
|
+
"totalInputTokens": 45491,
|
|
537
|
+
"timestamp": "2026-02-25T08:48:39.777Z"
|
|
538
|
+
},
|
|
539
|
+
"turnElapsedMs": 256146
|
|
540
|
+
}
|
|
541
|
+
],
|
|
542
|
+
"agentMode": "smart",
|
|
543
|
+
"nextMessageId": 18,
|
|
544
|
+
"meta": {
|
|
545
|
+
"traces": [
|
|
546
|
+
{
|
|
547
|
+
"name": "agent",
|
|
548
|
+
"id": "0Ul0v",
|
|
549
|
+
"startTime": "2026-02-25T08:44:23.632Z",
|
|
550
|
+
"context": {
|
|
551
|
+
"messageId": 0
|
|
552
|
+
},
|
|
553
|
+
"endTime": "2026-02-25T08:48:39.778Z"
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
"name": "inference",
|
|
557
|
+
"id": "SVuMi",
|
|
558
|
+
"parent": "0Ul0v",
|
|
559
|
+
"startTime": "2026-02-25T08:44:23.633Z",
|
|
560
|
+
"context": {
|
|
561
|
+
"messageId": 0
|
|
562
|
+
},
|
|
563
|
+
"endTime": "2026-02-25T08:44:27.195Z"
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"name": "tools",
|
|
567
|
+
"id": "edrkD",
|
|
568
|
+
"parent": "0Ul0v",
|
|
569
|
+
"startTime": "2026-02-25T08:44:27.193Z",
|
|
570
|
+
"context": {
|
|
571
|
+
"messageId": 1
|
|
572
|
+
},
|
|
573
|
+
"endTime": "2026-02-25T08:44:27.224Z"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
"name": "inference",
|
|
577
|
+
"id": "XLC0w",
|
|
578
|
+
"parent": "0Ul0v",
|
|
579
|
+
"startTime": "2026-02-25T08:44:27.225Z",
|
|
580
|
+
"context": {
|
|
581
|
+
"messageId": 0
|
|
582
|
+
},
|
|
583
|
+
"endTime": "2026-02-25T08:44:33.538Z"
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
"name": "tools",
|
|
587
|
+
"id": "S0nI1",
|
|
588
|
+
"parent": "0Ul0v",
|
|
589
|
+
"startTime": "2026-02-25T08:44:33.538Z",
|
|
590
|
+
"context": {
|
|
591
|
+
"messageId": 3
|
|
592
|
+
},
|
|
593
|
+
"endTime": "2026-02-25T08:44:33.550Z"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"name": "inference",
|
|
597
|
+
"id": "PDcwh",
|
|
598
|
+
"parent": "0Ul0v",
|
|
599
|
+
"startTime": "2026-02-25T08:44:33.553Z",
|
|
600
|
+
"context": {
|
|
601
|
+
"messageId": 0
|
|
602
|
+
},
|
|
603
|
+
"endTime": "2026-02-25T08:44:37.082Z"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
"name": "tools",
|
|
607
|
+
"id": "1a0PC",
|
|
608
|
+
"parent": "0Ul0v",
|
|
609
|
+
"startTime": "2026-02-25T08:44:37.081Z",
|
|
610
|
+
"context": {
|
|
611
|
+
"messageId": 5
|
|
612
|
+
},
|
|
613
|
+
"endTime": "2026-02-25T08:44:37.090Z"
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
"name": "inference",
|
|
617
|
+
"id": "Obox1",
|
|
618
|
+
"parent": "0Ul0v",
|
|
619
|
+
"startTime": "2026-02-25T08:44:37.093Z",
|
|
620
|
+
"context": {
|
|
621
|
+
"messageId": 0
|
|
622
|
+
},
|
|
623
|
+
"endTime": "2026-02-25T08:44:42.750Z"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"name": "tools",
|
|
627
|
+
"id": "t83G0",
|
|
628
|
+
"parent": "0Ul0v",
|
|
629
|
+
"startTime": "2026-02-25T08:44:42.750Z",
|
|
630
|
+
"context": {
|
|
631
|
+
"messageId": 7
|
|
632
|
+
},
|
|
633
|
+
"endTime": "2026-02-25T08:44:42.762Z"
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"name": "inference",
|
|
637
|
+
"id": "CBtvW",
|
|
638
|
+
"parent": "0Ul0v",
|
|
639
|
+
"startTime": "2026-02-25T08:44:42.768Z",
|
|
640
|
+
"context": {
|
|
641
|
+
"messageId": 0
|
|
642
|
+
},
|
|
643
|
+
"endTime": "2026-02-25T08:48:12.807Z"
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
"name": "tools",
|
|
647
|
+
"id": "9NCMn",
|
|
648
|
+
"parent": "0Ul0v",
|
|
649
|
+
"startTime": "2026-02-25T08:48:12.806Z",
|
|
650
|
+
"context": {
|
|
651
|
+
"messageId": 9
|
|
652
|
+
},
|
|
653
|
+
"endTime": "2026-02-25T08:48:12.933Z"
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
"name": "inference",
|
|
657
|
+
"id": "DMPEN",
|
|
658
|
+
"parent": "0Ul0v",
|
|
659
|
+
"startTime": "2026-02-25T08:48:12.935Z",
|
|
660
|
+
"context": {
|
|
661
|
+
"messageId": 0
|
|
662
|
+
},
|
|
663
|
+
"endTime": "2026-02-25T08:48:17.863Z"
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
"name": "tools",
|
|
667
|
+
"id": "rJ4fC",
|
|
668
|
+
"parent": "0Ul0v",
|
|
669
|
+
"startTime": "2026-02-25T08:48:17.862Z",
|
|
670
|
+
"context": {
|
|
671
|
+
"messageId": 11
|
|
672
|
+
},
|
|
673
|
+
"endTime": "2026-02-25T08:48:17.886Z"
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"name": "inference",
|
|
677
|
+
"id": "OptTF",
|
|
678
|
+
"parent": "0Ul0v",
|
|
679
|
+
"startTime": "2026-02-25T08:48:17.887Z",
|
|
680
|
+
"context": {
|
|
681
|
+
"messageId": 0
|
|
682
|
+
},
|
|
683
|
+
"endTime": "2026-02-25T08:48:31.581Z"
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
"name": "tools",
|
|
687
|
+
"id": "aHSIF",
|
|
688
|
+
"parent": "0Ul0v",
|
|
689
|
+
"startTime": "2026-02-25T08:48:31.581Z",
|
|
690
|
+
"context": {
|
|
691
|
+
"messageId": 13
|
|
692
|
+
},
|
|
693
|
+
"endTime": "2026-02-25T08:48:31.597Z"
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"name": "inference",
|
|
697
|
+
"id": "rVwxM",
|
|
698
|
+
"parent": "0Ul0v",
|
|
699
|
+
"startTime": "2026-02-25T08:48:31.598Z",
|
|
700
|
+
"context": {
|
|
701
|
+
"messageId": 0
|
|
702
|
+
},
|
|
703
|
+
"endTime": "2026-02-25T08:48:34.244Z"
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
"name": "tools",
|
|
707
|
+
"id": "XstrI",
|
|
708
|
+
"parent": "0Ul0v",
|
|
709
|
+
"startTime": "2026-02-25T08:48:34.244Z",
|
|
710
|
+
"context": {
|
|
711
|
+
"messageId": 15
|
|
712
|
+
},
|
|
713
|
+
"endTime": "2026-02-25T08:48:34.322Z"
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"name": "inference",
|
|
717
|
+
"id": "VSFtL",
|
|
718
|
+
"parent": "0Ul0v",
|
|
719
|
+
"startTime": "2026-02-25T08:48:34.322Z",
|
|
720
|
+
"context": {
|
|
721
|
+
"messageId": 0
|
|
722
|
+
},
|
|
723
|
+
"endTime": "2026-02-25T08:48:39.779Z"
|
|
724
|
+
}
|
|
725
|
+
]
|
|
726
|
+
},
|
|
727
|
+
"env": {
|
|
728
|
+
"initial": {
|
|
729
|
+
"trees": [
|
|
730
|
+
{
|
|
731
|
+
"displayName": "workspace",
|
|
732
|
+
"uri": "file:///home/runner/workspace"
|
|
733
|
+
}
|
|
734
|
+
],
|
|
735
|
+
"platform": {
|
|
736
|
+
"os": "linux",
|
|
737
|
+
"osVersion": "Ubuntu 24.04.2 LTS",
|
|
738
|
+
"cpuArchitecture": "x64",
|
|
739
|
+
"webBrowser": false,
|
|
740
|
+
"client": "CLI",
|
|
741
|
+
"clientVersion": "0.0.1772003388-gaa1ef1",
|
|
742
|
+
"clientType": "cli",
|
|
743
|
+
"installationID": "990855e2-5987-4061-ad34-8c29deacfa95",
|
|
744
|
+
"deviceFingerprint": "v1:fp_5e0b4aaea6d8b2adcf3c155505cf5c39765fb8ea3e8157ac186424d91df98615"
|
|
745
|
+
},
|
|
746
|
+
"tags": [
|
|
747
|
+
"model:claude-opus-4-6"
|
|
748
|
+
]
|
|
749
|
+
}
|
|
750
|
+
},
|
|
751
|
+
"title": "CLI tool exits after responding to request",
|
|
752
|
+
"~debug": {
|
|
753
|
+
"lastInferenceUsage": {
|
|
754
|
+
"model": "claude-opus-4-6",
|
|
755
|
+
"maxInputTokens": 168000,
|
|
756
|
+
"inputTokens": 3,
|
|
757
|
+
"outputTokens": 11531,
|
|
758
|
+
"cacheCreationInputTokens": 11493,
|
|
759
|
+
"cacheReadInputTokens": 45375,
|
|
760
|
+
"totalInputTokens": 45491,
|
|
761
|
+
"timestamp": "2026-02-25T08:48:39.777Z"
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|