Fuzzer
parent
31c4a4fb47
commit
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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" }]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
}))
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import { vfsPlugin } from "./plugin"
|
||||
Bun.plugin(vfsPlugin)
|
||||
|
|
@ -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
|
||||
|
|
@ -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(" | ")}`)
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -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)
|
||||
})
|
||||
|
|
@ -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")))
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue