{"record":{"id":"a8e8153ebf979bc7","repo":"JuliusBrussee/caveman","slug":"cave-eve-terminal-result-status","errorCode":"cave_eve_terminal_${result.status}","errorMessage":"cave_eve_terminal_${result.status}","messagePattern":"cave_eve_terminal_(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/adapters.ts","lineNumber":257,"sourceCode":"\nexport function createEveAdapter(\n  identity: HarnessAdapterIdentity,\n  session: EveSessionBinding,\n): HarnessAdapter {\n  assertSupportedUpstream(identity, EVE_VERSION, \"eve\", \"eve\");\n  return createHarnessAdapter(\"eve\", identity, {\n    package: \"eve/client\",\n    class: \"ClientSession\",\n    method: \"send.result\",\n    usage: \"step.completed.data.usage\",\n  }, async (request) => {\n    const startedAt = performance.now();\n    const response = await session.send({\n      message: request.prompt,\n      ...(request.signal === undefined ? {} : { signal: request.signal }),\n    });\n    const result = await response.result();\n    if (result.status !== \"completed\") throw new Error(`cave_eve_terminal_${result.status}`);\n    const identity = eveRuntimeIdentity(result.events);\n    if (identity.upstreamVersion !== request.build.harness.upstream_version) {\n      throw new Error(\"cave_harness_upstream_version_mismatch\");\n    }\n    const usage = usageFromEveEvents(result.events, request.plan.reasoning !== \"none\");\n    return harnessExecution({\n      request,\n      text: result.message ?? \"\",\n      provider: identity.provider,\n      model: identity.model,\n      usage,\n      latencyMs: Math.round(performance.now() - startedAt),\n    });\n  });\n}\n\nexport interface MastraAgentBinding {\n  generate(messages: string, options?: {","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/adapters.ts#L239-L275","documentation":"extractTools parses tool-catalog input for the MCP ({\"tools\":[…]}), OpenAI (array or {\"functions\":[…]}) shapes and first json.Unmarshals the whole document. Any JSON syntax error is wrapped as 'not valid JSON: %w', so the underlying err tells you the exact byte offset. This means the input never reached shape detection — it is malformed at the lexical/structural level.","triggerScenarios":"Piping text that is not JSON: an error message from an upstream command, truncated JSON (stream cut mid-write), a BOM or code fences around JSON, or concatenating multiple JSON documents into one stdin stream.","commonSituations":"curl failing and piping an HTML error page into the shrinker; a generator printing 'Progress: ...' lines before the JSON; copying JSON with smart quotes or trailing commas; feeding NDJSON (newline-delimited) where one document was expected.","solutions":["Validate the input with jq or json.Unmarshal on []byte before piping: jq empty input.json.","Strip non-JSON prefix/suffix output (progress lines, code fences, log noise) from the producer.","If the producer emits NDJSON, aggregate the records into a single JSON array first: jq -s '.' input.ndjson."],"exampleFix":"# before\ncurl -s https://host/v1/tools | caveman-shrink\n# curl error page is not JSON\n\n# after\nresp=$(curl -sf https://host/v1/tools) && printf '%s' \"$resp\" | jq -c '{tools}' | caveman-shrink","handlingStrategy":"type-guard","validationCode":"func isJSON(b []byte) bool {\n    return json.Valid(b)\n}\n\ninput, _ := io.ReadAll(os.Stdin)\nif !isJSON(input) {\n    log.Fatal(\"stdin is not valid JSON; run through: jq empty < input\")\n}","typeGuard":"func ensureJSONCatalog(b []byte) error {\n    if !json.Valid(b) {\n        return fmt.Errorf(\"not valid JSON: %s\", findJSONIssue(b))\n    }\n    return nil\n}","tryCatchPattern":"entries, err := extractTools(input)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"not valid JSON\") {\n        // surface the offset from the wrapped error and re-check the producer pipeline\n    }\n}","preventionTips":["Validate with jq (jq empty file.json) before piping into the shrinker.","Use curl -sf so HTTP error pages never reach the pipe.","Keep producer output clean: no progress lines, code fences, or concatenated documents."],"tags":["json","parsing","input-validation","cli"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}