mirror of
https://github.com/anomalyco/opencode.git
synced 2026-03-25 08:04:49 +00:00
Compare commits
2 Commits
dev
...
jlongster/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
544b179ee7 | ||
|
|
8d5c84d516 |
@@ -26,13 +26,15 @@ export namespace Global {
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
fs.mkdir(Global.Path.data, { recursive: true }),
|
||||
fs.mkdir(Global.Path.config, { recursive: true }),
|
||||
fs.mkdir(Global.Path.state, { recursive: true }),
|
||||
fs.mkdir(Global.Path.log, { recursive: true }),
|
||||
fs.mkdir(Global.Path.bin, { recursive: true }),
|
||||
])
|
||||
try {
|
||||
await Promise.all([
|
||||
fs.mkdir(Global.Path.data, { recursive: true }),
|
||||
fs.mkdir(Global.Path.config, { recursive: true }),
|
||||
fs.mkdir(Global.Path.state, { recursive: true }),
|
||||
fs.mkdir(Global.Path.log, { recursive: true }),
|
||||
fs.mkdir(Global.Path.bin, { recursive: true }),
|
||||
])
|
||||
} catch (err) {}
|
||||
|
||||
const CACHE_VERSION = "21"
|
||||
|
||||
|
||||
@@ -94,7 +94,10 @@ export namespace ModelsDev {
|
||||
.catch(() => undefined)
|
||||
if (snapshot) return snapshot
|
||||
if (Flag.OPENCODE_DISABLE_MODELS_FETCH) return {}
|
||||
const json = await fetch(`${url()}/api.json`).then((x) => x.text())
|
||||
const json = await fetch(`${url()}/api.json`)
|
||||
.then((x) => x.text())
|
||||
.catch(() => undefined)
|
||||
if (!json) return {}
|
||||
return JSON.parse(json)
|
||||
})
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import { createOpenAI } from "@ai-sdk/openai"
|
||||
import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
|
||||
import { createOpenRouter, type LanguageModelV2 } from "@openrouter/ai-sdk-provider"
|
||||
import { createOpenaiCompatible as createGitHubCopilotOpenAICompatible } from "./sdk/copilot"
|
||||
import { createMock } from "./sdk/mock"
|
||||
import { createXai } from "@ai-sdk/xai"
|
||||
import { createMistral } from "@ai-sdk/mistral"
|
||||
import { createGroq } from "@ai-sdk/groq"
|
||||
@@ -132,6 +133,7 @@ export namespace Provider {
|
||||
"gitlab-ai-provider": createGitLab,
|
||||
// @ts-ignore (TODO: kill this code so we dont have to maintain it)
|
||||
"@ai-sdk/github-copilot": createGitHubCopilotOpenAICompatible,
|
||||
"@opencode/mock": createMock as any,
|
||||
}
|
||||
|
||||
type CustomModelLoader = (sdk: any, modelID: string, options?: Record<string, any>) => Promise<any>
|
||||
@@ -150,6 +152,11 @@ export namespace Provider {
|
||||
}
|
||||
|
||||
const CUSTOM_LOADERS: Record<string, CustomLoader> = {
|
||||
async mock() {
|
||||
return {
|
||||
autoload: true,
|
||||
}
|
||||
},
|
||||
async anthropic() {
|
||||
return {
|
||||
autoload: false,
|
||||
@@ -920,6 +927,42 @@ export namespace Provider {
|
||||
const modelsDev = await ModelsDev.get()
|
||||
const database = mapValues(modelsDev, fromModelsDevProvider)
|
||||
|
||||
// Register the built-in mock provider for testing
|
||||
database["mock"] = {
|
||||
id: "mock",
|
||||
name: "Mock",
|
||||
source: "custom",
|
||||
env: [],
|
||||
options: {},
|
||||
models: {
|
||||
"mock-model": {
|
||||
id: "mock-model",
|
||||
providerID: "mock",
|
||||
name: "Mock Model",
|
||||
api: {
|
||||
id: "mock-model",
|
||||
url: "",
|
||||
npm: "@opencode/mock",
|
||||
},
|
||||
status: "active",
|
||||
capabilities: {
|
||||
temperature: false,
|
||||
reasoning: false,
|
||||
attachment: false,
|
||||
toolcall: true,
|
||||
input: { text: true, audio: false, image: false, video: false, pdf: false },
|
||||
output: { text: true, audio: false, image: false, video: false, pdf: false },
|
||||
interleaved: false,
|
||||
},
|
||||
cost: { input: 0, output: 0, cache: { read: 0, write: 0 } },
|
||||
limit: { context: 128000, output: 4096 },
|
||||
options: {},
|
||||
headers: {},
|
||||
release_date: "2025-01-01",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const disabled = new Set(config.disabled_providers ?? [])
|
||||
const enabled = config.enabled_providers ? new Set(config.enabled_providers) : null
|
||||
|
||||
|
||||
208
packages/opencode/src/provider/sdk/mock/PROTOCOL.md
Normal file
208
packages/opencode/src/provider/sdk/mock/PROTOCOL.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Mock RPC
|
||||
|
||||
Deterministic model scripting for tests.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The mock provider lets test harnesses script exactly what the model should emit. Instead of hitting a real API, the user message contains a JSON object that describes each step of the conversation. This makes test scenarios fully deterministic and reproducible.
|
||||
|
||||
---
|
||||
|
||||
## Understand the protocol
|
||||
|
||||
The user message text is a JSON object with a `steps` array. Each step is an array of actions that the model emits on that turn.
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "text", "content": "Hello" }],
|
||||
[{ "type": "text", "content": "Goodbye" }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The mock model reads the **last** user message in the prompt to find this JSON.
|
||||
|
||||
---
|
||||
|
||||
## Know how steps are selected
|
||||
|
||||
The model picks which step to execute by counting messages with `role: "tool"` in the prompt. This count represents how many tool-result rounds have occurred.
|
||||
|
||||
- **Step 0** runs on the first call (no tool results yet).
|
||||
- **Step 1** runs after the first tool-result round.
|
||||
- **Step N** runs after the Nth tool-result round.
|
||||
|
||||
If the step index is out of bounds, the model emits an empty set of actions.
|
||||
|
||||
---
|
||||
|
||||
## Use the `text` action
|
||||
|
||||
Emits a text block.
|
||||
|
||||
```json
|
||||
{ "type": "text", "content": "Some response text" }
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-----------|--------|----------------------|
|
||||
| `content` | string | The text to emit. |
|
||||
|
||||
---
|
||||
|
||||
## Use the `tool_call` action
|
||||
|
||||
Calls a tool. The input object is passed as-is.
|
||||
|
||||
```json
|
||||
{ "type": "tool_call", "name": "write", "input": { "filePath": "a.txt", "content": "hi" } }
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|---------|--------|---------------------------------|
|
||||
| `name` | string | Name of the tool to call. |
|
||||
| `input` | object | Arguments passed to the tool. |
|
||||
|
||||
---
|
||||
|
||||
## Use the `thinking` action
|
||||
|
||||
Emits a reasoning/thinking block.
|
||||
|
||||
```json
|
||||
{ "type": "thinking", "content": "Let me consider the options..." }
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-----------|--------|----------------------------|
|
||||
| `content` | string | The thinking text to emit. |
|
||||
|
||||
---
|
||||
|
||||
## Use the `list_tools` action
|
||||
|
||||
Responds with a JSON text block listing all available tools and their schemas. Useful for test scripts that need to discover tool names. No additional fields.
|
||||
|
||||
```json
|
||||
{ "type": "list_tools" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Use the `error` action
|
||||
|
||||
Emits an error chunk.
|
||||
|
||||
```json
|
||||
{ "type": "error", "message": "something went wrong" }
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-----------|--------|------------------------|
|
||||
| `message` | string | The error message. |
|
||||
|
||||
---
|
||||
|
||||
## Know the finish reason
|
||||
|
||||
The finish reason is auto-inferred from the actions in the current step. If any action has `type: "tool_call"`, the finish reason is `"tool-calls"`. Otherwise it is `"stop"`.
|
||||
|
||||
Token usage is always reported as `{ inputTokens: 10, outputTokens: 20, totalTokens: 30 }`.
|
||||
|
||||
---
|
||||
|
||||
## Handle invalid JSON
|
||||
|
||||
If the user message is not valid JSON or doesn't have a `steps` array, the model falls back to a default text response. This keeps backward compatibility with tests that don't use the RPC protocol.
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple text response
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "text", "content": "Hello from the mock model" }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Tool discovery
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "list_tools" }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Single tool call
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "tool_call", "name": "read", "input": { "filePath": "config.json" } }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-turn tool use
|
||||
|
||||
Step 0 calls a tool. Step 1 runs after the tool result comes back and emits a text response.
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "tool_call", "name": "write", "input": { "filePath": "a.txt", "content": "hi" } }],
|
||||
[{ "type": "text", "content": "Done writing the file." }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Thinking and text
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[
|
||||
{ "type": "thinking", "content": "The user wants a greeting." },
|
||||
{ "type": "text", "content": "Hey there!" }
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple actions in one step
|
||||
|
||||
A single step can contain any combination of actions.
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[
|
||||
{ "type": "text", "content": "I'll create two files." },
|
||||
{ "type": "tool_call", "name": "write", "input": { "filePath": "a.txt", "content": "aaa" } },
|
||||
{ "type": "tool_call", "name": "write", "input": { "filePath": "b.txt", "content": "bbb" } }
|
||||
],
|
||||
[
|
||||
{ "type": "text", "content": "Both files created." }
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Error simulation
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [
|
||||
[{ "type": "error", "message": "rate limit exceeded" }]
|
||||
]
|
||||
}
|
||||
```
|
||||
19
packages/opencode/src/provider/sdk/mock/README.md
Normal file
19
packages/opencode/src/provider/sdk/mock/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
I got it to the point where it can run a full mock session
|
||||
|
||||
Run the server with `./src/provider/sdk/mock/run`. It will run it sandboxes to make sure it doesn't interact with the outside world unexpectedly.
|
||||
|
||||
Then run `bun run src/provider/sdk/mock/runner/index.ts` to drive a session and get a log
|
||||
|
||||
There is also `bun run src/provider/sdk/mock/runner/diff.ts` which will drive two sessions at once and compare them. This is annoying right now because you have to run two servers. This would let you compare the differences between versions though
|
||||
|
||||
## Coverage
|
||||
|
||||
I also have an experiment in `serve.test.ts` which runs the server as a bun test, which gives us access to coverage info. Run it like this:
|
||||
|
||||
```
|
||||
bun test --coverage --coverage-reporter=lcov --timeout 0 src/provider/sdk/mock/runner/serve.test.ts
|
||||
```
|
||||
|
||||
That will give you a `lcov.info` file. Convert it to HTML with this:
|
||||
|
||||
genhtml coverage/lcov.info -o coverage/html && open coverage/html/index.html
|
||||
24
packages/opencode/src/provider/sdk/mock/index.ts
Normal file
24
packages/opencode/src/provider/sdk/mock/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { LanguageModelV2 } from "@ai-sdk/provider"
|
||||
import { MockLanguageModel } from "./model"
|
||||
|
||||
export { vfsPlugin } from "./plugin"
|
||||
export { Filesystem as VFilesystem } from "./vfs"
|
||||
|
||||
export interface MockProviderSettings {
|
||||
name?: string
|
||||
}
|
||||
|
||||
export interface MockProvider {
|
||||
(id: string): LanguageModelV2
|
||||
languageModel(id: string): LanguageModelV2
|
||||
}
|
||||
|
||||
export function createMock(options: MockProviderSettings = {}): MockProvider {
|
||||
const name = options.name ?? "mock"
|
||||
|
||||
const create = (id: string) => new MockLanguageModel(id, { provider: name })
|
||||
|
||||
const provider = Object.assign((id: string) => create(id), { languageModel: create })
|
||||
|
||||
return provider
|
||||
}
|
||||
244
packages/opencode/src/provider/sdk/mock/model.ts
Normal file
244
packages/opencode/src/provider/sdk/mock/model.ts
Normal file
@@ -0,0 +1,244 @@
|
||||
import type {
|
||||
LanguageModelV2,
|
||||
LanguageModelV2CallOptions,
|
||||
LanguageModelV2FunctionTool,
|
||||
LanguageModelV2StreamPart,
|
||||
} from "@ai-sdk/provider"
|
||||
|
||||
/**
|
||||
* Mock Model RPC Protocol
|
||||
*
|
||||
* The user message text is a JSON object that scripts exactly what the mock
|
||||
* model should emit. This lets test harnesses drive the model deterministically.
|
||||
*
|
||||
* Schema:
|
||||
* ```
|
||||
* {
|
||||
* "steps": [
|
||||
* // Step 0: executed on first call (no tool results yet)
|
||||
* [
|
||||
* { "type": "tool_call", "name": "write", "input": { "filePath": "a.txt", "content": "hi" } }
|
||||
* ],
|
||||
* // Step 1: executed after first tool-result round
|
||||
* [
|
||||
* { "type": "text", "content": "Done!" }
|
||||
* ]
|
||||
* ]
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Supported actions:
|
||||
*
|
||||
* { "type": "text", "content": "string" }
|
||||
* Emit a text block.
|
||||
*
|
||||
* { "type": "tool_call", "name": "toolName", "input": { ... } }
|
||||
* Call a tool. The input object is passed as-is.
|
||||
*
|
||||
* { "type": "thinking", "content": "string" }
|
||||
* Emit a reasoning/thinking block.
|
||||
*
|
||||
* { "type": "list_tools" }
|
||||
* Respond with a JSON text block listing all available tools and their
|
||||
* schemas. Useful for test scripts that need to discover tool names.
|
||||
*
|
||||
* { "type": "error", "message": "string" }
|
||||
* Emit an error chunk.
|
||||
*
|
||||
* Finish reason is auto-inferred: "tool-calls" when any tool_call action
|
||||
* exists in the step, "stop" otherwise. Override with a top-level "finish"
|
||||
* field on the script object.
|
||||
*
|
||||
* If the user message is not valid JSON or doesn't match the schema, the
|
||||
* model falls back to a default text response (backward compatible).
|
||||
*/
|
||||
|
||||
// ── Protocol types ──────────────────────────────────────────────────────
|
||||
|
||||
type TextAction = { type: "text"; content: string }
|
||||
type ToolCallAction = { type: "tool_call"; name: string; input: Record<string, unknown> }
|
||||
type ThinkingAction = { type: "thinking"; content: string }
|
||||
type ListToolsAction = { type: "list_tools" }
|
||||
type ErrorAction = { type: "error"; message: string }
|
||||
|
||||
type Action = TextAction | ToolCallAction | ThinkingAction | ListToolsAction | ErrorAction
|
||||
|
||||
type Script = {
|
||||
steps: Action[][]
|
||||
}
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
function text(options: LanguageModelV2CallOptions): string {
|
||||
for (const msg of [...options.prompt].reverse()) {
|
||||
if (msg.role !== "user") continue
|
||||
for (const part of msg.content) {
|
||||
if (part.type === "text") return part.text
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
/** Count tool-result rounds since the last user message. */
|
||||
function round(options: LanguageModelV2CallOptions): number {
|
||||
let count = 0
|
||||
for (const msg of [...options.prompt].reverse()) {
|
||||
if (msg.role === "user") break
|
||||
if (msg.role === "tool") count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
function parse(raw: string): Script | undefined {
|
||||
try {
|
||||
const json = JSON.parse(raw)
|
||||
if (!json || !Array.isArray(json.steps)) return undefined
|
||||
return json as Script
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function tools(options: LanguageModelV2CallOptions): LanguageModelV2FunctionTool[] {
|
||||
if (!options.tools) return []
|
||||
return options.tools.filter((t): t is LanguageModelV2FunctionTool => t.type === "function")
|
||||
}
|
||||
|
||||
function emit(actions: Action[], options: LanguageModelV2CallOptions): LanguageModelV2StreamPart[] {
|
||||
const chunks: LanguageModelV2StreamPart[] = []
|
||||
let tid = 0
|
||||
let rid = 0
|
||||
let xid = 0
|
||||
|
||||
for (const action of actions) {
|
||||
switch (action.type) {
|
||||
case "text": {
|
||||
const id = `mock-text-${xid++}`
|
||||
chunks.push(
|
||||
{ type: "text-start", id },
|
||||
{ type: "text-delta", id, delta: action.content },
|
||||
{ type: "text-end", id },
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
case "tool_call": {
|
||||
const id = `mock-call-${tid++}`
|
||||
const input = JSON.stringify(action.input)
|
||||
chunks.push(
|
||||
{ type: "tool-input-start", id, toolName: action.name },
|
||||
{ type: "tool-input-delta", id, delta: input },
|
||||
{ type: "tool-input-end", id },
|
||||
{ type: "tool-call" as const, toolCallId: id, toolName: action.name, input },
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
case "thinking": {
|
||||
const id = `mock-reasoning-${rid++}`
|
||||
chunks.push(
|
||||
{ type: "reasoning-start", id },
|
||||
{ type: "reasoning-delta", id, delta: action.content },
|
||||
{ type: "reasoning-end", id },
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
case "list_tools": {
|
||||
const id = `mock-text-${xid++}`
|
||||
const defs = tools(options).map((t) => ({
|
||||
name: t.name,
|
||||
description: t.description,
|
||||
input: t.inputSchema,
|
||||
}))
|
||||
chunks.push(
|
||||
{ type: "text-start", id },
|
||||
{ type: "text-delta", id, delta: JSON.stringify(defs, null, 2) },
|
||||
{ type: "text-end", id },
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
case "error": {
|
||||
chunks.push({ type: "error", error: new Error(action.message) })
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunks
|
||||
}
|
||||
|
||||
// ── Model ───────────────────────────────────────────────────────────────
|
||||
|
||||
export class MockLanguageModel implements LanguageModelV2 {
|
||||
readonly specificationVersion = "v2" as const
|
||||
readonly provider: string
|
||||
readonly modelId: string
|
||||
readonly supportedUrls: Record<string, RegExp[]> = {}
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
readonly options: { provider: string },
|
||||
) {
|
||||
this.modelId = id
|
||||
this.provider = options.provider
|
||||
}
|
||||
|
||||
async doGenerate(options: LanguageModelV2CallOptions): Promise<never> {
|
||||
throw new Error("`doGenerate` not implemented")
|
||||
}
|
||||
|
||||
async doStream(options: LanguageModelV2CallOptions) {
|
||||
const raw = text(options)
|
||||
const script = parse(raw)
|
||||
const r = round(options)
|
||||
const actions = script ? (script.steps[r] ?? []) : undefined
|
||||
|
||||
const chunks: LanguageModelV2StreamPart[] = [
|
||||
{ type: "stream-start", warnings: [] },
|
||||
{
|
||||
type: "response-metadata",
|
||||
id: "mock-response",
|
||||
modelId: this.modelId,
|
||||
timestamp: new Date(),
|
||||
},
|
||||
]
|
||||
|
||||
if (actions) {
|
||||
chunks.push(...emit(actions, options))
|
||||
} else {
|
||||
// Fallback: plain text response (backward compatible)
|
||||
chunks.push(
|
||||
{ type: "text-start", id: "mock-text-0" },
|
||||
{
|
||||
type: "text-delta",
|
||||
id: "mock-text-0",
|
||||
delta: `[mock] This is a streamed mock response from model "${this.modelId}". `,
|
||||
},
|
||||
{
|
||||
type: "text-delta",
|
||||
id: "mock-text-0",
|
||||
delta: "The mock provider does not call any real API.",
|
||||
},
|
||||
{ type: "text-end", id: "mock-text-0" },
|
||||
)
|
||||
}
|
||||
|
||||
const called = actions?.some((a) => a.type === "tool_call")
|
||||
chunks.push({
|
||||
type: "finish",
|
||||
finishReason: called ? "tool-calls" : "stop",
|
||||
usage: { inputTokens: 10, outputTokens: 20, totalTokens: 30 },
|
||||
})
|
||||
|
||||
const stream = new ReadableStream<LanguageModelV2StreamPart>({
|
||||
start(controller) {
|
||||
for (const chunk of chunks) controller.enqueue(chunk)
|
||||
controller.close()
|
||||
},
|
||||
})
|
||||
|
||||
return { stream }
|
||||
}
|
||||
}
|
||||
18
packages/opencode/src/provider/sdk/mock/plugin.ts
Normal file
18
packages/opencode/src/provider/sdk/mock/plugin.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { BunPlugin } from "bun"
|
||||
import { Filesystem } from "./vfs"
|
||||
|
||||
/**
|
||||
* Bun plugin that intercepts all loads of `util/filesystem.ts` and replaces
|
||||
* the real Filesystem namespace with the in-memory VFS implementation.
|
||||
*
|
||||
* Must be registered via preload before any application code runs.
|
||||
*/
|
||||
export const vfsPlugin: BunPlugin = {
|
||||
name: "vfs",
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /util\/filesystem\.ts$/ }, () => ({
|
||||
exports: { Filesystem },
|
||||
loader: "object",
|
||||
}))
|
||||
},
|
||||
}
|
||||
2
packages/opencode/src/provider/sdk/mock/preload.ts
Normal file
2
packages/opencode/src/provider/sdk/mock/preload.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import { vfsPlugin } from "./plugin"
|
||||
Bun.plugin(vfsPlugin)
|
||||
6
packages/opencode/src/provider/sdk/mock/run
Executable file
6
packages/opencode/src/provider/sdk/mock/run
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
ROOT="$(dirname "$0")"
|
||||
|
||||
cd "$ROOT/../../../.."
|
||||
sandbox-exec -f ./src/provider/sdk/mock/sandbox.sb -D HOME=$HOME bun --preload "$ROOT/preload.ts" "src/index.ts" serve
|
||||
345
packages/opencode/src/provider/sdk/mock/runner/core.ts
Normal file
345
packages/opencode/src/provider/sdk/mock/runner/core.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
/**
|
||||
* Shared core for mock runners: HTTP, SSE, script generation, message handling.
|
||||
*/
|
||||
|
||||
import path from "path"
|
||||
|
||||
// ── Types ───────────────────────────────────────────────────────────────
|
||||
|
||||
export type Tool = {
|
||||
id: string
|
||||
description: string
|
||||
parameters: {
|
||||
type: string
|
||||
properties?: Record<string, { type: string; description?: string }>
|
||||
required?: string[]
|
||||
}
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| { type: "text"; content: string }
|
||||
| { type: "tool_call"; name: string; input: Record<string, unknown> }
|
||||
| { type: "thinking"; content: string }
|
||||
| { type: "list_tools" }
|
||||
| { type: "error"; message: string }
|
||||
|
||||
export type Script = { steps: Action[][] }
|
||||
export type Event = { type: string; properties: Record<string, any> }
|
||||
export type Message = { info: Record<string, any>; parts: Record<string, any>[] }
|
||||
type Listener = (event: Event) => void
|
||||
|
||||
export type Instance = {
|
||||
name: string
|
||||
base: string
|
||||
sse: AbortController
|
||||
}
|
||||
|
||||
// ── HTTP ────────────────────────────────────────────────────────────────
|
||||
|
||||
export async function api<T = unknown>(base: string, method: string, path: string, body?: unknown): Promise<T> {
|
||||
const opts: RequestInit = {
|
||||
method,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
if (body !== undefined) opts.body = JSON.stringify(body)
|
||||
const res = await fetch(`${base}${path}`, opts)
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => "")
|
||||
throw new Error(`${method} ${path} → ${res.status}: ${text}`)
|
||||
}
|
||||
if (res.status === 204) return undefined as T
|
||||
return res.json() as T
|
||||
}
|
||||
|
||||
// ── SSE ─────────────────────────────────────────────────────────────────
|
||||
|
||||
const listeners = new Map<AbortController, Listener>()
|
||||
|
||||
function subscribe(base: string, cb: Listener): AbortController {
|
||||
const abort = new AbortController()
|
||||
;(async () => {
|
||||
const res = await fetch(`${base}/event`, {
|
||||
headers: { Accept: "text/event-stream" },
|
||||
signal: abort.signal,
|
||||
})
|
||||
if (!res.ok || !res.body) {
|
||||
log("SSE connect failed", base, res.status)
|
||||
return
|
||||
}
|
||||
const reader = res.body.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
let buf = ""
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
buf += decoder.decode(value, { stream: true })
|
||||
const lines = buf.split("\n")
|
||||
buf = lines.pop()!
|
||||
for (const line of lines) {
|
||||
if (!line.startsWith("data: ")) continue
|
||||
try {
|
||||
cb(JSON.parse(line.slice(6)))
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
})().catch(() => {})
|
||||
return abort
|
||||
}
|
||||
|
||||
export function startSSE(base: string): AbortController {
|
||||
const ctrl = subscribe(base, (evt) => {
|
||||
const fn = listeners.get(ctrl)
|
||||
fn?.(evt)
|
||||
})
|
||||
listeners.set(ctrl, () => {})
|
||||
return ctrl
|
||||
}
|
||||
|
||||
export function idle(sid: string, sse: AbortController, timeout = 60_000): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
cleanup()
|
||||
reject(new Error(`session ${sid} did not become idle within ${timeout}ms`))
|
||||
}, timeout)
|
||||
|
||||
const orig = listeners.get(sse)
|
||||
const handler = (evt: Event) => {
|
||||
orig?.(evt)
|
||||
if (evt.type !== "session.status") return
|
||||
if (evt.properties.sessionID !== sid) return
|
||||
if (evt.properties.status?.type === "idle") {
|
||||
cleanup()
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
listeners.set(sse, handler)
|
||||
|
||||
function cleanup() {
|
||||
clearTimeout(timer)
|
||||
if (orig) listeners.set(sse, orig)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ── Tool discovery ──────────────────────────────────────────────────────
|
||||
|
||||
let cachedTools: Tool[] | undefined
|
||||
|
||||
export async function tools(base: string): Promise<Tool[]> {
|
||||
if (cachedTools) return cachedTools
|
||||
cachedTools = await api<Tool[]>(base, "GET", "/experimental/tool?provider=mock&model=mock-model")
|
||||
return cachedTools
|
||||
}
|
||||
|
||||
// ── Random generators ───────────────────────────────────────────────────
|
||||
|
||||
function pick<T>(arr: T[]): T {
|
||||
return arr[Math.floor(Math.random() * arr.length)]
|
||||
}
|
||||
|
||||
export function rand(min: number, max: number) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||
}
|
||||
|
||||
const WORDS = [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"qux",
|
||||
"hello",
|
||||
"world",
|
||||
"test",
|
||||
"alpha",
|
||||
"beta",
|
||||
"gamma",
|
||||
"delta",
|
||||
"src",
|
||||
"lib",
|
||||
"tmp",
|
||||
]
|
||||
const EXTS = [".ts", ".js", ".json", ".txt", ".md"]
|
||||
|
||||
function word() {
|
||||
return pick(WORDS)
|
||||
}
|
||||
|
||||
function sentence() {
|
||||
const n = rand(3, 12)
|
||||
return Array.from({ length: n }, () => word()).join(" ")
|
||||
}
|
||||
|
||||
function filepath() {
|
||||
const depth = rand(1, 3)
|
||||
const parts = Array.from({ length: depth }, () => word())
|
||||
return parts.join("/") + pick(EXTS)
|
||||
}
|
||||
|
||||
function fakeInput(tool: Tool): Record<string, unknown> {
|
||||
const result: Record<string, unknown> = {}
|
||||
const props = tool.parameters.properties ?? {}
|
||||
for (const [key, schema] of Object.entries(props)) {
|
||||
switch (schema.type) {
|
||||
case "string":
|
||||
if (key.toLowerCase().includes("path") || key.toLowerCase().includes("file")) {
|
||||
result[key] = filepath()
|
||||
} else if (key.toLowerCase().includes("pattern") || key.toLowerCase().includes("regex")) {
|
||||
result[key] = word()
|
||||
} else if (key.toLowerCase().includes("command") || key.toLowerCase().includes("cmd")) {
|
||||
result[key] = `echo ${word()}`
|
||||
} else {
|
||||
result[key] = sentence()
|
||||
}
|
||||
break
|
||||
case "number":
|
||||
case "integer":
|
||||
result[key] = rand(1, 100)
|
||||
break
|
||||
case "boolean":
|
||||
result[key] = Math.random() > 0.5
|
||||
break
|
||||
case "object":
|
||||
result[key] = {}
|
||||
break
|
||||
case "array":
|
||||
result[key] = []
|
||||
break
|
||||
default:
|
||||
result[key] = sentence()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ── Action generators ───────────────────────────────────────────────────
|
||||
|
||||
const SAFE_TOOLS = new Set(["read", "glob", "grep", "todowrite", "webfetch", "websearch", "codesearch"])
|
||||
const WRITE_TOOLS = new Set(["write", "edit", "bash"])
|
||||
|
||||
function textAction(): Action {
|
||||
return { type: "text", content: sentence() }
|
||||
}
|
||||
|
||||
function thinkingAction(): Action {
|
||||
return { type: "thinking", content: sentence() }
|
||||
}
|
||||
|
||||
function errorAction(): Action {
|
||||
return { type: "error", message: `mock error: ${word()}` }
|
||||
}
|
||||
|
||||
function listToolsAction(): Action {
|
||||
return { type: "list_tools" }
|
||||
}
|
||||
|
||||
async function toolAction(base: string): Promise<Action> {
|
||||
const all = await tools(base)
|
||||
const safe = all.filter((t) => SAFE_TOOLS.has(t.id) || WRITE_TOOLS.has(t.id))
|
||||
if (!safe.length) return textAction()
|
||||
const tool = pick(safe)
|
||||
return { type: "tool_call", name: tool.id, input: fakeInput(tool) }
|
||||
}
|
||||
|
||||
// ── Script generation ───────────────────────────────────────────────────
|
||||
|
||||
export async function script(base: string): Promise<Script> {
|
||||
const r = Math.random()
|
||||
|
||||
if (r < 0.4) {
|
||||
const call = await toolAction(base)
|
||||
return { steps: [[call], [textAction()]] }
|
||||
}
|
||||
if (r < 0.6) {
|
||||
return { steps: [[thinkingAction(), textAction()]] }
|
||||
}
|
||||
if (r < 0.75) {
|
||||
const n = rand(2, 4)
|
||||
const calls: Action[] = []
|
||||
for (let i = 0; i < n; i++) calls.push(await toolAction(base))
|
||||
return { steps: [calls, [textAction()]] }
|
||||
}
|
||||
if (r < 0.85) {
|
||||
return { steps: [[textAction()]] }
|
||||
}
|
||||
if (r < 0.9) {
|
||||
return { steps: [[listToolsAction()]] }
|
||||
}
|
||||
if (r < 0.95) {
|
||||
const call = await toolAction(base)
|
||||
return { steps: [[thinkingAction(), call], [textAction()]] }
|
||||
}
|
||||
return { steps: [[errorAction()]] }
|
||||
}
|
||||
|
||||
// ── Pre-generate all scripts for a session ──────────────────────────────
|
||||
|
||||
export async function generate(base: string, count: number): Promise<Script[]> {
|
||||
const scripts: Script[] = []
|
||||
for (let i = 0; i < count; i++) scripts.push(await script(base))
|
||||
return scripts
|
||||
}
|
||||
|
||||
// ── Messages ────────────────────────────────────────────────────────────
|
||||
|
||||
export async function messages(base: string, sid: string): Promise<Message[]> {
|
||||
return api<Message[]>(base, "GET", `/session/${sid}/message`)
|
||||
}
|
||||
|
||||
// ── Run a full session: send all scripts, return all messages ───────────
|
||||
|
||||
export async function run(inst: Instance, scripts: Script[]): Promise<Message[]> {
|
||||
const info = await api<{ id: string }>(inst.base, "POST", "/session", {})
|
||||
const sid = info.id
|
||||
|
||||
for (const s of scripts) {
|
||||
const payload = JSON.stringify(s)
|
||||
await api(inst.base, "POST", `/session/${sid}/prompt_async`, {
|
||||
parts: [{ type: "text", text: payload }],
|
||||
model: { providerID: "mock", modelID: "mock-model" },
|
||||
})
|
||||
await idle(sid, inst.sse)
|
||||
}
|
||||
|
||||
return messages(inst.base, sid)
|
||||
}
|
||||
|
||||
// ── Connect to an instance ──────────────────────────────────────────────
|
||||
|
||||
export async function connect(name: string, port: string): Promise<Instance> {
|
||||
const base = `http://localhost:${port}`
|
||||
const health = await api<{ healthy: boolean; version: string }>(base, "GET", "/global/health")
|
||||
if (!health.healthy) throw new Error(`${name} not healthy`)
|
||||
log(`${name}: version ${health.version} at ${base}`)
|
||||
const sse = startSSE(base)
|
||||
return { name, base, sse }
|
||||
}
|
||||
|
||||
// ── Logging ─────────────────────────────────────────────────────────────
|
||||
|
||||
export function log(...args: unknown[]) {
|
||||
const ts = new Date().toISOString().slice(11, 23)
|
||||
console.log(`[${ts}]`, ...args)
|
||||
}
|
||||
|
||||
export function summary(s: Script): string {
|
||||
const actions = s.steps.flat()
|
||||
const types = actions.map((a) => {
|
||||
if (a.type === "tool_call") return `tool:${a.name}`
|
||||
return a.type
|
||||
})
|
||||
return `${s.steps.length} step(s): ${types.join(", ")}`
|
||||
}
|
||||
|
||||
export function logMessages(msgs: Message[]) {
|
||||
for (const msg of msgs) {
|
||||
const role = msg.info.role
|
||||
const parts = msg.parts.map((p: any) => {
|
||||
if (p.type === "text") return `text: ${p.text?.slice(0, 80)}${p.text?.length > 80 ? "..." : ""}`
|
||||
if (p.type === "tool") return `tool:${p.tool}(${p.state?.status})`
|
||||
if (p.type === "reasoning") return `reasoning: ${p.text?.slice(0, 60)}${(p.text?.length ?? 0) > 60 ? "..." : ""}`
|
||||
if (p.type === "step-start") return "step-start"
|
||||
if (p.type === "step-finish") return `step-finish(${p.reason})`
|
||||
return p.type
|
||||
})
|
||||
log(` ${role} [${msg.info.id?.slice(0, 8)}] ${parts.join(" | ")}`)
|
||||
}
|
||||
}
|
||||
130
packages/opencode/src/provider/sdk/mock/runner/diff.ts
Normal file
130
packages/opencode/src/provider/sdk/mock/runner/diff.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Mock Runner — Dual Instance Diff
|
||||
*
|
||||
* Connects to TWO running opencode servers, runs identical mock RPC scripts
|
||||
* against both (all turns on A, then all turns on B), and diffs the results.
|
||||
* Each session run writes the full serialized messages and a unified diff
|
||||
* into a folder under ./errors/<id>/.
|
||||
*
|
||||
* Usage:
|
||||
* bun run src/provider/sdk/mock/runner/diff.ts <port1> <port2>
|
||||
*/
|
||||
|
||||
import path from "path"
|
||||
import { connect, generate, run, log, summary, tools, rand, type Message } from "./core"
|
||||
|
||||
const port1 = process.argv[2]
|
||||
const port2 = process.argv[3]
|
||||
|
||||
if (!port1 || !port2) {
|
||||
console.error("Usage: bun run src/provider/sdk/mock/runner/diff.ts <port1> <port2>")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const ERRORS_DIR = path.join(import.meta.dir, "errors")
|
||||
|
||||
// ── Normalize ───────────────────────────────────────────────────────────
|
||||
|
||||
function normalize(msgs: Message[]): object[] {
|
||||
return msgs.map((m) => ({
|
||||
role: m.info.role,
|
||||
parts: m.parts.map((p) => {
|
||||
const { id, sessionID, messageID, ...rest } = p
|
||||
if (rest.type === "tool" && rest.state) {
|
||||
const { time, ...state } = rest.state
|
||||
return { ...rest, state }
|
||||
}
|
||||
if (rest.type === "step-finish") {
|
||||
const { cost, tokens, ...finish } = rest
|
||||
return finish
|
||||
}
|
||||
if ("time" in rest) {
|
||||
const { time, ...without } = rest
|
||||
return without
|
||||
}
|
||||
return rest
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
// ── Write results ───────────────────────────────────────────────────────
|
||||
|
||||
async function writeResults(scripts: { steps: object[][] }[], a: Message[], b: Message[]): Promise<string | false> {
|
||||
const na = normalize(a)
|
||||
const nb = normalize(b)
|
||||
const ja = JSON.stringify(na, null, 2)
|
||||
const jb = JSON.stringify(nb, null, 2)
|
||||
|
||||
if (ja === jb) return false
|
||||
|
||||
const id = Math.random().toString(36).slice(2, 10)
|
||||
const dir = path.join(ERRORS_DIR, id)
|
||||
|
||||
const fileA = path.join(dir, "normalized_a.json")
|
||||
const fileB = path.join(dir, "normalized_b.json")
|
||||
|
||||
await Promise.all([
|
||||
Bun.write(path.join(dir, "messages_a.json"), JSON.stringify(a, null, 2)),
|
||||
Bun.write(path.join(dir, "messages_b.json"), JSON.stringify(b, null, 2)),
|
||||
Bun.write(fileA, ja),
|
||||
Bun.write(fileB, jb),
|
||||
])
|
||||
|
||||
// generate unified diff via system `diff`
|
||||
const proc = Bun.spawn(["diff", "-u", "--label", "instance_a", fileA, "--label", "instance_b", fileB], {
|
||||
stdout: "pipe",
|
||||
})
|
||||
const patch = await new Response(proc.stdout).text()
|
||||
await proc.exited
|
||||
await Bun.write(path.join(dir, "diff.patch"), patch)
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
// ── Session loop ────────────────────────────────────────────────────────
|
||||
|
||||
async function session(a: Awaited<ReturnType<typeof connect>>, b: Awaited<ReturnType<typeof connect>>) {
|
||||
const turns = rand(30, 100)
|
||||
const scripts = await generate(a.base, turns)
|
||||
|
||||
log(`${turns} turns generated: ${scripts.map((s) => summary(s)).join(", ")}`)
|
||||
|
||||
log(`running ${turns} turns on A...`)
|
||||
const msgsA = await run(a, scripts)
|
||||
log(`A: ${msgsA.length} messages`)
|
||||
|
||||
log(`running ${turns} turns on B...`)
|
||||
const msgsB = await run(b, scripts)
|
||||
log(`B: ${msgsB.length} messages`)
|
||||
|
||||
const dir = await writeResults(scripts, msgsA, msgsB)
|
||||
if (dir) {
|
||||
log(`DIFF → ${dir}`)
|
||||
} else {
|
||||
log(`OK — no differences`)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Main ────────────────────────────────────────────────────────────────
|
||||
|
||||
async function main() {
|
||||
const a = await connect("A", port1)
|
||||
const b = await connect("B", port2)
|
||||
|
||||
const t = await tools(a.base)
|
||||
log(`${t.length} tools: ${t.map((x) => x.id).join(", ")}`)
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
await session(a, b)
|
||||
} catch (e: any) {
|
||||
log(`session failed: ${e.message}`)
|
||||
await Bun.sleep(2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
# Session diff
|
||||
# 4 turns
|
||||
# Instance A: port 4096
|
||||
# Instance B: port 4096
|
||||
# A messages: 11
|
||||
# B messages: 11
|
||||
--- instance A
|
||||
+++ instance B
|
||||
@@ -0,0 +1,716 @@
|
||||
[
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379576189
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143ab7d001ASSb6uqvhJ7FN7",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"write\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha src test\"}]]}",
|
||||
"id": "prt_d2143ab7d0026isp1ndlSmyxiw",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab7d001ASSb6uqvhJ7FN7"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379576192,
|
||||
"completed": 1774379576206
|
||||
},
|
||||
"parentID": "msg_d2143ab7d001ASSb6uqvhJ7FN7",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143ab80001AOMoMijnCTf0bb",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143ab89001qUzTE2B6gdv68l",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab80001AOMoMijnCTf0bb"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379576203,
|
||||
"end": 1774379576203
|
||||
},
|
||||
"id": "prt_d2143ab8a001pX1CoTDdUrvSdW",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab80001AOMoMijnCTf0bb"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "write",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The write tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"content\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n },\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"filePath\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379576204,
|
||||
"end": 1774379576204
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143ab8b001wYWKhe82IcjnFy",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab80001AOMoMijnCTf0bb"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143ab8c001m1pij4LiODTsKg",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab80001AOMoMijnCTf0bb"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379576207,
|
||||
"completed": 1774379576211
|
||||
},
|
||||
"parentID": "msg_d2143ab7d001ASSb6uqvhJ7FN7",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143ab8f001BgMv7OWVnzUnr9",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143ab91001F7jxegR2MOXnNN",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab8f001BgMv7OWVnzUnr9"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379576209,
|
||||
"end": 1774379576209
|
||||
},
|
||||
"id": "prt_d2143ab910027u37aFl4EQn4VO",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab8f001BgMv7OWVnzUnr9"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha src test",
|
||||
"time": {
|
||||
"start": 1774379576209,
|
||||
"end": 1774379576209
|
||||
},
|
||||
"id": "prt_d2143ab91003Ci5xJpgoiTJ1Ze",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab8f001BgMv7OWVnzUnr9"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143ab92001PzVA5i0DjhH2l0",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143ab8f001BgMv7OWVnzUnr9"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379577216
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143af80001O4aaGWU6LeV09I",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"lib lib hello qux src foo tmp gamma alpha\"},{\"type\":\"text\",\"content\":\"gamma bar gamma test src beta\"}]]}",
|
||||
"id": "prt_d2143af80002E2rLd5vwk4FJPG",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af80001O4aaGWU6LeV09I"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379577217,
|
||||
"completed": 1774379577222
|
||||
},
|
||||
"parentID": "msg_d2143af80001O4aaGWU6LeV09I",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143af81001gD7i0NZzdzwZ1G",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143af830010iTFlowoExs7b0",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af81001gD7i0NZzdzwZ1G"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379577219,
|
||||
"end": 1774379577219
|
||||
},
|
||||
"id": "prt_d2143af83002f1VULTn0TY9R2E",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af81001gD7i0NZzdzwZ1G"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "lib lib hello qux src foo tmp gamma alpha",
|
||||
"time": {
|
||||
"start": 1774379577220,
|
||||
"end": 1774379577220
|
||||
},
|
||||
"id": "prt_d2143af84001lRiLQgXzBHeuqP",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af81001gD7i0NZzdzwZ1G"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "gamma bar gamma test src beta",
|
||||
"time": {
|
||||
"start": 1774379577220,
|
||||
"end": 1774379577220
|
||||
},
|
||||
"id": "prt_d2143af84002BOGhkxAIx5gVVu",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af81001gD7i0NZzdzwZ1G"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143af85001jLwqpqu4fTNje4",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143af81001gD7i0NZzdzwZ1G"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379578226
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143b372001KvrMbCNcI3dB63",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"grep\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"todowrite\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test alpha alpha\"}]]}",
|
||||
"id": "prt_d2143b372002qQsCtyXB3KXtm0",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b372001KvrMbCNcI3dB63"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379578227,
|
||||
"completed": 1774379578239
|
||||
},
|
||||
"parentID": "msg_d2143b372001KvrMbCNcI3dB63",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143b373001HkR7TzdIYRbdL1",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143b376001KbLK6KZc5PYF9f",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b373001HkR7TzdIYRbdL1"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379578231,
|
||||
"end": 1774379578231
|
||||
},
|
||||
"id": "prt_d2143b376002iC7BK0widOQC98",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b373001HkR7TzdIYRbdL1"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "grep",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The grep tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379578231,
|
||||
"end": 1774379578232
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b3770014lsHALNBXJNBmI",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b373001HkR7TzdIYRbdL1"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "todowrite",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The todowrite tool was called with invalid arguments: [\n {\n \"expected\": \"array\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"todos\"\n ],\n \"message\": \"Invalid input: expected array, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379578232,
|
||||
"end": 1774379578235
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b378001e5p04JzcoGJo6Y",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b373001HkR7TzdIYRbdL1"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b37b001Ng2DGBhVEPgaSM",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b373001HkR7TzdIYRbdL1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379578240,
|
||||
"completed": 1774379578248
|
||||
},
|
||||
"parentID": "msg_d2143b372001KvrMbCNcI3dB63",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143b380001Ls2Trp5boTPmPh",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143b383001oK6kY2ziZUzQZX",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b380001Ls2Trp5boTPmPh"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379578244,
|
||||
"end": 1774379578244
|
||||
},
|
||||
"id": "prt_d2143b383002VGvjz7v5MvsYbp",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b380001Ls2Trp5boTPmPh"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test alpha alpha",
|
||||
"time": {
|
||||
"start": 1774379578246,
|
||||
"end": 1774379578246
|
||||
},
|
||||
"id": "prt_d2143b384001VmUMKZMYSR29dX",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b380001Ls2Trp5boTPmPh"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b386001nhWATjMdIw9JnA",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b380001Ls2Trp5boTPmPh"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379579237
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143b765001TJgD7CmDuJKvX4",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test baz lib tmp beta delta qux\"}]]}",
|
||||
"id": "prt_d2143b765002XDp4iZHaPM3owV",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b765001TJgD7CmDuJKvX4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379579313,
|
||||
"completed": 1774379579321
|
||||
},
|
||||
"parentID": "msg_d2143b765001TJgD7CmDuJKvX4",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143b7b1001wKt6ridUEPuyBy",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143b7b4001qSKg1nigww5QWL",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7b1001wKt6ridUEPuyBy"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379579317,
|
||||
"end": 1774379579317
|
||||
},
|
||||
"id": "prt_d2143b7b5001ZgrZbJWBljSF0B",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7b1001wKt6ridUEPuyBy"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379579318,
|
||||
"end": 1774379579318
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b7b5002Hy3vHvluGodElw",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7b1001wKt6ridUEPuyBy"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b7b7001F01F2XuppoBAvg",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7b1001wKt6ridUEPuyBy"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379579323,
|
||||
"completed": 1774379579327
|
||||
},
|
||||
"parentID": "msg_d2143b765001TJgD7CmDuJKvX4",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143b7bb001MwZ2fPznUkNWaD",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143b7bd001B5PfId3nlb7B4p",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7bb001MwZ2fPznUkNWaD"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379579325,
|
||||
"end": 1774379579325
|
||||
},
|
||||
"id": "prt_d2143b7bd002KNEoobBD1xRxl5",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7bb001MwZ2fPznUkNWaD"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test baz lib tmp beta delta qux",
|
||||
"time": {
|
||||
"start": 1774379579326,
|
||||
"end": 1774379579326
|
||||
},
|
||||
"id": "prt_d2143b7be0010qkY9dT7EP5bSL",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7bb001MwZ2fPznUkNWaD"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143b7be002kAMC1rvsBo7YI2",
|
||||
"sessionID": "ses_2debc5893ffeaAXV63RenuYRad",
|
||||
"messageID": "msg_d2143b7bb001MwZ2fPznUkNWaD"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,716 @@
|
||||
[
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379582422
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143c3d5001KT7T04r8FyRvjS",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"write\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha src test\"}]]}",
|
||||
"id": "prt_d2143c3d6001SGxGr1RY3wObHC",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3d5001KT7T04r8FyRvjS"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379582423,
|
||||
"completed": 1774379582445
|
||||
},
|
||||
"parentID": "msg_d2143c3d5001KT7T04r8FyRvjS",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143c3d7001769e2U0WPHNSTE",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143c3e2001CObsaU2q0Y53qL",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3d7001769e2U0WPHNSTE"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379582434,
|
||||
"end": 1774379582434
|
||||
},
|
||||
"id": "prt_d2143c3e2002aF1YmpGhj0Mwha",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3d7001769e2U0WPHNSTE"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "write",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The write tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"content\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n },\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"filePath\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379582441,
|
||||
"end": 1774379582442
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143c3e3001IEEo3tnjUPs15a",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3d7001769e2U0WPHNSTE"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143c3ea001bqur0mrFj2phlQ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3d7001769e2U0WPHNSTE"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379582446,
|
||||
"completed": 1774379582450
|
||||
},
|
||||
"parentID": "msg_d2143c3d5001KT7T04r8FyRvjS",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143c3ee0010AYXnrOaS99ZOQ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143c3f0001v8F3QQ0oX4S2rg",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3ee0010AYXnrOaS99ZOQ"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379582448,
|
||||
"end": 1774379582448
|
||||
},
|
||||
"id": "prt_d2143c3f000204hd55JZ8otMEp",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3ee0010AYXnrOaS99ZOQ"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha src test",
|
||||
"time": {
|
||||
"start": 1774379582449,
|
||||
"end": 1774379582449
|
||||
},
|
||||
"id": "prt_d2143c3f1001xS7OWBZ033y8l6",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3ee0010AYXnrOaS99ZOQ"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143c3f100229kD2ReqThCFSt",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c3ee0010AYXnrOaS99ZOQ"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379583480
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143c7f8001C6ROv8OzFHTCZM",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"lib lib hello qux src foo tmp gamma alpha\"},{\"type\":\"text\",\"content\":\"gamma bar gamma test src beta\"}]]}",
|
||||
"id": "prt_d2143c7f8002dYy3UaNalp5BbL",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7f8001C6ROv8OzFHTCZM"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379583483,
|
||||
"completed": 1774379583488
|
||||
},
|
||||
"parentID": "msg_d2143c7f8001C6ROv8OzFHTCZM",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143c7fb001we6hPbzshkzrNy",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143c7fe001TeFm1JF8iNEjwl",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7fb001we6hPbzshkzrNy"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379583487,
|
||||
"end": 1774379583487
|
||||
},
|
||||
"id": "prt_d2143c7fe002qY6Re5hhZKnN5C",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7fb001we6hPbzshkzrNy"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "lib lib hello qux src foo tmp gamma alpha",
|
||||
"time": {
|
||||
"start": 1774379583487,
|
||||
"end": 1774379583487
|
||||
},
|
||||
"id": "prt_d2143c7ff001vrJUyBL0kPYNCQ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7fb001we6hPbzshkzrNy"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "gamma bar gamma test src beta",
|
||||
"time": {
|
||||
"start": 1774379583487,
|
||||
"end": 1774379583487
|
||||
},
|
||||
"id": "prt_d2143c7ff0023EdYEmu7mV0nO5",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7fb001we6hPbzshkzrNy"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143c7ff003uV89tAjBWj79ko",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143c7fb001we6hPbzshkzrNy"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379584507
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143cbfb001gAL4NWFXdZgjKs",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"grep\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"todowrite\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test alpha alpha\"}]]}",
|
||||
"id": "prt_d2143cbfb002hFQRFJx8dUCsxJ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfb001gAL4NWFXdZgjKs"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379584508,
|
||||
"completed": 1774379584515
|
||||
},
|
||||
"parentID": "msg_d2143cbfb001gAL4NWFXdZgjKs",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143cbfc001JzvvQ9J0gr9qRg",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143cc00001dev0B2qo3KPN8O",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfc001JzvvQ9J0gr9qRg"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379584512,
|
||||
"end": 1774379584512
|
||||
},
|
||||
"id": "prt_d2143cc00002umrLwBNdirT4qx",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfc001JzvvQ9J0gr9qRg"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "grep",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The grep tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379584513,
|
||||
"end": 1774379584513
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cc00003YdloL2qv1oAuo8",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfc001JzvvQ9J0gr9qRg"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "todowrite",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The todowrite tool was called with invalid arguments: [\n {\n \"expected\": \"array\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"todos\"\n ],\n \"message\": \"Invalid input: expected array, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379584513,
|
||||
"end": 1774379584514
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cc010015Xy8V1X3KU3hRZ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfc001JzvvQ9J0gr9qRg"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cc02001mQ04qR4P4mtb8l",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cbfc001JzvvQ9J0gr9qRg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379584515,
|
||||
"completed": 1774379584519
|
||||
},
|
||||
"parentID": "msg_d2143cbfb001gAL4NWFXdZgjKs",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143cc03001sYIyyLHeLCbCeM",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143cc05001EWqrxaAjSmxgUi",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cc03001sYIyyLHeLCbCeM"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379584517,
|
||||
"end": 1774379584517
|
||||
},
|
||||
"id": "prt_d2143cc05002MtOf0RA6dgYkXp",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cc03001sYIyyLHeLCbCeM"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test alpha alpha",
|
||||
"time": {
|
||||
"start": 1774379584518,
|
||||
"end": 1774379584518
|
||||
},
|
||||
"id": "prt_d2143cc060016gbI2vMS7R5jU1",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cc03001sYIyyLHeLCbCeM"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cc06002O5FGgKAePaaGm0",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cc03001sYIyyLHeLCbCeM"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379585461
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143cfb5001PPQoIRtGeviy3c",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test baz lib tmp beta delta qux\"}]]}",
|
||||
"id": "prt_d2143cfb50027EsruWcB94okp9",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfb5001PPQoIRtGeviy3c"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379585463,
|
||||
"completed": 1774379585475
|
||||
},
|
||||
"parentID": "msg_d2143cfb5001PPQoIRtGeviy3c",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143cfb7001QuAkgD4erkOK2t",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143cfbd001bAWzjeTU0hd34Q",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfb7001QuAkgD4erkOK2t"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379585470,
|
||||
"end": 1774379585470
|
||||
},
|
||||
"id": "prt_d2143cfbd0021XodVrKNZennQd",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfb7001QuAkgD4erkOK2t"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379585471,
|
||||
"end": 1774379585472
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cfbf001hch9QVAuVVKeHX",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfb7001QuAkgD4erkOK2t"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cfc1001qdMuYmXs9sKr7o",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfb7001QuAkgD4erkOK2t"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379585476,
|
||||
"completed": 1774379585479
|
||||
},
|
||||
"parentID": "msg_d2143cfb5001PPQoIRtGeviy3c",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143cfc400106KBhqYfWCTNFn",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143cfc6001oMJV4hwqWbigpS",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfc400106KBhqYfWCTNFn"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379585478,
|
||||
"end": 1774379585478
|
||||
},
|
||||
"id": "prt_d2143cfc6002GJauPaAdD5zXhQ",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfc400106KBhqYfWCTNFn"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test baz lib tmp beta delta qux",
|
||||
"time": {
|
||||
"start": 1774379585478,
|
||||
"end": 1774379585478
|
||||
},
|
||||
"id": "prt_d2143cfc6003glU1XL5UB35LJX",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfc400106KBhqYfWCTNFn"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143cfc700106w94xd70qzIrD",
|
||||
"sessionID": "ses_2debc400dfferXmjJLga0kv53B",
|
||||
"messageID": "msg_d2143cfc400106KBhqYfWCTNFn"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,210 @@
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"write\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha src test\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "write",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The write tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"content\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n },\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"filePath\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha src test"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"lib lib hello qux src foo tmp gamma alpha\"},{\"type\":\"text\",\"content\":\"gamma bar gamma test src beta\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "lib lib hello qux src foo tmp gamma alpha"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "gamma bar gamma test src beta"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"grep\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"todowrite\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test alpha alpha\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "grep",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The grep tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "todowrite",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The todowrite tool was called with invalid arguments: [\n {\n \"expected\": \"array\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"todos\"\n ],\n \"message\": \"Invalid input: expected array, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test alpha alpha"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test baz lib tmp beta delta qux\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test baz lib tmp beta delta qux"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,210 @@
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"write\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha src test\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "write",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The write tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"content\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n },\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"filePath\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha src test"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"lib lib hello qux src foo tmp gamma alpha\"},{\"type\":\"text\",\"content\":\"gamma bar gamma test src beta\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "lib lib hello qux src foo tmp gamma alpha"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "gamma bar gamma test src beta"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"grep\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"todowrite\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test alpha alpha\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "grep",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The grep tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "todowrite",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The todowrite tool was called with invalid arguments: [\n {\n \"expected\": \"array\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"todos\"\n ],\n \"message\": \"Invalid input: expected array, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test alpha alpha"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"test baz lib tmp beta delta qux\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "test baz lib tmp beta delta qux"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
# Session diff
|
||||
# 3 turns
|
||||
# Instance A: port 4096
|
||||
# Instance B: port 4096
|
||||
# A messages: 7
|
||||
# B messages: 7
|
||||
--- instance A
|
||||
+++ instance B
|
||||
@@ -0,0 +1,465 @@
|
||||
[
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379588771
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143dca3001OhaTYuqHlFDvmt",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"webfetch\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha tmp beta\"}]]}",
|
||||
"id": "prt_d2143dca3002J7HBkBW7BRIkdw",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca3001OhaTYuqHlFDvmt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379588774,
|
||||
"completed": 1774379588783
|
||||
},
|
||||
"parentID": "msg_d2143dca3001OhaTYuqHlFDvmt",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143dca6001VTBnHQdm9M2HhS",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143dcaa001rYll62dnvTbQQK",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379588779,
|
||||
"end": 1774379588779
|
||||
},
|
||||
"id": "prt_d2143dcaa002Mg8ZIWIpUYImAA",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379588780,
|
||||
"end": 1774379588781
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143dcab001NcfFqgPswqln8M",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379588781,
|
||||
"end": 1774379588782
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143dcad0019Pa1Y3ND7F2prd",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-2",
|
||||
"tool": "webfetch",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The webfetch tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"url\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379588782,
|
||||
"end": 1774379588782
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143dcae001a1vQ60oApHrNij",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143dcae002CJtrhx4fVOKLka",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dca6001VTBnHQdm9M2HhS"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379588784,
|
||||
"completed": 1774379588790
|
||||
},
|
||||
"parentID": "msg_d2143dca3001OhaTYuqHlFDvmt",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143dcb0001I5jbgvOXa1kSHJ",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143dcb3001r7hqcHFemmnT5E",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dcb0001I5jbgvOXa1kSHJ"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379588788,
|
||||
"end": 1774379588788
|
||||
},
|
||||
"id": "prt_d2143dcb3002pQdd5l0U4exwVJ",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dcb0001I5jbgvOXa1kSHJ"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha tmp beta",
|
||||
"time": {
|
||||
"start": 1774379588789,
|
||||
"end": 1774379588789
|
||||
},
|
||||
"id": "prt_d2143dcb5001tqCK4eWTbrS1Ie",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dcb0001I5jbgvOXa1kSHJ"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143dcb5002tkgLWI8CjZ18qU",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143dcb0001I5jbgvOXa1kSHJ"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379589838
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143e0ce0010cbodqAmPw8M4Z",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"hello test baz delta src\"},{\"type\":\"text\",\"content\":\"tmp foo qux\"}]]}",
|
||||
"id": "prt_d2143e0ce0020ix0YCGLbGPNzH",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0ce0010cbodqAmPw8M4Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379589840,
|
||||
"completed": 1774379589845
|
||||
},
|
||||
"parentID": "msg_d2143e0ce0010cbodqAmPw8M4Z",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143e0d0001gal9nb1wbQtHtb",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143e0d3001Jiu1axRJoYd56C",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0d0001gal9nb1wbQtHtb"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379589843,
|
||||
"end": 1774379589843
|
||||
},
|
||||
"id": "prt_d2143e0d3002BCxqSyOdFp4MXy",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0d0001gal9nb1wbQtHtb"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "hello test baz delta src",
|
||||
"time": {
|
||||
"start": 1774379589843,
|
||||
"end": 1774379589844
|
||||
},
|
||||
"id": "prt_d2143e0d3003zXNCmsGkF469zo",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0d0001gal9nb1wbQtHtb"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "tmp foo qux",
|
||||
"time": {
|
||||
"start": 1774379589844,
|
||||
"end": 1774379589844
|
||||
},
|
||||
"id": "prt_d2143e0d4001HbowUiT0qQfsSR",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0d0001gal9nb1wbQtHtb"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143e0d4002sRySxZsIQiNtKw",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e0d0001gal9nb1wbQtHtb"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379590872
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143e4d8001jq1nk8KvjwVhpg",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"alpha baz gamma\"},{\"type\":\"text\",\"content\":\"src src lib foo src alpha qux delta foo\"}]]}",
|
||||
"id": "prt_d2143e4d80025Dn7lCBjC14lV3",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d8001jq1nk8KvjwVhpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379590873,
|
||||
"completed": 1774379590879
|
||||
},
|
||||
"parentID": "msg_d2143e4d8001jq1nk8KvjwVhpg",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143e4d9001utRznASk4YUE10",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143e4dd001g9U0gK61u6wi16",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d9001utRznASk4YUE10"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379590878,
|
||||
"end": 1774379590878
|
||||
},
|
||||
"id": "prt_d2143e4dd002xYtuQBc9mq01P7",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d9001utRznASk4YUE10"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "alpha baz gamma",
|
||||
"time": {
|
||||
"start": 1774379590878,
|
||||
"end": 1774379590878
|
||||
},
|
||||
"id": "prt_d2143e4de001WoiHGqS23mR2y7",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d9001utRznASk4YUE10"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "src src lib foo src alpha qux delta foo",
|
||||
"time": {
|
||||
"start": 1774379590878,
|
||||
"end": 1774379590878
|
||||
},
|
||||
"id": "prt_d2143e4de0027c6KiMdB8fTdhc",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d9001utRznASk4YUE10"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143e4df001RdPVu5PHt1ZXZy",
|
||||
"sessionID": "ses_2debc2792ffeOX6mtNg266sdQs",
|
||||
"messageID": "msg_d2143e4d9001utRznASk4YUE10"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,465 @@
|
||||
[
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379593974
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143f0f6001W06kLQkLc0Avmt",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"webfetch\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha tmp beta\"}]]}",
|
||||
"id": "prt_d2143f0f6002f7aHc9lHE9QNyB",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f0f6001W06kLQkLc0Avmt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379594061,
|
||||
"completed": 1774379594073
|
||||
},
|
||||
"parentID": "msg_d2143f0f6001W06kLQkLc0Avmt",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "tool-calls",
|
||||
"id": "msg_d2143f14d001THhEKu7ayFlx3Z",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143f154001PVSKjmtsV3DLJe",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2",
|
||||
"time": {
|
||||
"start": 1774379594069,
|
||||
"end": 1774379594069
|
||||
},
|
||||
"id": "prt_d2143f154002GsJ9lRNwVenp7X",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379594070,
|
||||
"end": 1774379594070
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f155001i3kutYi3KNE5wz",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379594071,
|
||||
"end": 1774379594071
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f156001R2TvLMCOOGpph6",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-2",
|
||||
"tool": "webfetch",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The webfetch tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"url\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema.",
|
||||
"time": {
|
||||
"start": 1774379594071,
|
||||
"end": 1774379594072
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f157001gNlwORHT1lN5PV",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f158001FRPSA8RbDrqAZw",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f14d001THhEKu7ayFlx3Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379594074,
|
||||
"completed": 1774379594078
|
||||
},
|
||||
"parentID": "msg_d2143f0f6001W06kLQkLc0Avmt",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143f15a001JjvWPtfcpPMziU",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143f15c0010jDTWHviMVLv1n",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f15a001JjvWPtfcpPMziU"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2",
|
||||
"time": {
|
||||
"start": 1774379594076,
|
||||
"end": 1774379594076
|
||||
},
|
||||
"id": "prt_d2143f15c002JSe7fs2ISI0UEp",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f15a001JjvWPtfcpPMziU"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha tmp beta",
|
||||
"time": {
|
||||
"start": 1774379594077,
|
||||
"end": 1774379594077
|
||||
},
|
||||
"id": "prt_d2143f15d001O2Tn3oWjYJtf5A",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f15a001JjvWPtfcpPMziU"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f15d002dGtu4Z2ZRqqE9I",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f15a001JjvWPtfcpPMziU"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379595311
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143f62f001QX3387NAQuBWSk",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"hello test baz delta src\"},{\"type\":\"text\",\"content\":\"tmp foo qux\"}]]}",
|
||||
"id": "prt_d2143f62f002tVsYdvhHZygvUd",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f62f001QX3387NAQuBWSk"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379595323,
|
||||
"completed": 1774379595332
|
||||
},
|
||||
"parentID": "msg_d2143f62f001QX3387NAQuBWSk",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143f63b001A6xJFFicEmTzJx",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143f6410016Hh0Sm1mRmt3X5",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f63b001A6xJFFicEmTzJx"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379595330,
|
||||
"end": 1774379595330
|
||||
},
|
||||
"id": "prt_d2143f641002ufYzrb5QanYeYN",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f63b001A6xJFFicEmTzJx"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "hello test baz delta src",
|
||||
"time": {
|
||||
"start": 1774379595330,
|
||||
"end": 1774379595330
|
||||
},
|
||||
"id": "prt_d2143f642001QkVKO6KVAImQYz",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f63b001A6xJFFicEmTzJx"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "tmp foo qux",
|
||||
"time": {
|
||||
"start": 1774379595331,
|
||||
"end": 1774379595331
|
||||
},
|
||||
"id": "prt_d2143f642002MLHz0uIaPAkeZ4",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f63b001A6xJFFicEmTzJx"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143f6430012waVXZMFXu3TC8",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143f63b001A6xJFFicEmTzJx"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "user",
|
||||
"time": {
|
||||
"created": 1774379596713
|
||||
},
|
||||
"summary": {
|
||||
"diffs": []
|
||||
},
|
||||
"agent": "build",
|
||||
"model": {
|
||||
"providerID": "mock",
|
||||
"modelID": "mock-model"
|
||||
},
|
||||
"id": "msg_d2143fba9001XAh8JaW5JvpJlv",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"alpha baz gamma\"},{\"type\":\"text\",\"content\":\"src src lib foo src alpha qux delta foo\"}]]}",
|
||||
"id": "prt_d2143fba9002dHYnp8GsUaBqDt",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fba9001XAh8JaW5JvpJlv"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": {
|
||||
"role": "assistant",
|
||||
"time": {
|
||||
"created": 1774379596722,
|
||||
"completed": 1774379596748
|
||||
},
|
||||
"parentID": "msg_d2143fba9001XAh8JaW5JvpJlv",
|
||||
"modelID": "mock-model",
|
||||
"providerID": "mock",
|
||||
"mode": "build",
|
||||
"agent": "build",
|
||||
"path": {
|
||||
"cwd": "/Users/james/projects/opencode/packages/opencode",
|
||||
"root": "/"
|
||||
},
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"finish": "stop",
|
||||
"id": "msg_d2143fbb2001XNDThR5D7TmNly",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ"
|
||||
},
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start",
|
||||
"id": "prt_d2143fbc6001W6cc2hnRvnzsik",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fbb2001XNDThR5D7TmNly"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=1",
|
||||
"time": {
|
||||
"start": 1774379596744,
|
||||
"end": 1774379596744
|
||||
},
|
||||
"id": "prt_d2143fbc7001N4GUWfPV2xT08C",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fbb2001XNDThR5D7TmNly"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "alpha baz gamma",
|
||||
"time": {
|
||||
"start": 1774379596744,
|
||||
"end": 1774379596745
|
||||
},
|
||||
"id": "prt_d2143fbc80019Ts62MVwF52nIT",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fbb2001XNDThR5D7TmNly"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "src src lib foo src alpha qux delta foo",
|
||||
"time": {
|
||||
"start": 1774379596747,
|
||||
"end": 1774379596747
|
||||
},
|
||||
"id": "prt_d2143fbca001ho24JWb5CDEzHB",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fbb2001XNDThR5D7TmNly"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop",
|
||||
"cost": 0,
|
||||
"tokens": {
|
||||
"total": 30,
|
||||
"input": 10,
|
||||
"output": 20,
|
||||
"reasoning": 0,
|
||||
"cache": {
|
||||
"read": 0,
|
||||
"write": 0
|
||||
}
|
||||
},
|
||||
"id": "prt_d2143fbcb001SvHn89K0x3NFNQ",
|
||||
"sessionID": "ses_2debc1358ffeJw4radOUd2jQXZ",
|
||||
"messageID": "msg_d2143fbb2001XNDThR5D7TmNly"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,143 @@
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"webfetch\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha tmp beta\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-2",
|
||||
"tool": "webfetch",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The webfetch tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"url\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha tmp beta"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"hello test baz delta src\"},{\"type\":\"text\",\"content\":\"tmp foo qux\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "hello test baz delta src"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "tmp foo qux"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"alpha baz gamma\"},{\"type\":\"text\",\"content\":\"src src lib foo src alpha qux delta foo\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "alpha baz gamma"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "src src lib foo src alpha qux delta foo"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,143 @@
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"glob\",\"input\":{}},{\"type\":\"tool_call\",\"name\":\"webfetch\",\"input\":{}}],[{\"type\":\"text\",\"content\":\"alpha tmp beta\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-0",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-1",
|
||||
"tool": "glob",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The glob tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"pattern\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "tool",
|
||||
"callID": "mock-call-2",
|
||||
"tool": "webfetch",
|
||||
"state": {
|
||||
"status": "error",
|
||||
"input": {},
|
||||
"error": "The webfetch tool was called with invalid arguments: [\n {\n \"expected\": \"string\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"url\"\n ],\n \"message\": \"Invalid input: expected string, received undefined\"\n }\n].\nPlease rewrite the input so it satisfies the expected schema."
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "tool-calls"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=1 roles=[system,user,assistant,tool] steps=2"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "alpha tmp beta"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"hello test baz delta src\"},{\"type\":\"text\",\"content\":\"tmp foo qux\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "hello test baz delta src"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "tmp foo qux"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"parts": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "{\"steps\":[[{\"type\":\"thinking\",\"content\":\"alpha baz gamma\"},{\"type\":\"text\",\"content\":\"src src lib foo src alpha qux delta foo\"}]]}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"parts": [
|
||||
{
|
||||
"type": "step-start"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[mock-debug] round=0 roles=[system,user,assistant,tool,assistant,user,assistant,user] steps=1"
|
||||
},
|
||||
{
|
||||
"type": "reasoning",
|
||||
"text": "alpha baz gamma"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "src src lib foo src alpha qux delta foo"
|
||||
},
|
||||
{
|
||||
"type": "step-finish",
|
||||
"reason": "stop"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
88
packages/opencode/src/provider/sdk/mock/runner/index.ts
Normal file
88
packages/opencode/src/provider/sdk/mock/runner/index.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Mock Runner — Single Instance (Log Mode)
|
||||
*
|
||||
* Connects to one running opencode server, sends mock RPC scripts,
|
||||
* and logs all user/assistant messages per turn.
|
||||
*
|
||||
* Usage:
|
||||
* bun run src/provider/sdk/mock/runner/index.ts <port>
|
||||
*/
|
||||
|
||||
import {
|
||||
connect,
|
||||
generate,
|
||||
run,
|
||||
log,
|
||||
summary,
|
||||
logMessages,
|
||||
tools,
|
||||
rand,
|
||||
api,
|
||||
idle,
|
||||
messages,
|
||||
type Message,
|
||||
} from "./core"
|
||||
|
||||
const port = process.argv[2] || 4096;
|
||||
|
||||
async function session(inst: Awaited<ReturnType<typeof connect>>) {
|
||||
const info = await api<{ id: string }>(inst.base, "POST", "/session", {})
|
||||
const sid = info.id
|
||||
const turns = rand(30, 100)
|
||||
const history: Message[] = []
|
||||
|
||||
log(`session ${sid} — ${turns} turns`)
|
||||
|
||||
const scripts = await generate(inst.base, turns)
|
||||
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
const s = scripts[i]
|
||||
const payload = JSON.stringify(s)
|
||||
log(` [${i + 1}/${turns}] ${summary(s)}`)
|
||||
|
||||
try {
|
||||
await api(inst.base, "POST", `/session/${sid}/prompt_async`, {
|
||||
parts: [{ type: "text", text: payload }],
|
||||
model: { providerID: "mock", modelID: "mock-model" },
|
||||
})
|
||||
await idle(sid, inst.sse)
|
||||
|
||||
const all = await messages(inst.base, sid)
|
||||
const known = new Set(history.map((m) => m.info.id))
|
||||
const fresh = all.filter((m) => !known.has(m.info.id))
|
||||
|
||||
log(` → ${fresh.length} new message(s):`)
|
||||
logMessages(fresh)
|
||||
|
||||
history.push(...fresh)
|
||||
} catch (e: any) {
|
||||
log(` error on turn ${i + 1}: ${e.message}`)
|
||||
await Bun.sleep(1000)
|
||||
await api(inst.base, "POST", `/session/${sid}/abort`).catch(() => {})
|
||||
await Bun.sleep(500)
|
||||
}
|
||||
}
|
||||
|
||||
log(`session ${sid} — done (${history.length} messages total)`)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const inst = await connect("server", port)
|
||||
|
||||
const t = await tools(inst.base)
|
||||
log(`${t.length} tools: ${t.map((x) => x.id).join(", ")}`)
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
await session(inst)
|
||||
} catch (e: any) {
|
||||
log(`session failed: ${e.message}`)
|
||||
await Bun.sleep(2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
52
packages/opencode/src/provider/sdk/mock/runner/serve.test.ts
Normal file
52
packages/opencode/src/provider/sdk/mock/runner/serve.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { vfsPlugin } from "../plugin"
|
||||
Bun.plugin(vfsPlugin)
|
||||
|
||||
/**
|
||||
* Starts the mock opencode server inside bun:test so coverage instrumentation works.
|
||||
*
|
||||
* Usage:
|
||||
* bun test --coverage --coverage-reporter=lcov --timeout 0 src/provider/sdk/mock/runner/serve.test.ts
|
||||
*
|
||||
* The server runs until the process is killed (Ctrl-C).
|
||||
* Coverage data is flushed on exit.
|
||||
*/
|
||||
|
||||
import { test } from "bun:test"
|
||||
import { Log } from "../../../../util/log"
|
||||
import { Server } from "../../../../server/server"
|
||||
import { Global } from "../../../../global"
|
||||
import { Filesystem } from "../../../../util/filesystem"
|
||||
import { JsonMigration } from "../../../../storage/json-migration"
|
||||
import { Database } from "../../../../storage/db"
|
||||
import path from "path"
|
||||
|
||||
const PORT = 4096;
|
||||
|
||||
test("serve", async () => {
|
||||
process.env.AGENT = "1"
|
||||
process.env.OPENCODE = "1"
|
||||
process.env.OPENCODE_PID = String(process.pid)
|
||||
|
||||
await Log.init({ print: false, dev: true, level: "DEBUG" })
|
||||
|
||||
const marker = path.join(Global.Path.data, "opencode.db")
|
||||
if (!(await Filesystem.exists(marker))) {
|
||||
console.log("Running one-time database migration...")
|
||||
await JsonMigration.run(Database.Client().$client, {
|
||||
progress: (event) => {
|
||||
const pct = Math.floor((event.current / event.total) * 100)
|
||||
if (event.current === event.total || pct % 25 === 0) {
|
||||
console.log(` migration: ${pct}%`)
|
||||
}
|
||||
},
|
||||
})
|
||||
console.log("Migration complete.")
|
||||
}
|
||||
|
||||
const server = Server.listen({ port: PORT, hostname: "127.0.0.1" })
|
||||
console.log(`opencode server listening on http://${server.hostname}:${server.port}`)
|
||||
|
||||
// keep alive until killed
|
||||
await new Promise(() => {})
|
||||
await server.stop()
|
||||
})
|
||||
17
packages/opencode/src/provider/sdk/mock/sandbox.sb
Normal file
17
packages/opencode/src/provider/sdk/mock/sandbox.sb
Normal file
@@ -0,0 +1,17 @@
|
||||
(version 1)
|
||||
|
||||
;; Start permissive, then lock down network and filesystem
|
||||
(allow default)
|
||||
|
||||
;; ── Network: deny all, allow localhost ──
|
||||
(deny network*)
|
||||
(allow network* (local ip "localhost:*"))
|
||||
(allow network* (remote ip "localhost:*"))
|
||||
|
||||
;; ── Filesystem writes: deny all, then allow temp dirs ──
|
||||
(deny file-write*)
|
||||
|
||||
;; ── Filesystem reads: deny sensitive dirs ──
|
||||
(deny file-read*
|
||||
(subpath (string-append (param "HOME") "/.local"))
|
||||
(subpath (string-append (param "HOME") "/.config")))
|
||||
243
packages/opencode/src/provider/sdk/mock/vfs.ts
Normal file
243
packages/opencode/src/provider/sdk/mock/vfs.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
import path from "path"
|
||||
import { lookup } from "mime-types"
|
||||
|
||||
const ROOT = '/mock'
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// * Some places use the `glob` utility to scan the filesystem which
|
||||
// does not go through `Filesystem`. We should mock that too
|
||||
|
||||
function globToRegex(pattern: string, cwd: string): RegExp {
|
||||
const full = pattern.startsWith("/") ? pattern : cwd.replace(/\/$/, "") + "/" + pattern
|
||||
const escaped = full
|
||||
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
||||
.replace(/\*\*/g, "<<<GLOBSTAR>>>")
|
||||
.replace(/\*/g, "[^/]*")
|
||||
.replace(/<<<GLOBSTAR>>>/g, ".*")
|
||||
.replace(/\?/g, "[^/]")
|
||||
return new RegExp("^" + escaped + "$")
|
||||
}
|
||||
|
||||
function enoent(p: string) {
|
||||
return Object.assign(new Error(`ENOENT: ${p}`), { code: "ENOENT" })
|
||||
}
|
||||
|
||||
/**
|
||||
* In-memory virtual filesystem that implements the same API as the
|
||||
* real `Filesystem` namespace from `util/filesystem`.
|
||||
*/
|
||||
export namespace Filesystem {
|
||||
const files = new Map<string, string>()
|
||||
|
||||
// seed
|
||||
// for (const [p, content] of Object.entries(SEED)) {
|
||||
// files.set(p, content)
|
||||
// }
|
||||
|
||||
function abs(p: string) {
|
||||
if (!path.isAbsolute(p)) return path.join(ROOT, p)
|
||||
return p
|
||||
}
|
||||
|
||||
function pfx(p: string) {
|
||||
const resolved = abs(p)
|
||||
return resolved.endsWith("/") ? resolved : resolved + "/"
|
||||
}
|
||||
|
||||
// -- Filesystem API --
|
||||
|
||||
export async function exists(p: string) {
|
||||
const resolved = abs(p)
|
||||
if (files.has(resolved)) return true
|
||||
const pre = pfx(p)
|
||||
for (const key of files.keys()) {
|
||||
if (key.startsWith(pre)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function isDir(p: string) {
|
||||
const resolved = abs(p)
|
||||
if (files.has(resolved)) return false
|
||||
const pre = pfx(p)
|
||||
for (const key of files.keys()) {
|
||||
if (key.startsWith(pre)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function stat(p: string) {
|
||||
const resolved = abs(p)
|
||||
const content = files.get(resolved)
|
||||
if (content !== undefined) {
|
||||
const sz = new TextEncoder().encode(content).byteLength
|
||||
return {
|
||||
isFile: () => true,
|
||||
isDirectory: () => false,
|
||||
isSymbolicLink: () => false,
|
||||
size: sz,
|
||||
mtimeMs: Date.now(),
|
||||
mtime: new Date(),
|
||||
}
|
||||
}
|
||||
// check directory
|
||||
const pre = pfx(p)
|
||||
for (const key of files.keys()) {
|
||||
if (key.startsWith(pre)) {
|
||||
return {
|
||||
isFile: () => false,
|
||||
isDirectory: () => true,
|
||||
isSymbolicLink: () => false,
|
||||
size: 0,
|
||||
mtimeMs: Date.now(),
|
||||
mtime: new Date(),
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export async function size(p: string) {
|
||||
const content = files.get(abs(p))
|
||||
if (content === undefined) return 0
|
||||
return new TextEncoder().encode(content).byteLength
|
||||
}
|
||||
|
||||
export async function readText(p: string) {
|
||||
console.log('reading', p)
|
||||
const content = files.get(abs(p))
|
||||
if (content === undefined) throw enoent(p)
|
||||
return content
|
||||
}
|
||||
|
||||
export async function readJson<T = any>(p: string): Promise<T> {
|
||||
console.log('reading', p)
|
||||
const content = files.get(abs(p))
|
||||
if (content === undefined) throw enoent(p)
|
||||
return JSON.parse(content)
|
||||
}
|
||||
|
||||
export async function readBytes(p: string) {
|
||||
console.log('reading', p)
|
||||
const content = files.get(abs(p))
|
||||
if (content === undefined) throw enoent(p)
|
||||
return Buffer.from(content)
|
||||
}
|
||||
|
||||
export async function readArrayBuffer(p: string) {
|
||||
const content = files.get(abs(p))
|
||||
if (content === undefined) throw enoent(p)
|
||||
const buf = Buffer.from(content)
|
||||
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer
|
||||
}
|
||||
|
||||
export async function write(p: string, content: string | Buffer | Uint8Array, _mode?: number) {
|
||||
console.log('writing', p)
|
||||
files.set(abs(p), typeof content === "string" ? content : Buffer.from(content).toString("utf-8"))
|
||||
}
|
||||
|
||||
export async function writeJson(p: string, data: unknown, _mode?: number) {
|
||||
files.set(abs(p), JSON.stringify(data, null, 2))
|
||||
}
|
||||
|
||||
export async function writeStream(p: string, stream: ReadableStream<Uint8Array>, _mode?: number) {
|
||||
const reader = stream.getReader()
|
||||
const chunks: Uint8Array[] = []
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
chunks.push(value)
|
||||
}
|
||||
files.set(abs(p), Buffer.concat(chunks).toString("utf-8"))
|
||||
}
|
||||
|
||||
export function mimeType(p: string) {
|
||||
return lookup(p) || "application/octet-stream"
|
||||
}
|
||||
|
||||
export function normalizePath(p: string) {
|
||||
return p
|
||||
}
|
||||
|
||||
export function resolve(p: string) {
|
||||
return path.resolve(p)
|
||||
}
|
||||
|
||||
export function windowsPath(p: string) {
|
||||
return p
|
||||
}
|
||||
|
||||
export function overlaps(a: string, b: string) {
|
||||
const relA = path.relative(a, b)
|
||||
const relB = path.relative(b, a)
|
||||
return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..")
|
||||
}
|
||||
|
||||
export function contains(parent: string, child: string) {
|
||||
return !path.relative(parent, child).startsWith("..")
|
||||
}
|
||||
|
||||
export async function findUp(target: string, start: string, stop?: string) {
|
||||
let current = start
|
||||
const result: string[] = []
|
||||
while (true) {
|
||||
const search = path.join(current, target)
|
||||
if (await exists(search)) result.push(search)
|
||||
if (stop === current) break
|
||||
const parent = path.dirname(current)
|
||||
if (parent === current) break
|
||||
current = parent
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export async function* up(options: { targets: string[]; start: string; stop?: string }) {
|
||||
let current = options.start
|
||||
while (true) {
|
||||
for (const target of options.targets) {
|
||||
const search = path.join(current, target)
|
||||
if (await exists(search)) yield search
|
||||
}
|
||||
if (options.stop === current) break
|
||||
const parent = path.dirname(current)
|
||||
if (parent === current) break
|
||||
current = parent
|
||||
}
|
||||
}
|
||||
|
||||
export async function globUp(pattern: string, start: string, stop?: string) {
|
||||
let current = start
|
||||
const result: string[] = []
|
||||
while (true) {
|
||||
const dir = abs(current)
|
||||
const regex = globToRegex(pattern, dir)
|
||||
for (const key of files.keys()) {
|
||||
if (regex.test(key)) result.push(key)
|
||||
}
|
||||
if (stop === current) break
|
||||
const parent = path.dirname(current)
|
||||
if (parent === current) break
|
||||
current = parent
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// -- extra helpers for direct test manipulation --
|
||||
|
||||
export function _set(p: string, content: string) {
|
||||
files.set(abs(p), content)
|
||||
}
|
||||
|
||||
export function _get(p: string) {
|
||||
return files.get(abs(p))
|
||||
}
|
||||
|
||||
export function _remove(p: string) {
|
||||
files.delete(abs(p))
|
||||
}
|
||||
|
||||
export function _list() {
|
||||
return [...files.keys()].sort()
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ const log = Log.create({ service: "db" })
|
||||
|
||||
export namespace Database {
|
||||
export const Path = iife(() => {
|
||||
return ':memory:'
|
||||
if (Flag.OPENCODE_DB) {
|
||||
if (path.isAbsolute(Flag.OPENCODE_DB)) return Flag.OPENCODE_DB
|
||||
return path.join(Global.Path.data, Flag.OPENCODE_DB)
|
||||
|
||||
Reference in New Issue
Block a user