Run jcode and capture token usage from trace output.
(prompt: str, workdir: str, jcode_binary: str, model: str = "claude-opus-4-5-20251101")
| 162 | |
| 163 | |
| 164 | def run_jcode(prompt: str, workdir: str, jcode_binary: str, model: str = "claude-opus-4-5-20251101") -> RunResult: |
| 165 | """Run jcode and capture token usage from trace output.""" |
| 166 | try: |
| 167 | # Create a temporary JCODE_HOME to avoid polluting user's sessions |
| 168 | with tempfile.TemporaryDirectory() as tmpdir: |
| 169 | env = os.environ.copy() |
| 170 | env["JCODE_HOME"] = tmpdir |
| 171 | env["JCODE_TRACE"] = "1" |
| 172 | |
| 173 | result = subprocess.run( |
| 174 | [ |
| 175 | jcode_binary, |
| 176 | "run", |
| 177 | "--no-update", |
| 178 | "--model", model, |
| 179 | prompt, |
| 180 | ], |
| 181 | capture_output=True, |
| 182 | text=True, |
| 183 | cwd=workdir, |
| 184 | timeout=120, |
| 185 | env=env, |
| 186 | ) |
| 187 | |
| 188 | # Parse token usage from trace output in stderr |
| 189 | # Format: [trace] token_usage input=X output=Y cache_read=Z cache_write=W |
| 190 | input_tokens = 0 |
| 191 | output_tokens = 0 |
| 192 | cache_read = 0 |
| 193 | cache_write = 0 |
| 194 | |
| 195 | for line in result.stderr.split("\n"): |
| 196 | if "[trace] token_usage" in line: |
| 197 | parts = line.split() |
| 198 | for part in parts: |
| 199 | if part.startswith("input="): |
| 200 | input_tokens = int(part.split("=")[1]) |
| 201 | elif part.startswith("output="): |
| 202 | output_tokens = int(part.split("=")[1]) |
| 203 | elif part.startswith("cache_read="): |
| 204 | cache_read = int(part.split("=")[1]) |
| 205 | elif part.startswith("cache_write="): |
| 206 | cache_write = int(part.split("=")[1]) |
| 207 | |
| 208 | token_usage = TokenUsage( |
| 209 | input_tokens=input_tokens, |
| 210 | output_tokens=output_tokens, |
| 211 | cache_read_tokens=cache_read, |
| 212 | cache_creation_tokens=cache_write, |
| 213 | ) |
| 214 | |
| 215 | return RunResult( |
| 216 | tool="jcode", |
| 217 | prompt=prompt, |
| 218 | usage=token_usage, |
| 219 | success=result.returncode == 0, |
| 220 | output=result.stdout, |
| 221 | error=None if result.returncode == 0 else result.stderr, |
no test coverage detected