diff --git a/.gitignore b/.gitignore index 888f944..25f9eed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /web/node_modules/ /internal/claude/testdata/transcripts/ +/internal/codex/testdata/transcripts/ /.preview/ diff --git a/TODO.md b/TODO.md index 00763eb..17ad6df 100644 --- a/TODO.md +++ b/TODO.md @@ -6,8 +6,6 @@ # M3 — Second vendor and review -- Codex adapter - A JSON-RPC client for `codex app-server`, with Go types generated from the protocol schema the CLI can emit. It needs: start thread, stream events, send turns, interrupt, resume, and the same interface coverage as Claude (interrupts, model switching, compaction, image input). Disable CLI auto-updates so the version changes only when the owner updates it, and keep a contract test suite built from recorded transcripts. - Verify that Codex app-server can fork threads - Review profiles and triggers Reviews are done by a separate agent session, never the implementer, by default from a different vendor. Each review targets a snapshot and is cached by tree sha; when the task's tree moves on, existing reviews are marked stale. A review profile (security, performance, privacy, visual UX, plan conformance, ...) has a prompt, vendor, model, output schema and capture config; workflow stages reference profiles by name. Triggers: on `ask_human` (the inbox item appears at once and the review attaches when done, even if the item was resolved first), before merge, on demand, and periodically on elapsed time or diff size, debounced to turn boundaries or a quiet period. A `request_review(scope, concerns[], profile?)` MCP tool lets agents ask for one. diff --git a/docs/codex-protocol.md b/docs/codex-protocol.md new file mode 100644 index 0000000..9d5a72a --- /dev/null +++ b/docs/codex-protocol.md @@ -0,0 +1,55 @@ +# Codex app-server protocol + +How `internal/codex` drives `codex app-server`. The server's own schema is the reference: `codex app-server generate-json-schema --experimental --out DIR` writes it, and `codex_app_server_protocol.schemas.json` in DIR is the whole bundle (top-level definitions plus a nested `v2` set). + +## Binary and version + +byre runs `codex` from `PATH`. On the owner's machine that is the CLI inside the ChatGPT desktop app (`ls -la ~/.local/bin/codex` shows the link), so the version moves when the app updates itself; `codex --version` prints it. byre passes `-c check_for_update_on_startup=false` so the CLI never checks for or offers updates of its own. `SchemaVersion` in `internal/codex/protocol.gen.go` names the version the types were generated from; when it differs from `codex --version`, regenerate and re-record (below). + +## Generated types + +`go generate ./internal/codex` runs `internal/codex/gen`: it asks the CLI for the experimental schema, then writes `protocol.gen.go` with a Go type for every params and response type of the client methods listed in `clientMethods` (`internal/codex/gen/main.go`), every server notification and every server request, and everything they reference. The experimental schema is used because the server sends experimental fields (such as `environments` on a thread) even to clients that don't opt into them. + +- A `oneOf`/`anyOf` whose alternatives are all objects becomes one struct with every alternative's fields (a field whose type differs between alternatives is `json.RawMessage`), plus `Type` constants for its `type` discriminator, as for `ThreadItem`. +- Alternatives that are all strings become a string type with a constant per value; a mix of strings and objects (such as `AskForApproval`) is `json.RawMessage`. +- Optional and nullable fields get `omitempty`; optional structs are pointers. +- `Method` constants name every method; `clientResults`, `notificationParams`, `serverRequestParams` and `serverRequestResponses` map methods to their types. + +## Launch and framing + +``` +codex app-server -c check_for_update_on_startup=false +``` + +Run in the session's working directory, with `GIT_AUTHOR_*`/`GIT_COMMITTER_*` set to the commit identity; shell commands inherit them. NDJSON both ways on stdio. Messages are JSON-RPC 2.0 without the `"jsonrpc"` member: requests `{"id","method","params"}`, responses `{"id","result"}` or `{"id","error":{"code","message"}}`, notifications `{"method","params"}`. The server adds `emittedAtMs` to its notifications. The server also reads the user's `~/.codex/config.toml`, so its MCP servers, plugins and `notify` program apply to byre's sessions too. + +## Session lifecycle + +1. `initialize` with `clientInfo`, then the `initialized` notification. +2. `thread/start` (`cwd`, `model`, `approvalPolicy` `never`, `sandbox` `danger-full-access`, `developerInstructions` for byre's guidance), or `thread/resume` with `threadId` and the same settings. The server picks the thread id, returned as `thread.id`; resuming keeps it. `Session.ID` is the thread id. +3. `turn/start` with `threadId` and `input`, a list of `UserInput`: `{"type":"text","text":...}`, and for each image `{"type":"image","url":"data:;base64,..."}` before the text. `model` on it switches the model for that turn and every later one (`Session.SetModel` holds the model for the next `Send`); `thread/read` reports the thread's current `model`. The response carries the new turn; `turn/started` follows. +4. `turn/interrupt` with `threadId` and the active `turnId` ends the turn: `turn/completed` arrives with `status` `interrupted` within milliseconds, a running command is killed, and the thread stays usable. `Session` tracks the active turn from `turn/started` and `turn/completed`. +5. `thread/compact/start` runs compaction as a turn of its own: `turn/started`, an item of type `contextCompaction`, `turn/completed`. The thread keeps its id and remembers the conversation in summary. + +Closing stdin ends the process. + +## Events + +- `turn/started`, `turn/completed` (`turn.status` `completed`, `interrupted` or `failed` with `turn.error`). A failed request to the model also sends an `error` notification first, with `willRetry`. +- `item/started` and `item/completed` with a `ThreadItem`: `userMessage`, `agentMessage` (`text`), `reasoning`, `commandExecution` (`command`, `aggregatedOutput`, `exitCode`), `fileChange`, `mcpToolCall`, `contextCompaction` and others. +- `item/agentMessage/delta` (`itemId`, `delta`) streams an agent message; the deltas join to the completed item's `text`. `item/commandExecution/outputDelta` and the reasoning deltas stream the same way. +- `thread/tokenUsage/updated` carries `last` and `total` token counts and `modelContextWindow`; `account/rateLimits/updated` the account's rate-limit windows; `thread/status/changed`, `mcpServer/startupStatus/updated`, `account/updated` and `remoteControl/status/changed` also arrive. +- Lines that aren't a JSON object, don't parse, or carry a notification method outside `notificationParams` go to `Options.OnBadLine`; parsed notifications are still delivered as events. `Event.Decode` returns the notification's generated params type. + +Server requests (approvals, user input, dynamic tool calls) shouldn't arrive with approvals off; if one does, command and file-change approvals are accepted and anything else gets a JSON-RPC error. + +## Transcripts and contract tests + +`Options.Transcript` records every line in both directions as `{"dir":"send"|"recv","msg":...}`, deltas included, with any `"email"` value replaced by `[redacted]`. + +The tests in `internal/codex/session_internal_test.go` are scenarios (commit identity, text deltas, interrupt, image input, resume, model switch, compaction), each run two ways: + +- `TestLive` runs it against the real CLI with the models named by `testModel` and `switchModel`, and writes transcripts to `internal/codex/testdata/transcripts/` (gitignored). +- `TestContract` runs the same scenario against the committed transcripts in `internal/codex/testdata/contract/`. A replay server stands in for the CLI: it expects each recorded `send` line in turn (method and params equal, `cwd` aside) and writes each recorded `recv` line, so the client must send exactly what the recording shows and handle exactly what the server sent. + +Both then decode every received line of their transcripts strictly into the generated types, so a field or method the types don't know fails the test. After a CLI update: `go generate ./internal/codex`, `go test ./internal/codex -run TestLive`, and when it passes, `cp internal/codex/testdata/transcripts/*.jsonl internal/codex/testdata/contract/`. Check the copies for anything private before committing them. diff --git a/docs/operations.md b/docs/operations.md index 94051c4..00a66aa 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -9,6 +9,7 @@ - `internal/git`: worktrees, the task changes view (see "Changes"), snapshots (see "Snapshots"), unmerged-change summaries, squash merges and pushes. - `internal/agents`: the agent session manager. It owns the running Claude processes, task agents and lead agents alike (see "Lead agent"), and records their activity as events. - `internal/claude`: the Claude Code stream-json client (see `docs/claude-protocol.md`). +- `internal/codex`: the `codex app-server` JSON-RPC client, with types generated from the CLI's schema by `go generate ./internal/codex` (see `docs/codex-protocol.md`). The agent manager doesn't use it yet. - `internal/push`: web push notifications for new inbox items (see "Notifications"). - `internal/tailscale`: `tailscale serve` for task previews (see "Previews"). - `web/`: the SPA, frameworkless TypeScript compiled file-by-file to ES modules (no bundler). `web/src/*.ts` is the source; `web/src/api.gen.ts` holds types generated from `api/openapi.yaml`, and `web/src/api.ts` is the typed client over them. `go generate ./web` runs `npm ci`, regenerates the types and compiles `web/dist/`, which is committed so `go install` needs no Node. The binary embeds `index.html`, `style.css`, `dist/`, `src/` (for source maps), `fonts/` and `vendor/` (Mermaid, see "Inbox"; xterm.js, see "Terminals"). `byre serve --dev` serves `./web` from disk instead (run from the repo root); pair it with `npm --prefix web exec tsc -- --watch`. diff --git a/internal/codex/badline_internal_test.go b/internal/codex/badline_internal_test.go new file mode 100644 index 0000000..c60e17a --- /dev/null +++ b/internal/codex/badline_internal_test.go @@ -0,0 +1,53 @@ +package codex + +import ( + "io" + "strings" + "testing" + "time" +) + +func TestBadLines(t *testing.T) { + bad := []string{} + input := strings.Join([]string{ + `{"method":"turn/started","params":{"threadId":"t","turn":{"id":"u","items":[],"status":"inProgress"}}}`, + ``, + `warning: something on stdout`, + `{"method":"turn/started",`, + `{"method":"mystery/event","params":{}}`, + `{"method":"turn/completed","params":{"threadId":"t","turn":{"id":"u","items":[],"status":"completed"}}}`, + }, "\n") + + before := time.Now() + r, w := io.Pipe() + s := newSession(Options{OnBadLine: func(line []byte, reason string) { + bad = append(bad, string(line)+" | "+reason) + }}, w, strings.NewReader(input)) + + methods := []string{} + for ev := range s.events { + methods = append(methods, ev.Method) + } + r.Close() + + want := []string{ + `warning: something on stdout | not a JSON object`, + `{"method":"turn/started", | unexpected end of JSON input`, + `{"method":"mystery/event","params":{}} | unrecognised method "mystery/event"`, + } + if strings.Join(bad, "\n") != strings.Join(want, "\n") { + t.Errorf("bad lines:\n%s\nwant:\n%s", strings.Join(bad, "\n"), strings.Join(want, "\n")) + } + if strings.Join(methods, ",") != "turn/started,mystery/event,turn/completed" { + t.Errorf("events = %v", methods) + } + if s.TurnID() != "" { + t.Errorf("turn %q still tracked after turn/completed", s.TurnID()) + } + if s.LastLine().Before(before) { + t.Errorf("last line time %v not updated", s.LastLine()) + } + if !s.Exited() { + t.Errorf("session not exited after stdout closed") + } +} diff --git a/internal/codex/gen/main.go b/internal/codex/gen/main.go new file mode 100644 index 0000000..77ff9b6 --- /dev/null +++ b/internal/codex/gen/main.go @@ -0,0 +1,685 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "go/format" + "log" + "os" + "os/exec" + "path/filepath" + "slices" + "strings" + "unicode" +) + +var clientMethods = []string{ + "initialize", + "thread/start", + "thread/resume", + "thread/read", + "thread/compact/start", + "turn/start", + "turn/interrupt", +} + +type schema struct { + any bool + Ref string `json:"$ref"` + Type json.RawMessage `json:"type"` + Enum []json.RawMessage `json:"enum"` + Title string `json:"title"` + Properties map[string]*schema `json:"properties"` + Required []string `json:"required"` + Items *schema `json:"items"` + AdditionalProperties *schema `json:"additionalProperties"` + OneOf []*schema `json:"oneOf"` + AnyOf []*schema `json:"anyOf"` + AllOf []*schema `json:"allOf"` +} + +func (s *schema) UnmarshalJSON(b []byte) error { + b = bytes.TrimSpace(b) + if bytes.Equal(b, []byte("true")) || bytes.Equal(b, []byte("false")) { + s.any = true + return nil + } + type plain schema + return json.Unmarshal(b, (*plain)(s)) +} + +func (s *schema) types() []string { + if len(s.Type) == 0 { + return nil + } + if s.Type[0] == '"' { + t := "" + err := json.Unmarshal(s.Type, &t) + if err != nil { + log.Fatalf("type: %v", err) + } + return []string{t} + } + ts := []string{} + err := json.Unmarshal(s.Type, &ts) + if err != nil { + log.Fatalf("type: %v", err) + } + return ts +} + +func (s *schema) isNull() bool { + ts := s.types() + return len(ts) == 1 && ts[0] == "null" && s.Ref == "" +} + +type bundle struct { + Definitions map[string]json.RawMessage `json:"definitions"` +} + +type gen struct { + defs map[string]*schema + order []string + emitted map[string]bool + kinds map[string]string + out bytes.Buffer + consts bytes.Buffer +} + +func main() { + dir, err := os.MkdirTemp("", "codex-schema") + if err != nil { + log.Fatalf("mkdir temp: %v", err) + } + defer os.RemoveAll(dir) + + cmd := exec.Command("codex", "app-server", "generate-json-schema", "--experimental", "--out", dir) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Run() + if err != nil { + log.Fatalf("generate schema: %v", err) + } + + version, err := exec.Command("codex", "--version").Output() + if err != nil { + log.Fatalf("codex version: %v", err) + } + + raw, err := os.ReadFile(filepath.Join(dir, "codex_app_server_protocol.schemas.json")) + if err != nil { + log.Fatalf("read schema: %v", err) + } + + b := bundle{} + err = json.Unmarshal(raw, &b) + if err != nil { + log.Fatalf("parse schema: %v", err) + } + + g := &gen{defs: map[string]*schema{}, emitted: map[string]bool{}, kinds: map[string]string{}} + g.load(b) + + src := g.generate(strings.TrimSpace(string(version))) + formatted, err := format.Source(src) + if err != nil { + os.WriteFile("protocol.gen.go", src, 0o644) + log.Fatalf("format: %v", err) + } + err = os.WriteFile("protocol.gen.go", formatted, 0o644) + if err != nil { + log.Fatalf("write: %v", err) + } +} + +func (g *gen) load(b bundle) { + top := map[string]json.RawMessage{} + for name, raw := range b.Definitions { + if name == "v2" { + continue + } + top[name] = raw + } + + v2 := map[string]json.RawMessage{} + err := json.Unmarshal(b.Definitions["v2"], &v2) + if err != nil { + log.Fatalf("parse v2 definitions: %v", err) + } + + for _, set := range []map[string]json.RawMessage{top, v2} { + for name, raw := range set { + s := &schema{} + err := json.Unmarshal(raw, s) + if err != nil { + log.Fatalf("parse %s: %v", name, err) + } + prev, ok := g.defs[name] + if ok { + p, q := *prev, *s + p.Title, q.Title = "", "" + a, _ := json.Marshal(p) + c, _ := json.Marshal(q) + if !bytes.Equal(a, c) { + log.Fatalf("definition %s differs between the top level and v2", name) + } + continue + } + g.defs[name] = s + } + } +} + +func refName(ref string) string { + i := strings.LastIndex(ref, "/") + return ref[i+1:] +} + +type method struct { + name string + params string + response string +} + +func (g *gen) variants(def string) []method { + s := g.defs[def] + if s == nil { + log.Fatalf("no definition %s", def) + } + ms := []method{} + for _, v := range s.OneOf { + m := v.Properties["method"] + if m == nil || len(m.Enum) != 1 { + log.Fatalf("%s variant without a single method", def) + } + name := "" + err := json.Unmarshal(m.Enum[0], &name) + if err != nil { + log.Fatalf("%s method: %v", def, err) + } + params := "" + if p := v.Properties["params"]; p != nil && p.Ref != "" { + params = refName(p.Ref) + } + response := "" + if strings.HasSuffix(params, "Params") { + r := strings.TrimSuffix(params, "Params") + "Response" + if g.defs[r] != nil { + response = r + } + } + ms = append(ms, method{name: name, params: params, response: response}) + } + return ms +} + +func (g *gen) generate(version string) []byte { + client := []method{} + for _, m := range g.variants("ClientRequest") { + if slices.Contains(clientMethods, m.name) { + client = append(client, m) + } + } + if len(client) != len(clientMethods) { + log.Fatalf("found %d of %d client methods", len(client), len(clientMethods)) + } + notifications := g.variants("ServerNotification") + requests := g.variants("ServerRequest") + + roots := []string{} + for _, set := range [][]method{client, notifications, requests} { + for _, m := range set { + if m.params != "" { + roots = append(roots, m.params) + } + if m.response != "" { + roots = append(roots, m.response) + } + } + } + for _, r := range roots { + g.named(r) + } + + h := bytes.Buffer{} + fmt.Fprintf(&h, "// Code generated by go run ./gen from the %s app-server schema. DO NOT EDIT.\n\n", version) + h.WriteString("package codex\n\nimport \"encoding/json\"\n\n") + fmt.Fprintf(&h, "const SchemaVersion = %q\n\n", version) + + h.WriteString("const (\n") + seen := map[string]bool{} + for _, set := range [][]method{client, notifications, requests} { + for _, m := range set { + c := "Method" + pascal(m.name) + if seen[c] { + continue + } + seen[c] = true + fmt.Fprintf(&h, "%s = %q\n", c, m.name) + } + } + h.WriteString(")\n\n") + + writeTable := func(name string, ms []method, field func(method) string) { + fmt.Fprintf(&h, "var %s = map[string]func() any{\n", name) + for _, m := range ms { + t := field(m) + if t == "" { + fmt.Fprintf(&h, "Method%s: nil,\n", pascal(m.name)) + continue + } + fmt.Fprintf(&h, "Method%s: func() any { return &%s{} },\n", pascal(m.name), t) + } + h.WriteString("}\n\n") + } + writeTable("clientResults", client, func(m method) string { return m.response }) + writeTable("notificationParams", notifications, func(m method) string { return m.params }) + writeTable("serverRequestParams", requests, func(m method) string { return m.params }) + writeTable("serverRequestResponses", requests, func(m method) string { return m.response }) + + h.Write(g.consts.Bytes()) + h.Write(g.out.Bytes()) + return h.Bytes() +} + +func (g *gen) named(name string) string { + s := g.defs[name] + if s == nil { + log.Fatalf("no definition %s", name) + } + if g.emitted[name] { + return name + } + g.emitted[name] = true + g.kinds[name] = g.kindOf(s) + g.emitType(name, s) + return name +} + +func (g *gen) resolve(s *schema) *schema { + for s.Ref != "" { + s = g.defs[refName(s.Ref)] + } + return s +} + +func nonNull(list []*schema) []*schema { + out := []*schema{} + for _, v := range list { + if !v.isNull() { + out = append(out, v) + } + } + return out +} + +func (g *gen) kindOf(s *schema) string { + if s.any { + return "raw" + } + if s.Ref != "" { + return g.kindOf(g.resolve(s)) + } + if len(s.AllOf) == 1 { + return g.kindOf(s.AllOf[0]) + } + alts := nonNull(append(append([]*schema{}, s.OneOf...), s.AnyOf...)) + if len(s.Properties) == 0 && len(alts) == 1 { + return g.kindOf(alts[0]) + } + if len(s.Properties) == 0 && len(alts) > 1 { + kinds := map[string]bool{} + for _, a := range alts { + kinds[g.kindOf(a)] = true + } + if len(kinds) == 1 && (kinds["string"] || kinds["struct"]) { + for k := range kinds { + return k + } + } + return "raw" + } + if len(s.Properties) > 0 { + return "struct" + } + ts := []string{} + for _, t := range s.types() { + if t != "null" { + ts = append(ts, t) + } + } + if len(ts) != 1 { + return "raw" + } + switch ts[0] { + case "string": + return "string" + case "integer", "number", "boolean": + return "scalar" + case "array": + return "slice" + case "object": + return "map" + } + return "raw" +} + +func (g *gen) emitType(name string, s *schema) { + switch g.kindOf(s) { + case "struct": + fields := g.collectFields(s) + g.emitStruct(name, fields) + g.emitDiscriminators(name, s) + case "string": + fmt.Fprintf(&g.out, "type %s string\n\n", name) + values := g.enumValues(s) + if len(values) > 0 { + g.consts.WriteString("const (\n") + for _, v := range values { + fmt.Fprintf(&g.consts, "%s%s %s = %q\n", name, pascal(v), name, v) + } + g.consts.WriteString(")\n\n") + } + default: + fmt.Fprintf(&g.out, "type %s = %s\n\n", name, g.goType(s, name)) + } +} + +func (g *gen) enumValues(s *schema) []string { + if s.Ref != "" { + return g.enumValues(g.resolve(s)) + } + out := []string{} + for _, e := range s.Enum { + v := "" + if json.Unmarshal(e, &v) == nil { + out = append(out, v) + } + } + for _, a := range append(append(append([]*schema{}, s.OneOf...), s.AnyOf...), s.AllOf...) { + for _, v := range g.enumValues(a) { + if !slices.Contains(out, v) { + out = append(out, v) + } + } + } + return out +} + +type field struct { + json string + schemas []*schema + required int + seen int +} + +type objectAlt struct { + props map[string]*schema + required []string +} + +func (g *gen) objectAlts(s *schema) []objectAlt { + if s.Ref != "" { + return g.objectAlts(g.resolve(s)) + } + if len(s.AllOf) == 1 && len(s.Properties) == 0 { + return g.objectAlts(s.AllOf[0]) + } + alts := nonNull(append(append([]*schema{}, s.OneOf...), s.AnyOf...)) + base := objectAlt{props: s.Properties, required: s.Required} + if len(alts) == 0 { + return []objectAlt{base} + } + out := []objectAlt{} + for _, a := range alts { + for _, sub := range g.objectAlts(a) { + props := map[string]*schema{} + for k, v := range base.props { + props[k] = v + } + for k, v := range sub.props { + props[k] = v + } + out = append(out, objectAlt{props: props, required: append(append([]string{}, base.required...), sub.required...)}) + } + } + return out +} + +func (g *gen) collectFields(s *schema) []*field { + alts := g.objectAlts(s) + byName := map[string]*field{} + names := []string{} + for _, a := range alts { + for k, v := range a.props { + f := byName[k] + if f == nil { + f = &field{json: k} + byName[k] = f + names = append(names, k) + } + f.schemas = append(f.schemas, v) + f.seen++ + if slices.Contains(a.required, k) { + f.required++ + } + } + } + slices.Sort(names) + out := []*field{} + for _, n := range names { + f := byName[n] + if f.seen < len(alts) { + f.required = 0 + } + out = append(out, f) + } + return out +} + +func (g *gen) emitStruct(name string, fields []*field) { + body := bytes.Buffer{} + used := map[string]bool{} + for _, f := range fields { + goName := fieldName(f.json) + for used[goName] { + goName += "_" + } + used[goName] = true + + types := map[string]bool{} + nullable := false + var first *schema + for _, fs := range f.schemas { + t, n := g.fieldType(fs, name+goName) + types[t] = true + nullable = nullable || n + if first == nil { + first = fs + } + } + t := "" + if len(types) == 1 { + for k := range types { + t = k + } + } else { + t = "json.RawMessage" + } + + required := f.required > 0 && f.required == f.seen && !nullable + if !required && g.kindOf(first) == "struct" && len(types) == 1 && !strings.HasPrefix(t, "*") { + t = "*" + t + } + tag := f.json + if !required { + tag += ",omitempty" + } + fmt.Fprintf(&body, "%s %s `json:%q`\n", goName, t, tag) + } + fmt.Fprintf(&g.out, "type %s struct {\n%s}\n\n", name, body.String()) +} + +func (g *gen) emitDiscriminators(name string, s *schema) { + r := g.resolve(s) + alts := nonNull(append(append([]*schema{}, r.OneOf...), r.AnyOf...)) + if len(alts) < 2 { + return + } + values := []string{} + for _, a := range alts { + a = g.resolve(a) + t := a.Properties["type"] + if t == nil || len(t.Enum) != 1 { + return + } + v := "" + if json.Unmarshal(t.Enum[0], &v) != nil { + return + } + values = append(values, v) + } + g.consts.WriteString("const (\n") + for _, v := range values { + fmt.Fprintf(&g.consts, "%sType%s = %q\n", name, pascal(v), v) + } + g.consts.WriteString(")\n\n") +} + +func (g *gen) fieldType(s *schema, ctx string) (string, bool) { + if s.any { + return "json.RawMessage", false + } + if s.Ref != "" { + return g.named(refName(s.Ref)), false + } + if len(s.AllOf) == 1 && len(s.Properties) == 0 { + return g.fieldType(s.AllOf[0], ctx) + } + all := append(append([]*schema{}, s.OneOf...), s.AnyOf...) + alts := nonNull(all) + nullable := len(alts) < len(all) + if len(s.Properties) == 0 && len(alts) == 1 { + t, n := g.fieldType(alts[0], ctx) + return t, n || nullable + } + ts := s.types() + if slices.Contains(ts, "null") { + nullable = true + } + return g.goType(s, ctx), nullable +} + +func (g *gen) goType(s *schema, ctx string) string { + switch g.kindOf(s) { + case "raw": + return "json.RawMessage" + case "struct": + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + if !g.emitted[ctx] { + g.emitted[ctx] = true + g.emitStruct(ctx, g.collectFields(s)) + g.emitDiscriminators(ctx, s) + } + return ctx + case "string": + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + alts := nonNull(append(append([]*schema{}, s.OneOf...), s.AnyOf...)) + if len(alts) == 1 { + return g.goType(alts[0], ctx) + } + return "string" + case "scalar": + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + for _, t := range s.types() { + switch t { + case "integer": + return "int64" + case "number": + return "float64" + case "boolean": + return "bool" + } + } + case "slice": + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + if s.Items == nil { + return "[]json.RawMessage" + } + t, _ := g.fieldType(s.Items, ctx+"Item") + return "[]" + t + case "map": + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + if s.AdditionalProperties == nil || s.AdditionalProperties.any { + return "map[string]any" + } + t, _ := g.fieldType(s.AdditionalProperties, ctx+"Value") + return "map[string]" + t + } + if s.Ref != "" { + return g.named(refName(s.Ref)) + } + alts := nonNull(append(append([]*schema{}, s.OneOf...), s.AnyOf...)) + if len(alts) == 1 { + return g.goType(alts[0], ctx) + } + return "json.RawMessage" +} + +func pascal(s string) string { + b := strings.Builder{} + up := true + for _, r := range s { + if !unicode.IsLetter(r) && !unicode.IsDigit(r) { + up = true + continue + } + if up { + b.WriteRune(unicode.ToUpper(r)) + up = false + continue + } + b.WriteRune(r) + } + out := b.String() + if out == "" || unicode.IsDigit(rune(out[0])) { + out = "X" + out + } + return out +} + +func fieldName(s string) string { + p := []rune(pascal(s)) + out := []rune{} + for i := 0; i < len(p); i++ { + end := func(n int) bool { return i+n == len(p) || unicode.IsUpper(p[i+n]) || unicode.IsDigit(p[i+n]) } + if i+1 < len(p) && p[i] == 'I' && p[i+1] == 'd' && end(2) { + out = append(out, 'I', 'D') + i++ + continue + } + if i+2 < len(p) && p[i] == 'I' && p[i+1] == 'd' && p[i+2] == 's' && end(3) { + out = append(out, 'I', 'D', 's') + i += 2 + continue + } + if i+2 < len(p) && p[i] == 'U' && p[i+1] == 'r' && p[i+2] == 'l' && end(3) { + out = append(out, 'U', 'R', 'L') + i += 2 + continue + } + out = append(out, p[i]) + } + return string(out) +} diff --git a/internal/codex/generate.go b/internal/codex/generate.go new file mode 100644 index 0000000..074a63e --- /dev/null +++ b/internal/codex/generate.go @@ -0,0 +1,3 @@ +package codex + +//go:generate go run ./gen diff --git a/internal/codex/protocol.gen.go b/internal/codex/protocol.gen.go new file mode 100644 index 0000000..bd03249 --- /dev/null +++ b/internal/codex/protocol.gen.go @@ -0,0 +1,2677 @@ +// Code generated by go run ./gen from the codex-cli 0.159.0 app-server schema. DO NOT EDIT. + +package codex + +import "encoding/json" + +const SchemaVersion = "codex-cli 0.159.0" + +const ( + MethodInitialize = "initialize" + MethodThreadStart = "thread/start" + MethodThreadResume = "thread/resume" + MethodThreadCompactStart = "thread/compact/start" + MethodThreadRead = "thread/read" + MethodTurnStart = "turn/start" + MethodTurnInterrupt = "turn/interrupt" + MethodError = "error" + MethodThreadStarted = "thread/started" + MethodThreadStatusChanged = "thread/status/changed" + MethodThreadArchived = "thread/archived" + MethodThreadDeleted = "thread/deleted" + MethodThreadUnarchived = "thread/unarchived" + MethodThreadClosed = "thread/closed" + MethodThreadReverted = "thread/reverted" + MethodSkillsChanged = "skills/changed" + MethodThreadNameUpdated = "thread/name/updated" + MethodThreadAttachmentUpdated = "thread/attachment/updated" + MethodThreadGoalUpdated = "thread/goal/updated" + MethodThreadGoalCleared = "thread/goal/cleared" + MethodThreadQueueChanged = "thread/queue/changed" + MethodProjectChanged = "project/changed" + MethodThreadProjectUpdated = "thread/project/updated" + MethodThreadEnvironmentConnected = "thread/environment/connected" + MethodThreadEnvironmentDisconnected = "thread/environment/disconnected" + MethodThreadSettingsUpdated = "thread/settings/updated" + MethodThreadTokenUsageUpdated = "thread/tokenUsage/updated" + MethodTurnStarted = "turn/started" + MethodHookStarted = "hook/started" + MethodTurnCompleted = "turn/completed" + MethodHookCompleted = "hook/completed" + MethodTurnDiffUpdated = "turn/diff/updated" + MethodTurnPlanUpdated = "turn/plan/updated" + MethodItemStarted = "item/started" + MethodItemAutoApprovalReviewStarted = "item/autoApprovalReview/started" + MethodItemAutoApprovalReviewCompleted = "item/autoApprovalReview/completed" + MethodAutoApprovalReviewStrictReviewRequired = "autoApprovalReview/strictReviewRequired" + MethodItemCompleted = "item/completed" + MethodItemAgentMessageDelta = "item/agentMessage/delta" + MethodItemPlanDelta = "item/plan/delta" + MethodCommandExecOutputDelta = "command/exec/outputDelta" + MethodProcessOutputDelta = "process/outputDelta" + MethodProcessExited = "process/exited" + MethodItemCommandExecutionOutputDelta = "item/commandExecution/outputDelta" + MethodItemCommandExecutionTerminalInteraction = "item/commandExecution/terminalInteraction" + MethodItemFileChangeOutputDelta = "item/fileChange/outputDelta" + MethodItemFileChangePatchUpdated = "item/fileChange/patchUpdated" + MethodServerRequestResolved = "serverRequest/resolved" + MethodItemMcpToolCallProgress = "item/mcpToolCall/progress" + MethodMcpServerOauthLoginCompleted = "mcpServer/oauthLogin/completed" + MethodMcpServerStartupStatusUpdated = "mcpServer/startupStatus/updated" + MethodMcpServerEventStreamNotification = "mcpServer/event/stream/notification" + MethodAccountUpdated = "account/updated" + MethodAccountGatewayOAuthChanged = "account/gatewayOAuth/changed" + MethodAccountRateLimitsUpdated = "account/rateLimits/updated" + MethodAppListUpdated = "app/list/updated" + MethodRemoteControlStatusChanged = "remoteControl/status/changed" + MethodExternalAgentConfigImportProgress = "externalAgentConfig/import/progress" + MethodExternalAgentConfigImportCompleted = "externalAgentConfig/import/completed" + MethodFsChanged = "fs/changed" + MethodItemReasoningSummaryTextDelta = "item/reasoning/summaryTextDelta" + MethodItemReasoningSummaryPartAdded = "item/reasoning/summaryPartAdded" + MethodItemReasoningTextDelta = "item/reasoning/textDelta" + MethodThreadCompacted = "thread/compacted" + MethodModelRerouted = "model/rerouted" + MethodModelVerification = "model/verification" + MethodModelProviderAuthRecoveryStarted = "modelProvider/authRecoveryStarted" + MethodModelProviderAuthRecoveryCompleted = "modelProvider/authRecoveryCompleted" + MethodTurnModerationMetadata = "turn/moderationMetadata" + MethodModelSafetyBufferingUpdated = "model/safetyBuffering/updated" + MethodWarning = "warning" + MethodGuardianWarning = "guardianWarning" + MethodDeprecationNotice = "deprecationNotice" + MethodConfigWarning = "configWarning" + MethodFuzzyFileSearchSessionUpdated = "fuzzyFileSearch/sessionUpdated" + MethodFuzzyFileSearchSessionCompleted = "fuzzyFileSearch/sessionCompleted" + MethodThreadRealtimeStarted = "thread/realtime/started" + MethodThreadRealtimeItemAdded = "thread/realtime/itemAdded" + MethodThreadRealtimeItemStarted = "thread/realtime/item/started" + MethodThreadRealtimeItemTranscriptDelta = "thread/realtime/item/transcript/delta" + MethodThreadRealtimeItemCompleted = "thread/realtime/item/completed" + MethodThreadRealtimeTranscriptDelta = "thread/realtime/transcript/delta" + MethodThreadRealtimeTranscriptDone = "thread/realtime/transcript/done" + MethodThreadRealtimeOutputAudioDelta = "thread/realtime/outputAudio/delta" + MethodThreadRealtimeSdp = "thread/realtime/sdp" + MethodThreadRealtimeError = "thread/realtime/error" + MethodThreadRealtimeClosed = "thread/realtime/closed" + MethodWindowsWorldWritableWarning = "windows/worldWritableWarning" + MethodWindowsSandboxSetupCompleted = "windowsSandbox/setupCompleted" + MethodAccountLoginCompleted = "account/login/completed" + MethodItemCommandExecutionRequestApproval = "item/commandExecution/requestApproval" + MethodItemFileChangeRequestApproval = "item/fileChange/requestApproval" + MethodItemToolRequestUserInput = "item/tool/requestUserInput" + MethodMcpServerElicitationRequest = "mcpServer/elicitation/request" + MethodItemPermissionsRequestApproval = "item/permissions/requestApproval" + MethodItemToolCall = "item/tool/call" + MethodAccountChatgptAuthTokensRefresh = "account/chatgptAuthTokens/refresh" + MethodAttestationGenerate = "attestation/generate" + MethodCurrentTimeRead = "currentTime/read" + MethodApplyPatchApproval = "applyPatchApproval" + MethodExecCommandApproval = "execCommandApproval" +) + +var clientResults = map[string]func() any{ + MethodInitialize: func() any { return &InitializeResponse{} }, + MethodThreadStart: func() any { return &ThreadStartResponse{} }, + MethodThreadResume: func() any { return &ThreadResumeResponse{} }, + MethodThreadCompactStart: func() any { return &ThreadCompactStartResponse{} }, + MethodThreadRead: func() any { return &ThreadReadResponse{} }, + MethodTurnStart: func() any { return &TurnStartResponse{} }, + MethodTurnInterrupt: func() any { return &TurnInterruptResponse{} }, +} + +var notificationParams = map[string]func() any{ + MethodError: func() any { return &ErrorNotification{} }, + MethodThreadStarted: func() any { return &ThreadStartedNotification{} }, + MethodThreadStatusChanged: func() any { return &ThreadStatusChangedNotification{} }, + MethodThreadArchived: func() any { return &ThreadArchivedNotification{} }, + MethodThreadDeleted: func() any { return &ThreadDeletedNotification{} }, + MethodThreadUnarchived: func() any { return &ThreadUnarchivedNotification{} }, + MethodThreadClosed: func() any { return &ThreadClosedNotification{} }, + MethodThreadReverted: func() any { return &ThreadRevertedNotification{} }, + MethodSkillsChanged: func() any { return &SkillsChangedNotification{} }, + MethodThreadNameUpdated: func() any { return &ThreadNameUpdatedNotification{} }, + MethodThreadAttachmentUpdated: func() any { return &ThreadAttachmentUpdatedNotification{} }, + MethodThreadGoalUpdated: func() any { return &ThreadGoalUpdatedNotification{} }, + MethodThreadGoalCleared: func() any { return &ThreadGoalClearedNotification{} }, + MethodThreadQueueChanged: func() any { return &ThreadQueueChangedNotification{} }, + MethodProjectChanged: func() any { return &ProjectChangedNotification{} }, + MethodThreadProjectUpdated: func() any { return &ThreadProjectUpdatedNotification{} }, + MethodThreadEnvironmentConnected: func() any { return &EnvironmentConnectionNotification{} }, + MethodThreadEnvironmentDisconnected: func() any { return &EnvironmentConnectionNotification{} }, + MethodThreadSettingsUpdated: func() any { return &ThreadSettingsUpdatedNotification{} }, + MethodThreadTokenUsageUpdated: func() any { return &ThreadTokenUsageUpdatedNotification{} }, + MethodTurnStarted: func() any { return &TurnStartedNotification{} }, + MethodHookStarted: func() any { return &HookStartedNotification{} }, + MethodTurnCompleted: func() any { return &TurnCompletedNotification{} }, + MethodHookCompleted: func() any { return &HookCompletedNotification{} }, + MethodTurnDiffUpdated: func() any { return &TurnDiffUpdatedNotification{} }, + MethodTurnPlanUpdated: func() any { return &TurnPlanUpdatedNotification{} }, + MethodItemStarted: func() any { return &ItemStartedNotification{} }, + MethodItemAutoApprovalReviewStarted: func() any { return &ItemGuardianApprovalReviewStartedNotification{} }, + MethodItemAutoApprovalReviewCompleted: func() any { return &ItemGuardianApprovalReviewCompletedNotification{} }, + MethodAutoApprovalReviewStrictReviewRequired: func() any { return &StrictReviewRequiredNotification{} }, + MethodItemCompleted: func() any { return &ItemCompletedNotification{} }, + MethodItemAgentMessageDelta: func() any { return &AgentMessageDeltaNotification{} }, + MethodItemPlanDelta: func() any { return &PlanDeltaNotification{} }, + MethodCommandExecOutputDelta: func() any { return &CommandExecOutputDeltaNotification{} }, + MethodProcessOutputDelta: func() any { return &ProcessOutputDeltaNotification{} }, + MethodProcessExited: func() any { return &ProcessExitedNotification{} }, + MethodItemCommandExecutionOutputDelta: func() any { return &CommandExecutionOutputDeltaNotification{} }, + MethodItemCommandExecutionTerminalInteraction: func() any { return &TerminalInteractionNotification{} }, + MethodItemFileChangeOutputDelta: func() any { return &FileChangeOutputDeltaNotification{} }, + MethodItemFileChangePatchUpdated: func() any { return &FileChangePatchUpdatedNotification{} }, + MethodServerRequestResolved: func() any { return &ServerRequestResolvedNotification{} }, + MethodItemMcpToolCallProgress: func() any { return &McpToolCallProgressNotification{} }, + MethodMcpServerOauthLoginCompleted: func() any { return &McpServerOauthLoginCompletedNotification{} }, + MethodMcpServerStartupStatusUpdated: func() any { return &McpServerStatusUpdatedNotification{} }, + MethodMcpServerEventStreamNotification: func() any { return &McpServerEventStreamNotification{} }, + MethodAccountUpdated: func() any { return &AccountUpdatedNotification{} }, + MethodAccountGatewayOAuthChanged: func() any { return &GatewayOAuthChangedNotification{} }, + MethodAccountRateLimitsUpdated: func() any { return &AccountRateLimitsUpdatedNotification{} }, + MethodAppListUpdated: func() any { return &AppListUpdatedNotification{} }, + MethodRemoteControlStatusChanged: func() any { return &RemoteControlStatusChangedNotification{} }, + MethodExternalAgentConfigImportProgress: func() any { return &ExternalAgentConfigImportProgressNotification{} }, + MethodExternalAgentConfigImportCompleted: func() any { return &ExternalAgentConfigImportCompletedNotification{} }, + MethodFsChanged: func() any { return &FsChangedNotification{} }, + MethodItemReasoningSummaryTextDelta: func() any { return &ReasoningSummaryTextDeltaNotification{} }, + MethodItemReasoningSummaryPartAdded: func() any { return &ReasoningSummaryPartAddedNotification{} }, + MethodItemReasoningTextDelta: func() any { return &ReasoningTextDeltaNotification{} }, + MethodThreadCompacted: func() any { return &ContextCompactedNotification{} }, + MethodModelRerouted: func() any { return &ModelReroutedNotification{} }, + MethodModelVerification: func() any { return &ModelVerificationNotification{} }, + MethodModelProviderAuthRecoveryStarted: func() any { return &AuthRecoveryNotification{} }, + MethodModelProviderAuthRecoveryCompleted: func() any { return &AuthRecoveryNotification{} }, + MethodTurnModerationMetadata: func() any { return &TurnModerationMetadataNotification{} }, + MethodModelSafetyBufferingUpdated: func() any { return &ModelSafetyBufferingUpdatedNotification{} }, + MethodWarning: func() any { return &WarningNotification{} }, + MethodGuardianWarning: func() any { return &GuardianWarningNotification{} }, + MethodDeprecationNotice: func() any { return &DeprecationNoticeNotification{} }, + MethodConfigWarning: func() any { return &ConfigWarningNotification{} }, + MethodFuzzyFileSearchSessionUpdated: func() any { return &FuzzyFileSearchSessionUpdatedNotification{} }, + MethodFuzzyFileSearchSessionCompleted: func() any { return &FuzzyFileSearchSessionCompletedNotification{} }, + MethodThreadRealtimeStarted: func() any { return &ThreadRealtimeStartedNotification{} }, + MethodThreadRealtimeItemAdded: func() any { return &ThreadRealtimeItemAddedNotification{} }, + MethodThreadRealtimeItemStarted: func() any { return &ThreadRealtimeItemStartedNotification{} }, + MethodThreadRealtimeItemTranscriptDelta: func() any { return &ThreadRealtimeItemTranscriptDeltaNotification{} }, + MethodThreadRealtimeItemCompleted: func() any { return &ThreadRealtimeItemCompletedNotification{} }, + MethodThreadRealtimeTranscriptDelta: func() any { return &ThreadRealtimeTranscriptDeltaNotification{} }, + MethodThreadRealtimeTranscriptDone: func() any { return &ThreadRealtimeTranscriptDoneNotification{} }, + MethodThreadRealtimeOutputAudioDelta: func() any { return &ThreadRealtimeOutputAudioDeltaNotification{} }, + MethodThreadRealtimeSdp: func() any { return &ThreadRealtimeSdpNotification{} }, + MethodThreadRealtimeError: func() any { return &ThreadRealtimeErrorNotification{} }, + MethodThreadRealtimeClosed: func() any { return &ThreadRealtimeClosedNotification{} }, + MethodWindowsWorldWritableWarning: func() any { return &WindowsWorldWritableWarningNotification{} }, + MethodWindowsSandboxSetupCompleted: func() any { return &WindowsSandboxSetupCompletedNotification{} }, + MethodAccountLoginCompleted: func() any { return &AccountLoginCompletedNotification{} }, +} + +var serverRequestParams = map[string]func() any{ + MethodItemCommandExecutionRequestApproval: func() any { return &CommandExecutionRequestApprovalParams{} }, + MethodItemFileChangeRequestApproval: func() any { return &FileChangeRequestApprovalParams{} }, + MethodItemToolRequestUserInput: func() any { return &ToolRequestUserInputParams{} }, + MethodMcpServerElicitationRequest: func() any { return &McpServerElicitationRequestParams{} }, + MethodItemPermissionsRequestApproval: func() any { return &PermissionsRequestApprovalParams{} }, + MethodItemToolCall: func() any { return &DynamicToolCallParams{} }, + MethodAccountChatgptAuthTokensRefresh: func() any { return &ChatgptAuthTokensRefreshParams{} }, + MethodAttestationGenerate: func() any { return &AttestationGenerateParams{} }, + MethodCurrentTimeRead: func() any { return &CurrentTimeReadParams{} }, + MethodApplyPatchApproval: func() any { return &ApplyPatchApprovalParams{} }, + MethodExecCommandApproval: func() any { return &ExecCommandApprovalParams{} }, +} + +var serverRequestResponses = map[string]func() any{ + MethodItemCommandExecutionRequestApproval: func() any { return &CommandExecutionRequestApprovalResponse{} }, + MethodItemFileChangeRequestApproval: func() any { return &FileChangeRequestApprovalResponse{} }, + MethodItemToolRequestUserInput: func() any { return &ToolRequestUserInputResponse{} }, + MethodMcpServerElicitationRequest: func() any { return &McpServerElicitationRequestResponse{} }, + MethodItemPermissionsRequestApproval: func() any { return &PermissionsRequestApprovalResponse{} }, + MethodItemToolCall: func() any { return &DynamicToolCallResponse{} }, + MethodAccountChatgptAuthTokensRefresh: func() any { return &ChatgptAuthTokensRefreshResponse{} }, + MethodAttestationGenerate: func() any { return &AttestationGenerateResponse{} }, + MethodCurrentTimeRead: func() any { return &CurrentTimeReadResponse{} }, + MethodApplyPatchApproval: func() any { return &ApplyPatchApprovalResponse{} }, + MethodExecCommandApproval: func() any { return &ExecCommandApprovalResponse{} }, +} + +const ( + ApprovalsReviewerUser ApprovalsReviewer = "user" + ApprovalsReviewerAutoReview ApprovalsReviewer = "auto_review" + ApprovalsReviewerGuardianSubagent ApprovalsReviewer = "guardian_subagent" +) + +const ( + DynamicToolSpecTypeFunction = "function" + DynamicToolSpecTypeNamespace = "namespace" +) + +const ( + ThreadHistoryModeLegacy ThreadHistoryMode = "legacy" + ThreadHistoryModePaginated ThreadHistoryMode = "paginated" +) + +const ( + PersonalityNone Personality = "none" + PersonalityFriendly Personality = "friendly" + PersonalityPragmatic Personality = "pragmatic" +) + +const ( + SandboxModeReadOnly SandboxMode = "read-only" + SandboxModeWorkspaceWrite SandboxMode = "workspace-write" + SandboxModeDangerFullAccess SandboxMode = "danger-full-access" +) + +const ( + ThreadStartSourceStartup ThreadStartSource = "startup" + ThreadStartSourceClear ThreadStartSource = "clear" +) + +const ( + NetworkAccessRestricted NetworkAccess = "restricted" + NetworkAccessEnabled NetworkAccess = "enabled" +) + +const ( + SandboxPolicyTypeDangerFullAccess = "dangerFullAccess" + SandboxPolicyTypeReadOnly = "readOnly" + SandboxPolicyTypeExternalSandbox = "externalSandbox" + SandboxPolicyTypeWorkspaceWrite = "workspaceWrite" +) + +const ( + ThreadActiveFlagWaitingOnApproval ThreadActiveFlag = "waitingOnApproval" + ThreadActiveFlagWaitingOnUserInput ThreadActiveFlag = "waitingOnUserInput" +) + +const ( + ThreadStatusTypeNotLoaded = "notLoaded" + ThreadStatusTypeIdle = "idle" + ThreadStatusTypeSystemError = "systemError" + ThreadStatusTypeActive = "active" +) + +const ( + WebSearchActionTypeSearch = "search" + WebSearchActionTypeOpenPage = "openPage" + WebSearchActionTypeFindInPage = "findInPage" + WebSearchActionTypeOther = "other" +) + +const ( + CollabAgentStatusPendingInit CollabAgentStatus = "pendingInit" + CollabAgentStatusRunning CollabAgentStatus = "running" + CollabAgentStatusInterrupted CollabAgentStatus = "interrupted" + CollabAgentStatusCompleted CollabAgentStatus = "completed" + CollabAgentStatusErrored CollabAgentStatus = "errored" + CollabAgentStatusShutdown CollabAgentStatus = "shutdown" + CollabAgentStatusNotFound CollabAgentStatus = "notFound" +) + +const ( + PatchChangeKindTypeAdd = "add" + PatchChangeKindTypeDelete = "delete" + PatchChangeKindTypeUpdate = "update" +) + +const ( + CommandActionTypeRead = "read" + CommandActionTypeListFiles = "listFiles" + CommandActionTypeSearch = "search" + CommandActionTypeUnknown = "unknown" +) + +const ( + ImageDetailAuto ImageDetail = "auto" + ImageDetailLow ImageDetail = "low" + ImageDetailHigh ImageDetail = "high" + ImageDetailOriginal ImageDetail = "original" +) + +const ( + UserInputTypeText = "text" + UserInputTypeImage = "image" + UserInputTypeLocalImage = "localImage" + UserInputTypeAudio = "audio" + UserInputTypeLocalAudio = "localAudio" + UserInputTypeSkill = "skill" + UserInputTypeMention = "mention" +) + +const ( + DynamicToolCallOutputContentItemTypeInputText = "inputText" + DynamicToolCallOutputContentItemTypeInputImage = "inputImage" + DynamicToolCallOutputContentItemTypeInputAudio = "inputAudio" +) + +const ( + AgentMessageDeliveryAsync AgentMessageDelivery = "async" +) + +const ( + SubAgentActivityKindStarted SubAgentActivityKind = "started" + SubAgentActivityKindInteracted SubAgentActivityKind = "interacted" + SubAgentActivityKindInterrupted SubAgentActivityKind = "interrupted" + SubAgentActivityKindCompleted SubAgentActivityKind = "completed" +) + +const ( + McpAppDisplayModeInline McpAppDisplayMode = "inline" + McpAppDisplayModeFullscreen McpAppDisplayMode = "fullscreen" +) + +const ( + MessagePhaseCommentary MessagePhase = "commentary" + MessagePhaseFinalAnswer MessagePhase = "final_answer" +) + +const ( + CommandExecutionSourceAgent CommandExecutionSource = "agent" + CommandExecutionSourceUserShell CommandExecutionSource = "userShell" + CommandExecutionSourceUnifiedExecStartup CommandExecutionSource = "unifiedExecStartup" + CommandExecutionSourceUnifiedExecInteraction CommandExecutionSource = "unifiedExecInteraction" +) + +const ( + CommandExecutionStatusInProgress CommandExecutionStatus = "inProgress" + CommandExecutionStatusCompleted CommandExecutionStatus = "completed" + CommandExecutionStatusFailed CommandExecutionStatus = "failed" + CommandExecutionStatusDeclined CommandExecutionStatus = "declined" +) + +const ( + PatchApplyStatusInProgress PatchApplyStatus = "inProgress" + PatchApplyStatusCompleted PatchApplyStatus = "completed" + PatchApplyStatusFailed PatchApplyStatus = "failed" + PatchApplyStatusDeclined PatchApplyStatus = "declined" +) + +const ( + McpToolCallStatusInProgress McpToolCallStatus = "inProgress" + McpToolCallStatusCompleted McpToolCallStatus = "completed" + McpToolCallStatusFailed McpToolCallStatus = "failed" +) + +const ( + DynamicToolCallStatusInProgress DynamicToolCallStatus = "inProgress" + DynamicToolCallStatusCompleted DynamicToolCallStatus = "completed" + DynamicToolCallStatusFailed DynamicToolCallStatus = "failed" +) + +const ( + CollabAgentToolCallStatusInProgress CollabAgentToolCallStatus = "inProgress" + CollabAgentToolCallStatusCompleted CollabAgentToolCallStatus = "completed" + CollabAgentToolCallStatusFailed CollabAgentToolCallStatus = "failed" + CollabAgentToolCallStatusInterrupted CollabAgentToolCallStatus = "interrupted" +) + +const ( + CollabAgentToolSpawnAgent CollabAgentTool = "spawnAgent" + CollabAgentToolSendInput CollabAgentTool = "sendInput" + CollabAgentToolResumeAgent CollabAgentTool = "resumeAgent" + CollabAgentToolWait CollabAgentTool = "wait" + CollabAgentToolCloseAgent CollabAgentTool = "closeAgent" + CollabAgentToolSendMessage CollabAgentTool = "sendMessage" + CollabAgentToolFollowupTask CollabAgentTool = "followupTask" + CollabAgentToolInterruptAgent CollabAgentTool = "interruptAgent" + CollabAgentToolListAgents CollabAgentTool = "listAgents" +) + +const ( + ThreadItemTypeUserMessage = "userMessage" + ThreadItemTypeHookPrompt = "hookPrompt" + ThreadItemTypeAgentMessage = "agentMessage" + ThreadItemTypeFunctionCallOutput = "functionCallOutput" + ThreadItemTypePlan = "plan" + ThreadItemTypeReasoning = "reasoning" + ThreadItemTypeCommandExecution = "commandExecution" + ThreadItemTypeFileChange = "fileChange" + ThreadItemTypeMcpToolCall = "mcpToolCall" + ThreadItemTypeDynamicToolCall = "dynamicToolCall" + ThreadItemTypeCollabAgentToolCall = "collabAgentToolCall" + ThreadItemTypeSubAgentActivity = "subAgentActivity" + ThreadItemTypeWebSearch = "webSearch" + ThreadItemTypeImageView = "imageView" + ThreadItemTypeSleep = "sleep" + ThreadItemTypeImageGeneration = "imageGeneration" + ThreadItemTypeEnteredReviewMode = "enteredReviewMode" + ThreadItemTypeExitedReviewMode = "exitedReviewMode" + ThreadItemTypeContextCompaction = "contextCompaction" +) + +const ( + TurnItemsViewNotLoaded TurnItemsView = "notLoaded" + TurnItemsViewSummary TurnItemsView = "summary" + TurnItemsViewFull TurnItemsView = "full" +) + +const ( + TurnStatusCompleted TurnStatus = "completed" + TurnStatusInterrupted TurnStatus = "interrupted" + TurnStatusFailed TurnStatus = "failed" + TurnStatusInProgress TurnStatus = "inProgress" +) + +const ( + ResponsesApiWebSearchActionTypeSearch = "search" + ResponsesApiWebSearchActionTypeOpenPage = "open_page" + ResponsesApiWebSearchActionTypeFindInPage = "find_in_page" + ResponsesApiWebSearchActionTypeOther = "other" +) + +const ( + ContentItemTypeInputText = "input_text" + ContentItemTypeInputImage = "input_image" + ContentItemTypeInputAudio = "input_audio" + ContentItemTypeOutputText = "output_text" +) + +const ( + AgentMessageInputContentTypeInputText = "input_text" + AgentMessageInputContentTypeEncryptedContent = "encrypted_content" +) + +const ( + ReasoningItemContentTypeReasoningText = "reasoning_text" + ReasoningItemContentTypeText = "text" +) + +const ( + LocalShellStatusCompleted LocalShellStatus = "completed" + LocalShellStatusInProgress LocalShellStatus = "in_progress" + LocalShellStatusIncomplete LocalShellStatus = "incomplete" +) + +const ( + ResponseItemTypeMessage = "message" + ResponseItemTypeAgentMessage = "agent_message" + ResponseItemTypeReasoning = "reasoning" + ResponseItemTypeLocalShellCall = "local_shell_call" + ResponseItemTypeFunctionCall = "function_call" + ResponseItemTypeToolSearchCall = "tool_search_call" + ResponseItemTypeFunctionCallOutput = "function_call_output" + ResponseItemTypeCustomToolCall = "custom_tool_call" + ResponseItemTypeCustomToolCallOutput = "custom_tool_call_output" + ResponseItemTypeToolSearchOutput = "tool_search_output" + ResponseItemTypeWebSearchCall = "web_search_call" + ResponseItemTypeImageGenerationCall = "image_generation_call" + ResponseItemTypeCompaction = "compaction" + ResponseItemTypeConfigurationUpdate = "configuration_update" + ResponseItemTypeCompactionTrigger = "compaction_trigger" + ResponseItemTypeContextCompaction = "context_compaction" + ResponseItemTypeOther = "other" +) + +const ( + SortDirectionAsc SortDirection = "asc" + SortDirectionDesc SortDirection = "desc" +) + +const ( + ModeKindPlan ModeKind = "plan" + ModeKindDefault ModeKind = "default" +) + +const ( + AdditionalContextKindUntrusted AdditionalContextKind = "untrusted" + AdditionalContextKindApplication AdditionalContextKind = "application" +) + +const ( + CyberAccessProgramStandard CyberAccessProgram = "standard" + CyberAccessProgramDaybreakBlue CyberAccessProgram = "daybreakBlue" + CyberAccessProgramDaybreakRed CyberAccessProgram = "daybreakRed" +) + +const ( + ReasoningSummaryAuto ReasoningSummary = "auto" + ReasoningSummaryConcise ReasoningSummary = "concise" + ReasoningSummaryDetailed ReasoningSummary = "detailed" + ReasoningSummaryNone ReasoningSummary = "none" +) + +const ( + ThreadAttachmentOperationCreated ThreadAttachmentOperation = "created" + ThreadAttachmentOperationDeleted ThreadAttachmentOperation = "deleted" +) + +const ( + ThreadGoalStatusActive ThreadGoalStatus = "active" + ThreadGoalStatusPaused ThreadGoalStatus = "paused" + ThreadGoalStatusBlocked ThreadGoalStatus = "blocked" + ThreadGoalStatusUsageLimited ThreadGoalStatus = "usageLimited" + ThreadGoalStatusBudgetLimited ThreadGoalStatus = "budgetLimited" + ThreadGoalStatusComplete ThreadGoalStatus = "complete" +) + +const ( + ProjectChangeTypeCreated ProjectChangeType = "created" + ProjectChangeTypeUpdated ProjectChangeType = "updated" + ProjectChangeTypeDeleted ProjectChangeType = "deleted" +) + +const ( + HookOutputEntryKindWarning HookOutputEntryKind = "warning" + HookOutputEntryKindStop HookOutputEntryKind = "stop" + HookOutputEntryKindFeedback HookOutputEntryKind = "feedback" + HookOutputEntryKindContext HookOutputEntryKind = "context" + HookOutputEntryKindError HookOutputEntryKind = "error" +) + +const ( + HookEventNamePreToolUse HookEventName = "preToolUse" + HookEventNamePermissionRequest HookEventName = "permissionRequest" + HookEventNamePostToolUse HookEventName = "postToolUse" + HookEventNamePreCompact HookEventName = "preCompact" + HookEventNamePostCompact HookEventName = "postCompact" + HookEventNameSessionStart HookEventName = "sessionStart" + HookEventNameSessionEnd HookEventName = "sessionEnd" + HookEventNameUserPromptSubmit HookEventName = "userPromptSubmit" + HookEventNameSubagentStart HookEventName = "subagentStart" + HookEventNameSubagentStop HookEventName = "subagentStop" + HookEventNameStop HookEventName = "stop" + HookEventNameInterrupt HookEventName = "interrupt" +) + +const ( + HookExecutionModeSync HookExecutionMode = "sync" + HookExecutionModeAsync HookExecutionMode = "async" +) + +const ( + HookHandlerTypeCommand HookHandlerType = "command" + HookHandlerTypeMcpTool HookHandlerType = "mcpTool" + HookHandlerTypePrompt HookHandlerType = "prompt" + HookHandlerTypeAgent HookHandlerType = "agent" +) + +const ( + HookScopeThread HookScope = "thread" + HookScopeTurn HookScope = "turn" +) + +const ( + HookSourceSystem HookSource = "system" + HookSourceUser HookSource = "user" + HookSourceProject HookSource = "project" + HookSourceMdm HookSource = "mdm" + HookSourceSessionFlags HookSource = "sessionFlags" + HookSourcePlugin HookSource = "plugin" + HookSourceCloudRequirements HookSource = "cloudRequirements" + HookSourceCloudManagedConfig HookSource = "cloudManagedConfig" + HookSourceLegacyManagedConfigFile HookSource = "legacyManagedConfigFile" + HookSourceLegacyManagedConfigMdm HookSource = "legacyManagedConfigMdm" + HookSourceUnknown HookSource = "unknown" +) + +const ( + HookRunStatusRunning HookRunStatus = "running" + HookRunStatusCompleted HookRunStatus = "completed" + HookRunStatusFailed HookRunStatus = "failed" + HookRunStatusBlocked HookRunStatus = "blocked" + HookRunStatusStopped HookRunStatus = "stopped" +) + +const ( + TurnPlanStepStatusPending TurnPlanStepStatus = "pending" + TurnPlanStepStatusInProgress TurnPlanStepStatus = "inProgress" + TurnPlanStepStatusCompleted TurnPlanStepStatus = "completed" +) + +const ( + FileSystemAccessModeRead FileSystemAccessMode = "read" + FileSystemAccessModeWrite FileSystemAccessMode = "write" + FileSystemAccessModeDeny FileSystemAccessMode = "deny" +) + +const ( + FileSystemPathTypePath = "path" + FileSystemPathTypeGlobPattern = "glob_pattern" + FileSystemPathTypeSpecial = "special" +) + +const ( + NetworkApprovalProtocolHttp NetworkApprovalProtocol = "http" + NetworkApprovalProtocolHttps NetworkApprovalProtocol = "https" + NetworkApprovalProtocolSocks5Tcp NetworkApprovalProtocol = "socks5Tcp" + NetworkApprovalProtocolSocks5Udp NetworkApprovalProtocol = "socks5Udp" +) + +const ( + GuardianCommandSourceShell GuardianCommandSource = "shell" + GuardianCommandSourceUnifiedExec GuardianCommandSource = "unifiedExec" +) + +const ( + GuardianApprovalReviewActionTypeCommand = "command" + GuardianApprovalReviewActionTypeExecve = "execve" + GuardianApprovalReviewActionTypeWriteStdin = "writeStdin" + GuardianApprovalReviewActionTypeApplyPatch = "applyPatch" + GuardianApprovalReviewActionTypeNetworkAccess = "networkAccess" + GuardianApprovalReviewActionTypeMcpToolCall = "mcpToolCall" + GuardianApprovalReviewActionTypeRequestPermissions = "requestPermissions" +) + +const ( + GuardianRiskLevelLow GuardianRiskLevel = "low" + GuardianRiskLevelMedium GuardianRiskLevel = "medium" + GuardianRiskLevelHigh GuardianRiskLevel = "high" + GuardianRiskLevelCritical GuardianRiskLevel = "critical" +) + +const ( + GuardianApprovalReviewStatusInProgress GuardianApprovalReviewStatus = "inProgress" + GuardianApprovalReviewStatusApproved GuardianApprovalReviewStatus = "approved" + GuardianApprovalReviewStatusDenied GuardianApprovalReviewStatus = "denied" + GuardianApprovalReviewStatusTimedOut GuardianApprovalReviewStatus = "timedOut" + GuardianApprovalReviewStatusAborted GuardianApprovalReviewStatus = "aborted" +) + +const ( + GuardianUserAuthorizationUnknown GuardianUserAuthorization = "unknown" + GuardianUserAuthorizationLow GuardianUserAuthorization = "low" + GuardianUserAuthorizationMedium GuardianUserAuthorization = "medium" + GuardianUserAuthorizationHigh GuardianUserAuthorization = "high" +) + +const ( + AutoReviewDecisionSourceAgent AutoReviewDecisionSource = "agent" +) + +const ( + CommandExecOutputStreamStdout CommandExecOutputStream = "stdout" + CommandExecOutputStreamStderr CommandExecOutputStream = "stderr" +) + +const ( + ProcessOutputStreamStdout ProcessOutputStream = "stdout" + ProcessOutputStreamStderr ProcessOutputStream = "stderr" +) + +const ( + McpServerStartupFailureReasonReauthenticationRequired McpServerStartupFailureReason = "reauthenticationRequired" +) + +const ( + McpServerStartupStateStarting McpServerStartupState = "starting" + McpServerStartupStateReady McpServerStartupState = "ready" + McpServerStartupStateFailed McpServerStartupState = "failed" + McpServerStartupStateCancelled McpServerStartupState = "cancelled" +) + +const ( + AuthModeApikey AuthMode = "apikey" + AuthModeChatgpt AuthMode = "chatgpt" + AuthModeChatgptAuthTokens AuthMode = "chatgptAuthTokens" + AuthModeHeaders AuthMode = "headers" + AuthModeAgentIdentity AuthMode = "agentIdentity" + AuthModePersonalAccessToken AuthMode = "personalAccessToken" + AuthModeBedrockApiKey AuthMode = "bedrockApiKey" + AuthModeBedrockAccessKeys AuthMode = "bedrockAccessKeys" +) + +const ( + PlanTypeFree PlanType = "free" + PlanTypeGo PlanType = "go" + PlanTypePlus PlanType = "plus" + PlanTypePro PlanType = "pro" + PlanTypeProlite PlanType = "prolite" + PlanTypePromax PlanType = "promax" + PlanTypeTeam PlanType = "team" + PlanTypeSelfServeBusinessProlite PlanType = "self_serve_business_prolite" + PlanTypeSelfServeBusinessUsageBased PlanType = "self_serve_business_usage_based" + PlanTypeBusiness PlanType = "business" + PlanTypeEnt26 PlanType = "ent26" + PlanTypeEnterpriseCbpAutomation PlanType = "enterprise_cbp_automation" + PlanTypeEnterpriseCbpUsageBased PlanType = "enterprise_cbp_usage_based" + PlanTypeEnterprise PlanType = "enterprise" + PlanTypeEdu PlanType = "edu" + PlanTypeEduPlus PlanType = "edu_plus" + PlanTypeEduPro PlanType = "edu_pro" + PlanTypeUnknown PlanType = "unknown" +) + +const ( + GatewayOAuthStatusNotReady GatewayOAuthStatus = "notReady" + GatewayOAuthStatusStarted GatewayOAuthStatus = "started" + GatewayOAuthStatusSucceeded GatewayOAuthStatus = "succeeded" + GatewayOAuthStatusFailed GatewayOAuthStatus = "failed" +) + +const ( + RateLimitReachedTypeRateLimitReached RateLimitReachedType = "rate_limit_reached" + RateLimitReachedTypeWorkspaceOwnerCreditsDepleted RateLimitReachedType = "workspace_owner_credits_depleted" + RateLimitReachedTypeWorkspaceMemberCreditsDepleted RateLimitReachedType = "workspace_member_credits_depleted" + RateLimitReachedTypeWorkspaceOwnerUsageLimitReached RateLimitReachedType = "workspace_owner_usage_limit_reached" + RateLimitReachedTypeWorkspaceMemberUsageLimitReached RateLimitReachedType = "workspace_member_usage_limit_reached" +) + +const ( + RemoteControlConnectionStatusDisabled RemoteControlConnectionStatus = "disabled" + RemoteControlConnectionStatusConnecting RemoteControlConnectionStatus = "connecting" + RemoteControlConnectionStatusConnected RemoteControlConnectionStatus = "connected" + RemoteControlConnectionStatusErrored RemoteControlConnectionStatus = "errored" +) + +const ( + ExternalAgentConfigMigrationItemTypeAGENTSMD ExternalAgentConfigMigrationItemType = "AGENTS_MD" + ExternalAgentConfigMigrationItemTypeCONFIG ExternalAgentConfigMigrationItemType = "CONFIG" + ExternalAgentConfigMigrationItemTypeSKILLS ExternalAgentConfigMigrationItemType = "SKILLS" + ExternalAgentConfigMigrationItemTypePLUGINS ExternalAgentConfigMigrationItemType = "PLUGINS" + ExternalAgentConfigMigrationItemTypeMCPSERVERCONFIG ExternalAgentConfigMigrationItemType = "MCP_SERVER_CONFIG" + ExternalAgentConfigMigrationItemTypeSUBAGENTS ExternalAgentConfigMigrationItemType = "SUBAGENTS" + ExternalAgentConfigMigrationItemTypeHOOKS ExternalAgentConfigMigrationItemType = "HOOKS" + ExternalAgentConfigMigrationItemTypeCOMMANDS ExternalAgentConfigMigrationItemType = "COMMANDS" + ExternalAgentConfigMigrationItemTypeMEMORY ExternalAgentConfigMigrationItemType = "MEMORY" + ExternalAgentConfigMigrationItemTypeSESSIONS ExternalAgentConfigMigrationItemType = "SESSIONS" +) + +const ( + ModelRerouteReasonHighRiskCyberActivity ModelRerouteReason = "highRiskCyberActivity" +) + +const ( + ModelVerificationTrustedAccessForCyber ModelVerification = "trustedAccessForCyber" +) + +const ( + FuzzyFileSearchMatchTypeFile FuzzyFileSearchMatchType = "file" + FuzzyFileSearchMatchTypeDirectory FuzzyFileSearchMatchType = "directory" +) + +const ( + RealtimeConversationVersionV1 RealtimeConversationVersion = "v1" + RealtimeConversationVersionV2 RealtimeConversationVersion = "v2" + RealtimeConversationVersionV3 RealtimeConversationVersion = "v3" +) + +const ( + ThreadRealtimeSessionOutcomeEnded ThreadRealtimeSessionOutcome = "ended" + ThreadRealtimeSessionOutcomeFailed ThreadRealtimeSessionOutcome = "failed" +) + +const ( + ThreadRealtimeBemItemPresentationTypeWholeItem = "wholeItem" + ThreadRealtimeBemItemPresentationTypeInlineMarkdown = "inlineMarkdown" + ThreadRealtimeBemItemPresentationTypeInlineVisualization = "inlineVisualization" +) + +const ( + ThreadRealtimeTranscriptRoleUser ThreadRealtimeTranscriptRole = "user" + ThreadRealtimeTranscriptRoleAssistant ThreadRealtimeTranscriptRole = "assistant" +) + +const ( + ThreadRealtimeItemTypeRealtimeSessionStarted = "realtimeSessionStarted" + ThreadRealtimeItemTypeTranscriptSegment = "transcriptSegment" + ThreadRealtimeItemTypeBemItemPromoted = "bemItemPromoted" + ThreadRealtimeItemTypeRealtimeSessionClosed = "realtimeSessionClosed" +) + +const ( + WindowsSandboxSetupModeElevated WindowsSandboxSetupMode = "elevated" + WindowsSandboxSetupModeUnelevated WindowsSandboxSetupMode = "unelevated" +) + +const ( + DesktopOnboardingEntrypointLifeSciences DesktopOnboardingEntrypoint = "life_sciences" +) + +const ( + CommandExecutionApprovalKindCommand CommandExecutionApprovalKind = "command" + CommandExecutionApprovalKindWriteStdin CommandExecutionApprovalKind = "writeStdin" +) + +const ( + NetworkPolicyRuleActionAllow NetworkPolicyRuleAction = "allow" + NetworkPolicyRuleActionDeny NetworkPolicyRuleAction = "deny" +) + +const ( + FileChangeApprovalDecisionAccept FileChangeApprovalDecision = "accept" + FileChangeApprovalDecisionAcceptForSession FileChangeApprovalDecision = "acceptForSession" + FileChangeApprovalDecisionDecline FileChangeApprovalDecision = "decline" + FileChangeApprovalDecisionCancel FileChangeApprovalDecision = "cancel" +) + +const ( + McpElicitationStringFormatEmail McpElicitationStringFormat = "email" + McpElicitationStringFormatUri McpElicitationStringFormat = "uri" + McpElicitationStringFormatDate McpElicitationStringFormat = "date" + McpElicitationStringFormatDateTime McpElicitationStringFormat = "date-time" +) + +const ( + McpElicitationStringTypeString McpElicitationStringType = "string" +) + +const ( + McpElicitationArrayTypeArray McpElicitationArrayType = "array" +) + +const ( + McpElicitationNumberTypeNumber McpElicitationNumberType = "number" + McpElicitationNumberTypeInteger McpElicitationNumberType = "integer" +) + +const ( + McpElicitationBooleanTypeBoolean McpElicitationBooleanType = "boolean" +) + +const ( + McpElicitationObjectTypeObject McpElicitationObjectType = "object" +) + +const ( + McpServerElicitationActionAccept McpServerElicitationAction = "accept" + McpServerElicitationActionDecline McpServerElicitationAction = "decline" + McpServerElicitationActionCancel McpServerElicitationAction = "cancel" +) + +const ( + PermissionGrantScopeTurn PermissionGrantScope = "turn" + PermissionGrantScopeSession PermissionGrantScope = "session" +) + +const ( + ChatgptAuthTokensRefreshReasonUnauthorized ChatgptAuthTokensRefreshReason = "unauthorized" +) + +const ( + FileChangeTypeAdd = "add" + FileChangeTypeDelete = "delete" + FileChangeTypeUpdate = "update" +) + +const ( + ParsedCommandTypeRead = "read" + ParsedCommandTypeListFiles = "list_files" + ParsedCommandTypeSearch = "search" + ParsedCommandTypeUnknown = "unknown" +) + +type InitializeCapabilities struct { + ExperimentalApi bool `json:"experimentalApi,omitempty"` + ExplicitGatewayOauth bool `json:"explicitGatewayOauth,omitempty"` + Extensions map[string]any `json:"extensions,omitempty"` + McpServerOpenaiFormElicitation bool `json:"mcpServerOpenaiFormElicitation,omitempty"` + OptOutNotificationMethods []string `json:"optOutNotificationMethods,omitempty"` + RequestAttestation bool `json:"requestAttestation,omitempty"` +} + +type ClientInfo struct { + Name string `json:"name"` + Title string `json:"title,omitempty"` + Version string `json:"version"` +} + +type InitializeParams struct { + Capabilities *InitializeCapabilities `json:"capabilities,omitempty"` + ClientInfo ClientInfo `json:"clientInfo"` +} + +type AbsolutePathBuf string + +type InitializeResponse struct { + CodexHome AbsolutePathBuf `json:"codexHome"` + PlatformFamily string `json:"platformFamily"` + PlatformOs string `json:"platformOs"` + UserAgent string `json:"userAgent"` +} + +type AskForApproval = json.RawMessage + +type ApprovalsReviewer string + +type DynamicToolNamespaceTool struct { + DeferLoading bool `json:"deferLoading,omitempty"` + Description string `json:"description"` + InputSchema json.RawMessage `json:"inputSchema"` + Name string `json:"name"` + Type string `json:"type"` +} + +type DynamicToolSpec struct { + DeferLoading bool `json:"deferLoading,omitempty"` + Description string `json:"description"` + InputSchema json.RawMessage `json:"inputSchema,omitempty"` + Name string `json:"name"` + Tools []DynamicToolNamespaceTool `json:"tools,omitempty"` + Type string `json:"type"` +} + +type LegacyAppPathString string + +type TurnEnvironmentParams struct { + Cwd LegacyAppPathString `json:"cwd"` + EnvironmentID string `json:"environmentId"` + RuntimeWorkspaceRoots []LegacyAppPathString `json:"runtimeWorkspaceRoots,omitempty"` +} + +type ThreadHistoryMode string + +type MultiAgentMode = json.RawMessage + +type Personality string + +type SandboxMode string + +type CapabilityRootLocation struct { + EnvironmentID string `json:"environmentId"` + Path string `json:"path"` + Type string `json:"type"` +} + +type SelectedCapabilityRoot struct { + ID string `json:"id"` + Location CapabilityRootLocation `json:"location"` +} + +type ThreadStartSource string + +type ThreadSource string + +type ThreadStartParams struct { + AllowProviderModelFallback bool `json:"allowProviderModelFallback,omitempty"` + ApprovalPolicy AskForApproval `json:"approvalPolicy,omitempty"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer,omitempty"` + BaseInstructions string `json:"baseInstructions,omitempty"` + Config map[string]any `json:"config,omitempty"` + Cwd string `json:"cwd,omitempty"` + DaybreakEnabled bool `json:"daybreakEnabled,omitempty"` + DeveloperInstructions string `json:"developerInstructions,omitempty"` + DynamicTools []DynamicToolSpec `json:"dynamicTools,omitempty"` + Environments []TurnEnvironmentParams `json:"environments,omitempty"` + Ephemeral bool `json:"ephemeral,omitempty"` + ExperimentalRawEvents bool `json:"experimentalRawEvents,omitempty"` + HistoryMode ThreadHistoryMode `json:"historyMode,omitempty"` + MockExperimentalField string `json:"mockExperimentalField,omitempty"` + Model string `json:"model,omitempty"` + ModelProvider string `json:"modelProvider,omitempty"` + MultiAgentMode MultiAgentMode `json:"multiAgentMode,omitempty"` + Permissions string `json:"permissions,omitempty"` + Personality Personality `json:"personality,omitempty"` + ProjectID string `json:"projectId,omitempty"` + RuntimeWorkspaceRoots []AbsolutePathBuf `json:"runtimeWorkspaceRoots,omitempty"` + Sandbox SandboxMode `json:"sandbox,omitempty"` + SelectedCapabilityRoots []SelectedCapabilityRoot `json:"selectedCapabilityRoots,omitempty"` + ServiceName string `json:"serviceName,omitempty"` + ServiceTier string `json:"serviceTier,omitempty"` + SessionStartSource ThreadStartSource `json:"sessionStartSource,omitempty"` + ThreadSource ThreadSource `json:"threadSource,omitempty"` +} + +type ActivePermissionProfile struct { + Extends string `json:"extends,omitempty"` + ID string `json:"id"` +} + +type ReasoningEffort string + +type NetworkAccess string + +type SandboxPolicy struct { + ExcludeSlashTmp bool `json:"excludeSlashTmp,omitempty"` + ExcludeTmpdirEnvVar bool `json:"excludeTmpdirEnvVar,omitempty"` + NetworkAccess json.RawMessage `json:"networkAccess,omitempty"` + Type string `json:"type"` + WritableRoots []AbsolutePathBuf `json:"writableRoots,omitempty"` +} + +type ThreadEnvironment struct { + Cwd LegacyAppPathString `json:"cwd"` + EnvironmentID string `json:"environmentId"` + RuntimeWorkspaceRoots []LegacyAppPathString `json:"runtimeWorkspaceRoots"` +} + +type ThreadExtra = map[string]any + +type GitInfo struct { + Branch string `json:"branch,omitempty"` + OriginURL string `json:"originUrl,omitempty"` + Sha string `json:"sha,omitempty"` +} + +type ThreadSectionAppearance struct { + Color string `json:"color,omitempty"` + Icon string `json:"icon,omitempty"` +} + +type ThreadSection struct { + Appearance *ThreadSectionAppearance `json:"appearance,omitempty"` + ID string `json:"id"` + Name string `json:"name"` +} + +type SessionSource = json.RawMessage + +type ThreadActiveFlag string + +type ThreadStatus struct { + ActiveFlags []ThreadActiveFlag `json:"activeFlags,omitempty"` + Type string `json:"type"` +} + +type CodexErrorInfo = json.RawMessage + +type MisalignmentSteer struct { + Message string `json:"message"` +} + +type MisalignmentErrorDetails struct { + DetailedExplanation string `json:"detailedExplanation,omitempty"` + ErrorType string `json:"errorType,omitempty"` + Steer *MisalignmentSteer `json:"steer,omitempty"` +} + +type TurnError struct { + AdditionalDetails string `json:"additionalDetails,omitempty"` + CodexErrorInfo CodexErrorInfo `json:"codexErrorInfo,omitempty"` + Message string `json:"message"` + Misalignment *MisalignmentErrorDetails `json:"misalignment,omitempty"` +} + +type WebSearchAction struct { + Pattern string `json:"pattern,omitempty"` + Queries []string `json:"queries,omitempty"` + Query string `json:"query,omitempty"` + Type string `json:"type"` + URL string `json:"url,omitempty"` +} + +type CollabAgentStatus string + +type CollabAgentState struct { + Message string `json:"message,omitempty"` + Status CollabAgentStatus `json:"status"` +} + +type McpToolCallAppContext struct { + ActionName string `json:"actionName,omitempty"` + AppName string `json:"appName,omitempty"` + ConnectorID string `json:"connectorId"` + LinkID string `json:"linkId,omitempty"` + ResourceUri string `json:"resourceUri,omitempty"` +} + +type PatchChangeKind struct { + MovePath string `json:"move_path,omitempty"` + Type string `json:"type"` +} + +type FileUpdateChange struct { + Diff string `json:"diff"` + Kind PatchChangeKind `json:"kind"` + Path string `json:"path"` +} + +type CommandAction struct { + Command string `json:"command"` + Name string `json:"name,omitempty"` + Path json.RawMessage `json:"path,omitempty"` + Query string `json:"query,omitempty"` + Type string `json:"type"` +} + +type ImageDetail string + +type ByteRange struct { + End int64 `json:"end"` + Start int64 `json:"start"` +} + +type TextElement struct { + ByteRange ByteRange `json:"byteRange"` + Placeholder string `json:"placeholder,omitempty"` +} + +type UserInput struct { + Detail ImageDetail `json:"detail,omitempty"` + FileID string `json:"fileId,omitempty"` + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` + Text string `json:"text,omitempty"` + TextElements []TextElement `json:"text_elements,omitempty"` + Type string `json:"type"` + URL string `json:"url,omitempty"` +} + +type DynamicToolCallOutputContentItem struct { + AudioURL string `json:"audioUrl,omitempty"` + ImageURL string `json:"imageUrl,omitempty"` + Text string `json:"text,omitempty"` + Type string `json:"type"` +} + +type AgentMessageDelivery string + +type McpToolCallError struct { + Message string `json:"message"` +} + +type ImageGenerationFailure struct { + LimitID string `json:"limitId"` + ResetsAt int64 `json:"resetsAt,omitempty"` + Type string `json:"type"` +} + +type HookPromptFragment struct { + HookRunID string `json:"hookRunId"` + Text string `json:"text"` +} + +type SubAgentActivityKind string + +type McpAppDisplayMode string + +type McpAppUi struct { + PreferredModelDisplayMode McpAppDisplayMode `json:"preferredModelDisplayMode"` + ResourceUri string `json:"resourceUri"` +} + +type MemoryCitationEntry struct { + LineEnd int64 `json:"lineEnd"` + LineStart int64 `json:"lineStart"` + Note string `json:"note"` + Path string `json:"path"` +} + +type MemoryCitation struct { + Entries []MemoryCitationEntry `json:"entries"` + ThreadIDs []string `json:"threadIds"` +} + +type FunctionCallOutputBody = json.RawMessage + +type MessagePhase string + +type AsyncUserInputQuestion struct { + Options []string `json:"options,omitempty"` + Title string `json:"title"` +} + +type McpToolCallResult struct { + Meta json.RawMessage `json:"_meta,omitempty"` + Content []json.RawMessage `json:"content"` + StructuredContent json.RawMessage `json:"structuredContent,omitempty"` +} + +type CommandExecutionSource string + +type CommandExecutionStatus string + +type PatchApplyStatus string + +type McpToolCallStatus string + +type DynamicToolCallStatus string + +type CollabAgentToolCallStatus string + +type CollabAgentTool string + +type ThreadItem struct { + Action *WebSearchAction `json:"action,omitempty"` + AgentPath string `json:"agentPath,omitempty"` + AgentThreadID string `json:"agentThreadId,omitempty"` + AgentsStates map[string]CollabAgentState `json:"agentsStates,omitempty"` + AggregatedOutput string `json:"aggregatedOutput,omitempty"` + AppContext *McpToolCallAppContext `json:"appContext,omitempty"` + Arguments json.RawMessage `json:"arguments,omitempty"` + Changes []FileUpdateChange `json:"changes,omitempty"` + ClientID string `json:"clientId,omitempty"` + Command string `json:"command,omitempty"` + CommandActions []CommandAction `json:"commandActions,omitempty"` + Content json.RawMessage `json:"content,omitempty"` + ContentItems []DynamicToolCallOutputContentItem `json:"contentItems,omitempty"` + Cwd LegacyAppPathString `json:"cwd,omitempty"` + Delivery AgentMessageDelivery `json:"delivery,omitempty"` + DurationMs int64 `json:"durationMs,omitempty"` + Error *McpToolCallError `json:"error,omitempty"` + ExitCode int64 `json:"exitCode,omitempty"` + Failure *ImageGenerationFailure `json:"failure,omitempty"` + Fragments []HookPromptFragment `json:"fragments,omitempty"` + ID string `json:"id"` + Kind SubAgentActivityKind `json:"kind,omitempty"` + McpAppResourceUri string `json:"mcpAppResourceUri,omitempty"` + McpAppUi *McpAppUi `json:"mcpAppUi,omitempty"` + MemoryCitation *MemoryCitation `json:"memoryCitation,omitempty"` + Model string `json:"model,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Output FunctionCallOutputBody `json:"output,omitempty"` + Path LegacyAppPathString `json:"path,omitempty"` + Phase MessagePhase `json:"phase,omitempty"` + PluginID string `json:"pluginId,omitempty"` + ProcessID string `json:"processId,omitempty"` + Prompt string `json:"prompt,omitempty"` + Query string `json:"query,omitempty"` + Questions []AsyncUserInputQuestion `json:"questions,omitempty"` + ReadOnlyHint bool `json:"readOnlyHint,omitempty"` + ReasoningEffort ReasoningEffort `json:"reasoningEffort,omitempty"` + ReceiverThreadIDs []string `json:"receiverThreadIds,omitempty"` + Result json.RawMessage `json:"result,omitempty"` + Results []json.RawMessage `json:"results,omitempty"` + Review string `json:"review,omitempty"` + RevisedPrompt string `json:"revisedPrompt,omitempty"` + SavedPath AbsolutePathBuf `json:"savedPath,omitempty"` + ScriptPath string `json:"scriptPath,omitempty"` + SenderThreadID string `json:"senderThreadId,omitempty"` + Server string `json:"server,omitempty"` + Source CommandExecutionSource `json:"source,omitempty"` + Status json.RawMessage `json:"status,omitempty"` + Success bool `json:"success,omitempty"` + Summary []string `json:"summary,omitempty"` + Text string `json:"text,omitempty"` + Tool json.RawMessage `json:"tool,omitempty"` + TransparentBackground bool `json:"transparentBackground,omitempty"` + Type string `json:"type"` +} + +type TurnItemsView string + +type TurnStatus string + +type Turn struct { + CompletedAt int64 `json:"completedAt,omitempty"` + DurationMs int64 `json:"durationMs,omitempty"` + Error *TurnError `json:"error,omitempty"` + ID string `json:"id"` + Items []ThreadItem `json:"items"` + ItemsView TurnItemsView `json:"itemsView,omitempty"` + StartedAt int64 `json:"startedAt,omitempty"` + Status TurnStatus `json:"status"` +} + +type Thread struct { + AgentNickname string `json:"agentNickname,omitempty"` + AgentRole string `json:"agentRole,omitempty"` + CanAcceptDirectInput bool `json:"canAcceptDirectInput,omitempty"` + CliVersion string `json:"cliVersion"` + CreatedAt int64 `json:"createdAt"` + Cwd AbsolutePathBuf `json:"cwd"` + DaybreakEnabled bool `json:"daybreakEnabled,omitempty"` + Environments []ThreadEnvironment `json:"environments,omitempty"` + Ephemeral bool `json:"ephemeral"` + Extra ThreadExtra `json:"extra,omitempty"` + ForkedFromID string `json:"forkedFromId,omitempty"` + GitInfo *GitInfo `json:"gitInfo,omitempty"` + HistoryMode ThreadHistoryMode `json:"historyMode,omitempty"` + ID string `json:"id"` + Model string `json:"model,omitempty"` + ModelProvider string `json:"modelProvider"` + Name string `json:"name,omitempty"` + Originator string `json:"originator,omitempty"` + ParentThreadID string `json:"parentThreadId,omitempty"` + Path string `json:"path,omitempty"` + Preview string `json:"preview"` + ProjectID string `json:"projectId,omitempty"` + ReasoningEffort ReasoningEffort `json:"reasoningEffort,omitempty"` + RecencyAt int64 `json:"recencyAt,omitempty"` + Section *ThreadSection `json:"section,omitempty"` + SectionEnteredAt int64 `json:"sectionEnteredAt,omitempty"` + SessionID string `json:"sessionId"` + Source SessionSource `json:"source"` + Status ThreadStatus `json:"status"` + ThreadSource ThreadSource `json:"threadSource,omitempty"` + Turns []Turn `json:"turns"` + UpdatedAt int64 `json:"updatedAt"` +} + +type ThreadStartResponse struct { + ActivePermissionProfile *ActivePermissionProfile `json:"activePermissionProfile,omitempty"` + ApprovalPolicy AskForApproval `json:"approvalPolicy"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer"` + Cwd AbsolutePathBuf `json:"cwd"` + DisabledPluginIDs []string `json:"disabledPluginIds,omitempty"` + InstructionSources []LegacyAppPathString `json:"instructionSources,omitempty"` + Model string `json:"model"` + ModelProvider string `json:"modelProvider"` + MultiAgentMode MultiAgentMode `json:"multiAgentMode,omitempty"` + ReasoningEffort ReasoningEffort `json:"reasoningEffort,omitempty"` + RuntimeWorkspaceRoots []AbsolutePathBuf `json:"runtimeWorkspaceRoots,omitempty"` + Sandbox SandboxPolicy `json:"sandbox"` + ServiceTier string `json:"serviceTier,omitempty"` + Thread Thread `json:"thread"` +} + +type LocalShellAction struct { + Command []string `json:"command"` + Env map[string]string `json:"env,omitempty"` + TimeoutMs int64 `json:"timeout_ms,omitempty"` + Type string `json:"type"` + User string `json:"user,omitempty"` + WorkingDirectory string `json:"working_directory,omitempty"` +} + +type ResponsesApiWebSearchAction struct { + Pattern string `json:"pattern,omitempty"` + Queries []string `json:"queries,omitempty"` + Query string `json:"query,omitempty"` + Type string `json:"type"` + URL string `json:"url,omitempty"` +} + +type ContentItem struct { + AudioURL string `json:"audio_url,omitempty"` + Detail ImageDetail `json:"detail,omitempty"` + FileID string `json:"file_id,omitempty"` + ImageURL string `json:"image_url,omitempty"` + Text string `json:"text,omitempty"` + Type string `json:"type"` +} + +type AgentMessageInputContent struct { + EncryptedContent string `json:"encrypted_content,omitempty"` + Text string `json:"text,omitempty"` + Type string `json:"type"` +} + +type ReasoningItemContent struct { + Text string `json:"text"` + Type string `json:"type"` +} + +type InternalChatMessageMetadataPassthrough struct { + TurnID string `json:"turn_id,omitempty"` +} + +type ConfigurationReasoning struct { + Effort ReasoningEffort `json:"effort"` +} + +type LocalShellStatus string + +type ReasoningItemReasoningSummary struct { + Text string `json:"text"` + Type string `json:"type"` +} + +type ResponseItem struct { + Action json.RawMessage `json:"action,omitempty"` + Arguments json.RawMessage `json:"arguments,omitempty"` + Author string `json:"author,omitempty"` + CallID string `json:"call_id,omitempty"` + Content json.RawMessage `json:"content,omitempty"` + EncryptedContent string `json:"encrypted_content,omitempty"` + EncryptedFunctionArgs []string `json:"encrypted_function_args,omitempty"` + Execution string `json:"execution,omitempty"` + ID string `json:"id,omitempty"` + Input string `json:"input,omitempty"` + InternalChatMessageMetadataPassthrough *InternalChatMessageMetadataPassthrough `json:"internal_chat_message_metadata_passthrough,omitempty"` + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Output FunctionCallOutputBody `json:"output,omitempty"` + Phase MessagePhase `json:"phase,omitempty"` + Reasoning *ConfigurationReasoning `json:"reasoning,omitempty"` + Recipient string `json:"recipient,omitempty"` + Result string `json:"result,omitempty"` + RevisedPrompt string `json:"revised_prompt,omitempty"` + Role string `json:"role,omitempty"` + Status json.RawMessage `json:"status,omitempty"` + Summary []ReasoningItemReasoningSummary `json:"summary,omitempty"` + Tools []json.RawMessage `json:"tools,omitempty"` + Type string `json:"type"` +} + +type SortDirection string + +type ThreadResumeInitialTurnsPageParams struct { + ItemsView TurnItemsView `json:"itemsView,omitempty"` + Limit int64 `json:"limit,omitempty"` + SortDirection SortDirection `json:"sortDirection,omitempty"` +} + +type ThreadResumeParams struct { + ApprovalPolicy AskForApproval `json:"approvalPolicy,omitempty"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer,omitempty"` + BaseInstructions string `json:"baseInstructions,omitempty"` + Config map[string]any `json:"config,omitempty"` + Cwd string `json:"cwd,omitempty"` + DeveloperInstructions string `json:"developerInstructions,omitempty"` + ExcludeTurns bool `json:"excludeTurns,omitempty"` + History []ResponseItem `json:"history,omitempty"` + InitialTurnsPage *ThreadResumeInitialTurnsPageParams `json:"initialTurnsPage,omitempty"` + Model string `json:"model,omitempty"` + ModelProvider string `json:"modelProvider,omitempty"` + Path string `json:"path,omitempty"` + Permissions string `json:"permissions,omitempty"` + Personality Personality `json:"personality,omitempty"` + RuntimeWorkspaceRoots []AbsolutePathBuf `json:"runtimeWorkspaceRoots,omitempty"` + Sandbox SandboxMode `json:"sandbox,omitempty"` + ServiceTier string `json:"serviceTier,omitempty"` + ThreadID string `json:"threadId"` +} + +type ModeKind string + +type Settings struct { + DeveloperInstructions string `json:"developer_instructions,omitempty"` + Model string `json:"model"` + ReasoningEffort ReasoningEffort `json:"reasoning_effort,omitempty"` +} + +type CollaborationMode struct { + Mode ModeKind `json:"mode"` + Settings Settings `json:"settings"` +} + +type TurnsPage struct { + BackwardsCursor string `json:"backwardsCursor,omitempty"` + Data []Turn `json:"data"` + NextCursor string `json:"nextCursor,omitempty"` +} + +type ThreadResumeResponse struct { + ActivePermissionProfile *ActivePermissionProfile `json:"activePermissionProfile,omitempty"` + ApprovalPolicy AskForApproval `json:"approvalPolicy"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer"` + CollaborationMode *CollaborationMode `json:"collaborationMode,omitempty"` + Cwd AbsolutePathBuf `json:"cwd"` + DisabledPluginIDs []string `json:"disabledPluginIds,omitempty"` + InitialTurnsPage *TurnsPage `json:"initialTurnsPage,omitempty"` + InstructionSources []LegacyAppPathString `json:"instructionSources,omitempty"` + ItemsBackwardsCursor string `json:"itemsBackwardsCursor,omitempty"` + Model string `json:"model"` + ModelProvider string `json:"modelProvider"` + MultiAgentMode MultiAgentMode `json:"multiAgentMode,omitempty"` + ReasoningEffort ReasoningEffort `json:"reasoningEffort,omitempty"` + RuntimeWorkspaceRoots []AbsolutePathBuf `json:"runtimeWorkspaceRoots,omitempty"` + Sandbox SandboxPolicy `json:"sandbox"` + ServiceTier string `json:"serviceTier,omitempty"` + Thread Thread `json:"thread"` + TurnsBackwardsCursor string `json:"turnsBackwardsCursor,omitempty"` +} + +type ThreadCompactStartParams struct { + ThreadID string `json:"threadId"` +} + +type ThreadCompactStartResponse = map[string]any + +type ThreadReadParams struct { + IncludeTurns bool `json:"includeTurns,omitempty"` + ThreadID string `json:"threadId"` +} + +type ThreadReadResponse struct { + Thread Thread `json:"thread"` +} + +type AdditionalContextKind string + +type AdditionalContextEntry struct { + Kind AdditionalContextKind `json:"kind"` + Value string `json:"value"` +} + +type CyberAccessProgram string + +type ReasoningSummary string + +type TurnToolOutput struct { + Name string `json:"name"` + Namespace string `json:"namespace,omitempty"` + Output FunctionCallOutputBody `json:"output"` +} + +type TurnStartParams struct { + AdditionalContext map[string]AdditionalContextEntry `json:"additionalContext,omitempty"` + ApprovalPolicy AskForApproval `json:"approvalPolicy,omitempty"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer,omitempty"` + ClientUserMessageID string `json:"clientUserMessageId,omitempty"` + CollaborationMode *CollaborationMode `json:"collaborationMode,omitempty"` + Cwd string `json:"cwd,omitempty"` + CyberAccessProgram CyberAccessProgram `json:"cyberAccessProgram,omitempty"` + DisabledPluginIDs []string `json:"disabledPluginIds,omitempty"` + Effort ReasoningEffort `json:"effort,omitempty"` + Environments []TurnEnvironmentParams `json:"environments,omitempty"` + Input []UserInput `json:"input"` + Model string `json:"model,omitempty"` + MultiAgentMode MultiAgentMode `json:"multiAgentMode,omitempty"` + OutputSchema json.RawMessage `json:"outputSchema,omitempty"` + Permissions string `json:"permissions,omitempty"` + Personality Personality `json:"personality,omitempty"` + ResponsesapiClientMetadata map[string]string `json:"responsesapiClientMetadata,omitempty"` + RuntimeWorkspaceRoots []AbsolutePathBuf `json:"runtimeWorkspaceRoots,omitempty"` + SandboxPolicy *SandboxPolicy `json:"sandboxPolicy,omitempty"` + ServiceTier string `json:"serviceTier,omitempty"` + ServiceTierForTurn string `json:"serviceTierForTurn,omitempty"` + Summary ReasoningSummary `json:"summary,omitempty"` + ThreadID string `json:"threadId"` + ToolOutput *TurnToolOutput `json:"toolOutput,omitempty"` + TurnTrigger string `json:"turnTrigger,omitempty"` +} + +type TurnStartResponse struct { + Turn Turn `json:"turn"` +} + +type TurnInterruptParams struct { + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type TurnInterruptResponse = map[string]any + +type ErrorNotification struct { + Error TurnError `json:"error"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` + WillRetry bool `json:"willRetry"` +} + +type ThreadStartedNotification struct { + Thread Thread `json:"thread"` +} + +type ThreadStatusChangedNotification struct { + Status ThreadStatus `json:"status"` + ThreadID string `json:"threadId"` +} + +type ThreadArchivedNotification struct { + ThreadID string `json:"threadId"` +} + +type ThreadDeletedNotification struct { + ThreadID string `json:"threadId"` +} + +type ThreadUnarchivedNotification struct { + ThreadID string `json:"threadId"` +} + +type ThreadClosedNotification struct { + ThreadID string `json:"threadId"` +} + +type ThreadRevertedNotification struct { + ThreadID string `json:"threadId"` +} + +type SkillsChangedNotification = map[string]any + +type ThreadNameUpdatedNotification struct { + ThreadID string `json:"threadId"` + ThreadName string `json:"threadName,omitempty"` +} + +type ThreadAttachmentOperation string + +type ThreadAttachmentUpdatedNotification struct { + AttachmentID string `json:"attachmentId"` + AttachmentType string `json:"attachmentType"` + IdentityKey string `json:"identityKey"` + Operation ThreadAttachmentOperation `json:"operation"` + ThreadID string `json:"threadId"` +} + +type ThreadGoalStatus string + +type ThreadGoal struct { + CreatedAt int64 `json:"createdAt"` + Objective string `json:"objective"` + Status ThreadGoalStatus `json:"status"` + ThreadID string `json:"threadId"` + TimeUsedSeconds int64 `json:"timeUsedSeconds"` + TokenBudget int64 `json:"tokenBudget,omitempty"` + TokensUsed int64 `json:"tokensUsed"` + UpdatedAt int64 `json:"updatedAt"` +} + +type ThreadGoalUpdatedNotification struct { + Goal ThreadGoal `json:"goal"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId,omitempty"` +} + +type ThreadGoalClearedNotification struct { + ThreadID string `json:"threadId"` +} + +type ThreadQueueChangedNotification struct { + ThreadID string `json:"threadId"` +} + +type ProjectChangeType string + +type ProjectChangedNotification struct { + ChangeType ProjectChangeType `json:"changeType"` + ProjectID string `json:"projectId"` +} + +type ThreadProjectUpdatedNotification struct { + ProjectID string `json:"projectId,omitempty"` + ThreadID string `json:"threadId"` +} + +type EnvironmentConnectionNotification struct { + EnvironmentID string `json:"environmentId"` + ThreadID string `json:"threadId"` +} + +type ThreadSettings struct { + ActivePermissionProfile *ActivePermissionProfile `json:"activePermissionProfile,omitempty"` + ApprovalPolicy AskForApproval `json:"approvalPolicy"` + ApprovalsReviewer ApprovalsReviewer `json:"approvalsReviewer"` + CollaborationMode CollaborationMode `json:"collaborationMode"` + Cwd AbsolutePathBuf `json:"cwd"` + DisabledPluginIDs []string `json:"disabledPluginIds,omitempty"` + Effort ReasoningEffort `json:"effort,omitempty"` + Model string `json:"model"` + ModelProvider string `json:"modelProvider"` + MultiAgentMode MultiAgentMode `json:"multiAgentMode,omitempty"` + Personality Personality `json:"personality,omitempty"` + SandboxPolicy SandboxPolicy `json:"sandboxPolicy"` + ServiceTier string `json:"serviceTier,omitempty"` + Summary ReasoningSummary `json:"summary,omitempty"` +} + +type ThreadSettingsUpdatedNotification struct { + ThreadID string `json:"threadId"` + ThreadSettings ThreadSettings `json:"threadSettings"` +} + +type TokenUsageBreakdown struct { + CacheWriteInputTokens int64 `json:"cacheWriteInputTokens,omitempty"` + CachedInputTokens int64 `json:"cachedInputTokens"` + InputTokens int64 `json:"inputTokens"` + OutputTokens int64 `json:"outputTokens"` + ReasoningOutputTokens int64 `json:"reasoningOutputTokens"` + TotalTokens int64 `json:"totalTokens"` +} + +type ThreadTokenUsage struct { + Last TokenUsageBreakdown `json:"last"` + ModelContextWindow int64 `json:"modelContextWindow,omitempty"` + Total TokenUsageBreakdown `json:"total"` +} + +type ThreadTokenUsageUpdatedNotification struct { + ThreadID string `json:"threadId"` + TokenUsage ThreadTokenUsage `json:"tokenUsage"` + TurnID string `json:"turnId"` +} + +type TurnStartedNotification struct { + ThreadID string `json:"threadId"` + Turn Turn `json:"turn"` +} + +type HookOutputEntryKind string + +type HookOutputEntry struct { + Kind HookOutputEntryKind `json:"kind"` + Text string `json:"text"` +} + +type HookEventName string + +type HookExecutionMode string + +type HookHandlerType string + +type HookScope string + +type HookSource string + +type HookRunStatus string + +type HookRunSummary struct { + CompletedAt int64 `json:"completedAt,omitempty"` + DisplayOrder int64 `json:"displayOrder"` + DurationMs int64 `json:"durationMs,omitempty"` + Entries []HookOutputEntry `json:"entries"` + EventName HookEventName `json:"eventName"` + ExecutionMode HookExecutionMode `json:"executionMode"` + HandlerType HookHandlerType `json:"handlerType"` + ID string `json:"id"` + Scope HookScope `json:"scope"` + Source HookSource `json:"source,omitempty"` + SourcePath AbsolutePathBuf `json:"sourcePath"` + StartedAt int64 `json:"startedAt"` + Status HookRunStatus `json:"status"` + StatusMessage string `json:"statusMessage,omitempty"` +} + +type HookStartedNotification struct { + Run HookRunSummary `json:"run"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId,omitempty"` +} + +type TurnCompletedNotification struct { + ThreadID string `json:"threadId"` + Turn Turn `json:"turn"` +} + +type HookCompletedNotification struct { + Run HookRunSummary `json:"run"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId,omitempty"` +} + +type TurnDiffUpdatedNotification struct { + Diff string `json:"diff"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type TurnPlanStepStatus string + +type TurnPlanStep struct { + Status TurnPlanStepStatus `json:"status"` + Step string `json:"step"` +} + +type TurnPlanUpdatedNotification struct { + Explanation string `json:"explanation,omitempty"` + Plan []TurnPlanStep `json:"plan"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ItemStartedNotification struct { + Item ThreadItem `json:"item"` + StartedAtMs int64 `json:"startedAtMs"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type FileSystemAccessMode string + +type FileSystemSpecialPath struct { + Kind string `json:"kind"` + Path string `json:"path,omitempty"` + Subpath LegacyAppPathString `json:"subpath,omitempty"` +} + +type FileSystemPath struct { + Path LegacyAppPathString `json:"path,omitempty"` + Pattern string `json:"pattern,omitempty"` + Type string `json:"type"` + Value *FileSystemSpecialPath `json:"value,omitempty"` +} + +type FileSystemSandboxEntry struct { + Access FileSystemAccessMode `json:"access"` + Path FileSystemPath `json:"path"` +} + +type AdditionalFileSystemPermissions struct { + Entries []FileSystemSandboxEntry `json:"entries,omitempty"` + GlobScanMaxDepth int64 `json:"globScanMaxDepth,omitempty"` + Read []LegacyAppPathString `json:"read,omitempty"` + Write []LegacyAppPathString `json:"write,omitempty"` +} + +type AdditionalNetworkPermissions struct { + Enabled bool `json:"enabled,omitempty"` +} + +type RequestPermissionProfile struct { + FileSystem *AdditionalFileSystemPermissions `json:"fileSystem,omitempty"` + Network *AdditionalNetworkPermissions `json:"network,omitempty"` +} + +type NetworkApprovalProtocol string + +type GuardianCommandSource string + +type GuardianApprovalReviewAction struct { + ApprovalID string `json:"approvalId,omitempty"` + Argv []string `json:"argv,omitempty"` + Command string `json:"command,omitempty"` + ConnectorID string `json:"connectorId,omitempty"` + ConnectorName string `json:"connectorName,omitempty"` + Cwd json.RawMessage `json:"cwd,omitempty"` + Files []LegacyAppPathString `json:"files,omitempty"` + Host string `json:"host,omitempty"` + Permissions *RequestPermissionProfile `json:"permissions,omitempty"` + Port int64 `json:"port,omitempty"` + ProcessID string `json:"processId,omitempty"` + Program string `json:"program,omitempty"` + Protocol NetworkApprovalProtocol `json:"protocol,omitempty"` + Reason string `json:"reason,omitempty"` + Server string `json:"server,omitempty"` + Source GuardianCommandSource `json:"source,omitempty"` + Stdin string `json:"stdin,omitempty"` + Target string `json:"target,omitempty"` + ToolName string `json:"toolName,omitempty"` + ToolTitle string `json:"toolTitle,omitempty"` + Type string `json:"type"` +} + +type GuardianRiskLevel string + +type GuardianApprovalReviewStatus string + +type GuardianUserAuthorization string + +type GuardianApprovalReview struct { + Rationale string `json:"rationale,omitempty"` + RiskLevel GuardianRiskLevel `json:"riskLevel,omitempty"` + Status GuardianApprovalReviewStatus `json:"status"` + UserAuthorization GuardianUserAuthorization `json:"userAuthorization,omitempty"` +} + +type ItemGuardianApprovalReviewStartedNotification struct { + Action GuardianApprovalReviewAction `json:"action"` + Review GuardianApprovalReview `json:"review"` + ReviewID string `json:"reviewId"` + StartedAtMs int64 `json:"startedAtMs"` + TargetItemID string `json:"targetItemId,omitempty"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type AutoReviewDecisionSource string + +type ItemGuardianApprovalReviewCompletedNotification struct { + Action GuardianApprovalReviewAction `json:"action"` + CompletedAtMs int64 `json:"completedAtMs"` + DecisionSource AutoReviewDecisionSource `json:"decisionSource"` + Review GuardianApprovalReview `json:"review"` + ReviewID string `json:"reviewId"` + StartedAtMs int64 `json:"startedAtMs"` + TargetItemID string `json:"targetItemId,omitempty"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type StrictReviewRequiredNotification struct { + StartedAtMs int64 `json:"startedAtMs"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ItemCompletedNotification struct { + CompletedAtMs int64 `json:"completedAtMs"` + Item ThreadItem `json:"item"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type AgentMessageDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type PlanDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type CommandExecOutputStream string + +type CommandExecOutputDeltaNotification struct { + CapReached bool `json:"capReached"` + DeltaBase64 string `json:"deltaBase64"` + ProcessID string `json:"processId"` + Stream CommandExecOutputStream `json:"stream"` +} + +type ProcessOutputStream string + +type ProcessOutputDeltaNotification struct { + CapReached bool `json:"capReached"` + DeltaBase64 string `json:"deltaBase64"` + ProcessHandle string `json:"processHandle"` + Stream ProcessOutputStream `json:"stream"` +} + +type ProcessExitedNotification struct { + ExitCode int64 `json:"exitCode"` + ProcessHandle string `json:"processHandle"` + Stderr string `json:"stderr"` + StderrCapReached bool `json:"stderrCapReached"` + Stdout string `json:"stdout"` + StdoutCapReached bool `json:"stdoutCapReached"` +} + +type CommandExecutionOutputDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type TerminalInteractionNotification struct { + ItemID string `json:"itemId"` + ProcessID string `json:"processId"` + Stdin string `json:"stdin"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type FileChangeOutputDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type FileChangePatchUpdatedNotification struct { + Changes []FileUpdateChange `json:"changes"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type RequestId = json.RawMessage + +type ServerRequestResolvedNotification struct { + RequestID RequestId `json:"requestId"` + ThreadID string `json:"threadId"` +} + +type McpToolCallProgressNotification struct { + ItemID string `json:"itemId"` + Message string `json:"message"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type McpServerOauthLoginCompletedNotification struct { + Error string `json:"error,omitempty"` + Name string `json:"name"` + Success bool `json:"success"` + ThreadID string `json:"threadId,omitempty"` +} + +type McpServerStartupFailureReason string + +type McpServerStartupState string + +type McpServerStatusUpdatedNotification struct { + Error string `json:"error,omitempty"` + FailureReason McpServerStartupFailureReason `json:"failureReason,omitempty"` + Name string `json:"name"` + Status McpServerStartupState `json:"status"` + ThreadID string `json:"threadId,omitempty"` +} + +type McpServerEventNotification struct { + Method string `json:"method"` + Params json.RawMessage `json:"params"` +} + +type McpServerEventStreamNotification struct { + Notification McpServerEventNotification `json:"notification"` + SubscriptionID string `json:"subscriptionId"` +} + +type AuthMode string + +type PlanType string + +type AccountUpdatedNotification struct { + AuthMode AuthMode `json:"authMode,omitempty"` + PlanType PlanType `json:"planType,omitempty"` +} + +type GatewayOAuthStatus string + +type GatewayOAuthChangedNotification struct { + AuthURL string `json:"authUrl,omitempty"` + Error string `json:"error,omitempty"` + ProviderID string `json:"providerId"` + Status GatewayOAuthStatus `json:"status"` +} + +type CreditsSnapshot struct { + Balance string `json:"balance,omitempty"` + HasCredits bool `json:"hasCredits"` + Unlimited bool `json:"unlimited"` +} + +type SpendControlLimitSnapshot struct { + Limit string `json:"limit"` + RemainingPercent int64 `json:"remainingPercent"` + ResetsAt int64 `json:"resetsAt"` + Used string `json:"used"` +} + +type RateLimitWindow struct { + ResetsAt int64 `json:"resetsAt,omitempty"` + UsedPercent int64 `json:"usedPercent"` + WindowDurationMins int64 `json:"windowDurationMins,omitempty"` +} + +type RateLimitReachedType string + +type RateLimitSnapshot struct { + Credits *CreditsSnapshot `json:"credits,omitempty"` + IndividualLimit *SpendControlLimitSnapshot `json:"individualLimit,omitempty"` + LimitID string `json:"limitId,omitempty"` + LimitName string `json:"limitName,omitempty"` + NormalModelSlug string `json:"normalModelSlug,omitempty"` + PlanType PlanType `json:"planType,omitempty"` + Primary *RateLimitWindow `json:"primary,omitempty"` + RateLimitReachedType RateLimitReachedType `json:"rateLimitReachedType,omitempty"` + Secondary *RateLimitWindow `json:"secondary,omitempty"` + SpendControlReached bool `json:"spendControlReached,omitempty"` +} + +type AccountRateLimitsUpdatedNotification struct { + RateLimits RateLimitSnapshot `json:"rateLimits"` +} + +type AppReview struct { + Status string `json:"status"` +} + +type AppScreenshot struct { + FileID string `json:"fileId,omitempty"` + URL string `json:"url,omitempty"` + UserPrompt string `json:"userPrompt"` +} + +type AppMetadata struct { + Categories []string `json:"categories,omitempty"` + Developer string `json:"developer,omitempty"` + FirstPartyRequiresInstall bool `json:"firstPartyRequiresInstall,omitempty"` + Review *AppReview `json:"review,omitempty"` + Screenshots []AppScreenshot `json:"screenshots,omitempty"` + SeoDescription string `json:"seoDescription,omitempty"` + ShowInComposerWhenUnlinked bool `json:"showInComposerWhenUnlinked,omitempty"` + SubCategories []string `json:"subCategories,omitempty"` + Version string `json:"version,omitempty"` + VersionID string `json:"versionId,omitempty"` + VersionNotes string `json:"versionNotes,omitempty"` +} + +type AppBranding struct { + Category string `json:"category,omitempty"` + Developer string `json:"developer,omitempty"` + IsDiscoverableApp bool `json:"isDiscoverableApp"` + PrivacyPolicy string `json:"privacyPolicy,omitempty"` + TermsOfService string `json:"termsOfService,omitempty"` + Website string `json:"website,omitempty"` +} + +type AppInfo struct { + AppMetadata *AppMetadata `json:"appMetadata,omitempty"` + Branding *AppBranding `json:"branding,omitempty"` + Description string `json:"description,omitempty"` + DistributionChannel string `json:"distributionChannel,omitempty"` + IconAssets map[string]string `json:"iconAssets,omitempty"` + IconDarkAssets map[string]string `json:"iconDarkAssets,omitempty"` + ID string `json:"id"` + InstallURL string `json:"installUrl,omitempty"` + IsAccessible bool `json:"isAccessible,omitempty"` + IsEnabled bool `json:"isEnabled,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + LogoURL string `json:"logoUrl,omitempty"` + LogoURLDark string `json:"logoUrlDark,omitempty"` + Name string `json:"name"` + PluginDisplayNames []string `json:"pluginDisplayNames,omitempty"` +} + +type AppListUpdatedNotification struct { + Data []AppInfo `json:"data"` +} + +type RemoteControlConnectionStatus string + +type RemoteControlStatusChangedNotification struct { + EnvironmentID string `json:"environmentId,omitempty"` + InstallationID string `json:"installationId"` + ServerName string `json:"serverName"` + Status RemoteControlConnectionStatus `json:"status"` +} + +type ExternalAgentConfigMigrationItemType string + +type ExternalAgentConfigImportItemTypeFailure struct { + Cwd string `json:"cwd,omitempty"` + ErrorType string `json:"errorType,omitempty"` + FailureStage string `json:"failureStage"` + ItemType ExternalAgentConfigMigrationItemType `json:"itemType"` + Message string `json:"message"` + Source string `json:"source,omitempty"` + SubErrorType string `json:"subErrorType,omitempty"` +} + +type ExternalAgentConfigImportItemTypeSuccess struct { + Cwd string `json:"cwd,omitempty"` + ItemType ExternalAgentConfigMigrationItemType `json:"itemType"` + Source string `json:"source,omitempty"` + Target string `json:"target,omitempty"` + Title string `json:"title,omitempty"` +} + +type ExternalAgentConfigImportTypeResult struct { + Failures []ExternalAgentConfigImportItemTypeFailure `json:"failures"` + ItemType ExternalAgentConfigMigrationItemType `json:"itemType"` + Successes []ExternalAgentConfigImportItemTypeSuccess `json:"successes"` +} + +type ExternalAgentConfigImportProgressNotification struct { + ImportID string `json:"importId"` + ItemTypeResults []ExternalAgentConfigImportTypeResult `json:"itemTypeResults"` +} + +type ExternalAgentConfigImportCompletedNotification struct { + ImportID string `json:"importId"` + ItemTypeResults []ExternalAgentConfigImportTypeResult `json:"itemTypeResults"` +} + +type FsChangedNotification struct { + ChangedPaths []AbsolutePathBuf `json:"changedPaths"` + WatchID string `json:"watchId"` +} + +type ReasoningSummaryTextDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + SummaryIndex int64 `json:"summaryIndex"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ReasoningSummaryPartAddedNotification struct { + ItemID string `json:"itemId"` + SummaryIndex int64 `json:"summaryIndex"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ReasoningTextDeltaNotification struct { + ContentIndex int64 `json:"contentIndex"` + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ContextCompactedNotification struct { + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ModelRerouteReason string + +type ModelReroutedNotification struct { + FromModel string `json:"fromModel"` + Reason ModelRerouteReason `json:"reason"` + ThreadID string `json:"threadId"` + ToModel string `json:"toModel"` + TurnID string `json:"turnId"` +} + +type ModelVerification string + +type ModelVerificationNotification struct { + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` + Verifications []ModelVerification `json:"verifications"` +} + +type AuthRecoveryNotification struct { + Message string `json:"message"` + Provider string `json:"provider"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type TurnModerationMetadataNotification struct { + Metadata json.RawMessage `json:"metadata"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ModelSafetyBufferingUpdatedNotification struct { + FasterModel string `json:"fasterModel,omitempty"` + Model string `json:"model"` + Reasons []string `json:"reasons"` + ShowBufferingUi bool `json:"showBufferingUi"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` + UseCases []string `json:"useCases"` +} + +type WarningNotification struct { + Message string `json:"message"` + ThreadID string `json:"threadId,omitempty"` +} + +type GuardianWarningNotification struct { + Message string `json:"message"` + ThreadID string `json:"threadId"` +} + +type DeprecationNoticeNotification struct { + Details string `json:"details,omitempty"` + Summary string `json:"summary"` +} + +type TextPosition struct { + Column int64 `json:"column"` + Line int64 `json:"line"` +} + +type TextRange struct { + End TextPosition `json:"end"` + Start TextPosition `json:"start"` +} + +type ConfigWarningNotification struct { + Details string `json:"details,omitempty"` + Path string `json:"path,omitempty"` + Range *TextRange `json:"range,omitempty"` + Summary string `json:"summary"` +} + +type FuzzyFileSearchMatchType string + +type FuzzyFileSearchResult struct { + FileName string `json:"file_name"` + Indices []int64 `json:"indices,omitempty"` + MatchType FuzzyFileSearchMatchType `json:"match_type"` + Path string `json:"path"` + Root string `json:"root"` + Score int64 `json:"score"` +} + +type FuzzyFileSearchSessionUpdatedNotification struct { + Files []FuzzyFileSearchResult `json:"files"` + Query string `json:"query"` + SessionID string `json:"sessionId"` +} + +type FuzzyFileSearchSessionCompletedNotification struct { + SessionID string `json:"sessionId"` +} + +type RealtimeConversationVersion string + +type ThreadRealtimeStartedNotification struct { + RealtimeSessionID string `json:"realtimeSessionId,omitempty"` + ThreadID string `json:"threadId"` + Version RealtimeConversationVersion `json:"version"` +} + +type ThreadRealtimeItemAddedNotification struct { + Item json.RawMessage `json:"item"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeSessionOutcome string + +type ThreadRealtimeBemItemPresentation struct { + Index int64 `json:"index,omitempty"` + Type string `json:"type"` +} + +type ThreadRealtimeTranscriptRole string + +type ThreadRealtimeItem struct { + ID string `json:"id"` + ItemID string `json:"item_id,omitempty"` + Outcome ThreadRealtimeSessionOutcome `json:"outcome,omitempty"` + Presentation *ThreadRealtimeBemItemPresentation `json:"presentation,omitempty"` + RealtimeSessionID string `json:"realtimeSessionId"` + Role ThreadRealtimeTranscriptRole `json:"role,omitempty"` + Text string `json:"text,omitempty"` + TurnID string `json:"turn_id,omitempty"` + Type string `json:"type"` +} + +type ThreadRealtimeItemStartedNotification struct { + Item ThreadRealtimeItem `json:"item"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeItemTranscriptDeltaNotification struct { + Delta string `json:"delta"` + ItemID string `json:"itemId"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeItemCompletedNotification struct { + Item ThreadRealtimeItem `json:"item"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeTranscriptDeltaNotification struct { + Delta string `json:"delta"` + Role string `json:"role"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeTranscriptDoneNotification struct { + Role string `json:"role"` + Text string `json:"text"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeAudioChunk struct { + Data string `json:"data"` + ItemID string `json:"itemId,omitempty"` + NumChannels int64 `json:"numChannels"` + SampleRate int64 `json:"sampleRate"` + SamplesPerChannel int64 `json:"samplesPerChannel,omitempty"` +} + +type ThreadRealtimeOutputAudioDeltaNotification struct { + Audio ThreadRealtimeAudioChunk `json:"audio"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeSdpNotification struct { + Sdp string `json:"sdp"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeErrorNotification struct { + Message string `json:"message"` + ThreadID string `json:"threadId"` +} + +type ThreadRealtimeClosedNotification struct { + Reason string `json:"reason,omitempty"` + ThreadID string `json:"threadId"` +} + +type WindowsWorldWritableWarningNotification struct { + ExtraCount int64 `json:"extraCount"` + FailedScan bool `json:"failedScan"` + SamplePaths []string `json:"samplePaths"` +} + +type WindowsSandboxSetupMode string + +type WindowsSandboxSetupCompletedNotification struct { + Error string `json:"error,omitempty"` + Mode WindowsSandboxSetupMode `json:"mode"` + Success bool `json:"success"` +} + +type DesktopOnboardingEntrypoint string + +type AccountLoginCompletedNotification struct { + Error string `json:"error,omitempty"` + LoginID string `json:"loginId,omitempty"` + OnboardingEntrypoint DesktopOnboardingEntrypoint `json:"onboardingEntrypoint,omitempty"` + Success bool `json:"success"` +} + +type AdditionalPermissionProfile struct { + FileSystem *AdditionalFileSystemPermissions `json:"fileSystem,omitempty"` + Network *AdditionalNetworkPermissions `json:"network,omitempty"` +} + +type CommandExecutionApprovalDecision = json.RawMessage + +type CommandExecutionApprovalKind string + +type NetworkApprovalContext struct { + Host string `json:"host"` + Protocol NetworkApprovalProtocol `json:"protocol"` +} + +type NetworkPolicyRuleAction string + +type NetworkPolicyAmendment struct { + Action NetworkPolicyRuleAction `json:"action"` + Host string `json:"host"` +} + +type CommandExecutionRequestApprovalParams struct { + AdditionalPermissions *AdditionalPermissionProfile `json:"additionalPermissions,omitempty"` + ApprovalID string `json:"approvalId,omitempty"` + AvailableDecisions []CommandExecutionApprovalDecision `json:"availableDecisions,omitempty"` + Command string `json:"command,omitempty"` + CommandActions []CommandAction `json:"commandActions,omitempty"` + Cwd LegacyAppPathString `json:"cwd,omitempty"` + EnvironmentID string `json:"environmentId,omitempty"` + ItemID string `json:"itemId"` + Kind CommandExecutionApprovalKind `json:"kind,omitempty"` + NetworkApprovalContext *NetworkApprovalContext `json:"networkApprovalContext,omitempty"` + ProposedExecpolicyAmendment []string `json:"proposedExecpolicyAmendment,omitempty"` + ProposedNetworkPolicyAmendments []NetworkPolicyAmendment `json:"proposedNetworkPolicyAmendments,omitempty"` + Reason string `json:"reason,omitempty"` + StartedAtMs int64 `json:"startedAtMs"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type CommandExecutionRequestApprovalResponse struct { + Decision CommandExecutionApprovalDecision `json:"decision"` +} + +type FileChangeRequestApprovalParams struct { + GrantRoot string `json:"grantRoot,omitempty"` + ItemID string `json:"itemId"` + Reason string `json:"reason,omitempty"` + StartedAtMs int64 `json:"startedAtMs"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type FileChangeApprovalDecision string + +type FileChangeRequestApprovalResponse struct { + Decision FileChangeApprovalDecision `json:"decision"` +} + +type ToolRequestUserInputOption struct { + Description string `json:"description"` + Label string `json:"label"` +} + +type ToolRequestUserInputQuestion struct { + Header string `json:"header"` + ID string `json:"id"` + IsOther bool `json:"isOther,omitempty"` + IsSecret bool `json:"isSecret,omitempty"` + Options []ToolRequestUserInputOption `json:"options,omitempty"` + Question string `json:"question"` +} + +type ToolRequestUserInputParams struct { + AutoResolutionMs int64 `json:"autoResolutionMs,omitempty"` + IsBlocking bool `json:"isBlocking"` + ItemID string `json:"itemId"` + Questions []ToolRequestUserInputQuestion `json:"questions"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type ToolRequestUserInputAnswer struct { + Answers []string `json:"answers"` +} + +type ToolRequestUserInputResponse struct { + Answers map[string]ToolRequestUserInputAnswer `json:"answers"` +} + +type McpElicitationStringFormat string + +type McpElicitationStringType string + +type McpElicitationUntitledEnumItems struct { + Enum []string `json:"enum"` + Type McpElicitationStringType `json:"type"` +} + +type McpElicitationConstOption struct { + Const string `json:"const"` + Title string `json:"title"` +} + +type McpElicitationTitledEnumItems struct { + AnyOf []McpElicitationConstOption `json:"anyOf"` +} + +type McpElicitationArrayType string + +type McpElicitationNumberType string + +type McpElicitationBooleanType string + +type McpElicitationPrimitiveSchema struct { + Default json.RawMessage `json:"default,omitempty"` + Description string `json:"description,omitempty"` + Enum []string `json:"enum,omitempty"` + EnumNames []string `json:"enumNames,omitempty"` + Format McpElicitationStringFormat `json:"format,omitempty"` + Items json.RawMessage `json:"items,omitempty"` + MaxItems int64 `json:"maxItems,omitempty"` + MaxLength int64 `json:"maxLength,omitempty"` + Maximum float64 `json:"maximum,omitempty"` + MinItems int64 `json:"minItems,omitempty"` + MinLength int64 `json:"minLength,omitempty"` + Minimum float64 `json:"minimum,omitempty"` + OneOf []McpElicitationConstOption `json:"oneOf,omitempty"` + Title string `json:"title,omitempty"` + Type json.RawMessage `json:"type"` +} + +type McpElicitationObjectType string + +type McpElicitationSchema struct { + Schema string `json:"$schema,omitempty"` + Properties map[string]McpElicitationPrimitiveSchema `json:"properties"` + Required []string `json:"required,omitempty"` + Type McpElicitationObjectType `json:"type"` +} + +type McpServerElicitationRequestParams struct { + Meta json.RawMessage `json:"_meta,omitempty"` + Challenge string `json:"challenge,omitempty"` + Description string `json:"description,omitempty"` + ElicitationID string `json:"elicitationId,omitempty"` + Message string `json:"message,omitempty"` + Mode string `json:"mode"` + RequestedSchema json.RawMessage `json:"requestedSchema,omitempty"` + ServerName string `json:"serverName"` + ThreadID string `json:"threadId"` + Title string `json:"title,omitempty"` + TurnID string `json:"turnId,omitempty"` + URL string `json:"url,omitempty"` +} + +type McpServerElicitationAction string + +type McpServerElicitationRequestResponse struct { + Meta json.RawMessage `json:"_meta,omitempty"` + Action McpServerElicitationAction `json:"action"` + Content json.RawMessage `json:"content,omitempty"` +} + +type PermissionsRequestApprovalParams struct { + Cwd LegacyAppPathString `json:"cwd"` + EnvironmentID string `json:"environmentId,omitempty"` + ItemID string `json:"itemId"` + Permissions RequestPermissionProfile `json:"permissions"` + Reason string `json:"reason,omitempty"` + StartedAtMs int64 `json:"startedAtMs"` + ThreadID string `json:"threadId"` + TurnID string `json:"turnId"` +} + +type GrantedPermissionProfile struct { + FileSystem *AdditionalFileSystemPermissions `json:"fileSystem,omitempty"` + Network *AdditionalNetworkPermissions `json:"network,omitempty"` +} + +type PermissionGrantScope string + +type PermissionsRequestApprovalResponse struct { + Permissions GrantedPermissionProfile `json:"permissions"` + Scope PermissionGrantScope `json:"scope,omitempty"` + StrictAutoReview bool `json:"strictAutoReview,omitempty"` +} + +type DynamicToolCallParams struct { + Arguments json.RawMessage `json:"arguments"` + CallID string `json:"callId"` + Namespace string `json:"namespace,omitempty"` + ThreadID string `json:"threadId"` + Tool string `json:"tool"` + TurnID string `json:"turnId"` +} + +type DynamicToolCallResponse struct { + ContentItems []DynamicToolCallOutputContentItem `json:"contentItems"` + Success bool `json:"success"` +} + +type ChatgptAuthTokensRefreshReason string + +type ChatgptAuthTokensRefreshParams struct { + PreviousAccountID string `json:"previousAccountId,omitempty"` + Reason ChatgptAuthTokensRefreshReason `json:"reason"` +} + +type ChatgptAuthTokensRefreshResponse struct { + AccessToken string `json:"accessToken"` + ChatgptAccountID string `json:"chatgptAccountId"` + ChatgptPlanType string `json:"chatgptPlanType,omitempty"` +} + +type AttestationGenerateParams = map[string]any + +type AttestationGenerateResponse struct { + Token string `json:"token"` +} + +type CurrentTimeReadParams struct { + ThreadID string `json:"threadId"` +} + +type CurrentTimeReadResponse struct { + CurrentTimeAt int64 `json:"currentTimeAt"` +} + +type ThreadId string + +type FileChange struct { + Content string `json:"content,omitempty"` + MovePath string `json:"move_path,omitempty"` + Type string `json:"type"` + UnifiedDiff string `json:"unified_diff,omitempty"` +} + +type ApplyPatchApprovalParams struct { + CallID string `json:"callId"` + ConversationID ThreadId `json:"conversationId"` + FileChanges map[string]FileChange `json:"fileChanges"` + GrantRoot string `json:"grantRoot,omitempty"` + Reason string `json:"reason,omitempty"` +} + +type ReviewDecision = json.RawMessage + +type ApplyPatchApprovalResponse struct { + Decision ReviewDecision `json:"decision"` +} + +type ParsedCommand struct { + Cmd string `json:"cmd"` + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` + Query string `json:"query,omitempty"` + Type string `json:"type"` +} + +type ExecCommandApprovalParams struct { + ApprovalID string `json:"approvalId,omitempty"` + CallID string `json:"callId"` + Command []string `json:"command"` + ConversationID ThreadId `json:"conversationId"` + Cwd string `json:"cwd"` + ParsedCmd []ParsedCommand `json:"parsedCmd"` + Reason string `json:"reason,omitempty"` +} + +type ExecCommandApprovalResponse struct { + Decision ReviewDecision `json:"decision"` +} diff --git a/internal/codex/session.go b/internal/codex/session.go new file mode 100644 index 0000000..a36441f --- /dev/null +++ b/internal/codex/session.go @@ -0,0 +1,552 @@ +package codex + +import ( + "bufio" + "bytes" + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "log/slog" + "os" + "os/exec" + "regexp" + "strconv" + "sync" + "sync/atomic" + "time" +) + +type Options struct { + Cwd string + Model string + Resume string + GitName string + GitEmail string + Env []string + Guidance string + Transcript io.Writer + OnBadLine func(line []byte, reason string) +} + +type Event struct { + Method string + Params json.RawMessage + Read time.Time +} + +func (e Event) Decode() (any, error) { + ctor, ok := notificationParams[e.Method] + if !ok { + return nil, fmt.Errorf("unknown notification %q", e.Method) + } + if ctor == nil { + return nil, nil + } + v := ctor() + err := json.Unmarshal(e.Params, v) + if err != nil { + return nil, fmt.Errorf("decode %s: %w", e.Method, err) + } + return v, nil +} + +type Image struct { + MediaType string + Data []byte +} + +type RPCError struct { + Code int64 `json:"code"` + Message string `json:"message"` + Data json.RawMessage `json:"data,omitempty"` +} + +func (e *RPCError) Error() string { + return fmt.Sprintf("codex rpc error %d: %s", e.Code, e.Message) +} + +type message struct { + ID json.RawMessage `json:"id,omitempty"` + Method string `json:"method,omitempty"` + Params json.RawMessage `json:"params,omitempty"` + Result json.RawMessage `json:"result,omitempty"` + Error *RPCError `json:"error,omitempty"` +} + +type rpcResult struct { + result json.RawMessage + err error +} + +type Session struct { + cmd *exec.Cmd + stdin io.WriteCloser + events chan Event + done chan struct{} + + writeMu sync.Mutex + recordMu sync.Mutex + transcript io.Writer + + nextID atomic.Int64 + pendingMu sync.Mutex + pending map[int64]chan rpcResult + + stateMu sync.Mutex + threadID string + turnID string + model string + userAgent string + + onBadLine func(line []byte, reason string) + lastLine atomic.Int64 +} + +func Start(ctx context.Context, opts Options) (*Session, error) { + cmd := exec.Command("codex", "app-server", "-c", "check_for_update_on_startup=false") + cmd.Dir = opts.Cwd + cmd.Stderr = os.Stderr + cmd.Env = buildEnv(opts) + + stdin, err := cmd.StdinPipe() + if err != nil { + return nil, err + } + + stdout, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + + err = cmd.Start() + if err != nil { + return nil, fmt.Errorf("start codex: %w", err) + } + + s := newSession(opts, stdin, stdout) + s.cmd = cmd + + err = s.open(ctx, opts) + if err != nil { + s.Close() + return nil, err + } + return s, nil +} + +func newSession(opts Options, stdin io.WriteCloser, stdout io.Reader) *Session { + s := &Session{ + stdin: stdin, + events: make(chan Event, 256), + done: make(chan struct{}), + transcript: opts.Transcript, + pending: map[int64]chan rpcResult{}, + onBadLine: opts.OnBadLine, + } + s.lastLine.Store(time.Now().UnixNano()) + go s.readLoop(stdout) + return s +} + +func (s *Session) open(ctx context.Context, opts Options) error { + init := InitializeResponse{} + err := s.Call(ctx, MethodInitialize, InitializeParams{ + ClientInfo: ClientInfo{Name: "byre", Title: "byre", Version: "0.0.0"}, + }, &init) + if err != nil { + return fmt.Errorf("initialize: %w", err) + } + + s.stateMu.Lock() + s.userAgent = init.UserAgent + s.stateMu.Unlock() + + err = s.notify("initialized", nil) + if err != nil { + return err + } + + if opts.Resume != "" { + resp := ThreadResumeResponse{} + err = s.Call(ctx, MethodThreadResume, ThreadResumeParams{ + ThreadID: opts.Resume, + Cwd: opts.Cwd, + Model: opts.Model, + ApprovalPolicy: json.RawMessage(`"never"`), + Sandbox: SandboxModeDangerFullAccess, + DeveloperInstructions: opts.Guidance, + }, &resp) + if err != nil { + return fmt.Errorf("resume thread: %w", err) + } + s.setThread(resp.Thread.ID) + return nil + } + + resp := ThreadStartResponse{} + err = s.Call(ctx, MethodThreadStart, ThreadStartParams{ + Cwd: opts.Cwd, + Model: opts.Model, + ApprovalPolicy: json.RawMessage(`"never"`), + Sandbox: SandboxModeDangerFullAccess, + DeveloperInstructions: opts.Guidance, + }, &resp) + if err != nil { + return fmt.Errorf("start thread: %w", err) + } + s.setThread(resp.Thread.ID) + return nil +} + +func (s *Session) setThread(id string) { + s.stateMu.Lock() + s.threadID = id + s.stateMu.Unlock() +} + +func buildEnv(opts Options) []string { + env := append(os.Environ(), + "GIT_AUTHOR_NAME="+opts.GitName, + "GIT_AUTHOR_EMAIL="+opts.GitEmail, + "GIT_COMMITTER_NAME="+opts.GitName, + "GIT_COMMITTER_EMAIL="+opts.GitEmail, + ) + return append(env, opts.Env...) +} + +func (s *Session) Events() <-chan Event { + return s.events +} + +func (s *Session) Done() <-chan struct{} { + return s.done +} + +func (s *Session) Pid() int { + return s.cmd.Process.Pid +} + +func (s *Session) LastLine() time.Time { + return time.Unix(0, s.lastLine.Load()) +} + +func (s *Session) Exited() bool { + select { + case <-s.done: + return true + default: + return false + } +} + +func (s *Session) ID() string { + s.stateMu.Lock() + defer s.stateMu.Unlock() + return s.threadID +} + +func (s *Session) TurnID() string { + s.stateMu.Lock() + defer s.stateMu.Unlock() + return s.turnID +} + +func (s *Session) UserAgent() string { + s.stateMu.Lock() + defer s.stateMu.Unlock() + return s.userAgent +} + +func (s *Session) SetModel(model string) { + s.stateMu.Lock() + s.model = model + s.stateMu.Unlock() +} + +func (s *Session) Send(ctx context.Context, text string, images ...Image) (Turn, error) { + input := []UserInput{} + for _, img := range images { + input = append(input, UserInput{ + Type: "image", + URL: "data:" + img.MediaType + ";base64," + base64.StdEncoding.EncodeToString(img.Data), + }) + } + if text != "" { + input = append(input, UserInput{Type: "text", Text: text}) + } + + s.stateMu.Lock() + params := TurnStartParams{ThreadID: s.threadID, Input: input, Model: s.model} + s.model = "" + s.stateMu.Unlock() + + resp := TurnStartResponse{} + err := s.Call(ctx, MethodTurnStart, params, &resp) + if err != nil { + return Turn{}, err + } + + s.stateMu.Lock() + if s.turnID == "" { + s.turnID = resp.Turn.ID + } + s.stateMu.Unlock() + return resp.Turn, nil +} + +func (s *Session) Interrupt(ctx context.Context) error { + s.stateMu.Lock() + params := TurnInterruptParams{ThreadID: s.threadID, TurnID: s.turnID} + s.stateMu.Unlock() + + if params.TurnID == "" { + return errors.New("no turn in progress") + } + return s.Call(ctx, MethodTurnInterrupt, params, nil) +} + +func (s *Session) Compact(ctx context.Context) error { + return s.Call(ctx, MethodThreadCompactStart, ThreadCompactStartParams{ThreadID: s.ID()}, nil) +} + +func (s *Session) Call(ctx context.Context, method string, params any, result any) error { + id := s.nextID.Add(1) + ch := make(chan rpcResult, 1) + + s.pendingMu.Lock() + s.pending[id] = ch + s.pendingMu.Unlock() + + defer func() { + s.pendingMu.Lock() + delete(s.pending, id) + s.pendingMu.Unlock() + }() + + raw, err := json.Marshal(params) + if err != nil { + return err + } + + err = s.write(message{ID: json.RawMessage(strconv.FormatInt(id, 10)), Method: method, Params: raw}) + if err != nil { + return err + } + + select { + case res := <-ch: + if res.err != nil { + return res.err + } + if result == nil { + return nil + } + return json.Unmarshal(res.result, result) + case <-s.done: + return errors.New("codex exited") + case <-ctx.Done(): + return ctx.Err() + } +} + +func (s *Session) notify(method string, params any) error { + m := message{Method: method} + if params != nil { + raw, err := json.Marshal(params) + if err != nil { + return err + } + m.Params = raw + } + return s.write(m) +} + +func (s *Session) Close() error { + s.writeMu.Lock() + s.stdin.Close() + s.writeMu.Unlock() + + select { + case <-s.done: + case <-time.After(5 * time.Second): + s.cmd.Process.Kill() + <-s.done + } + + return s.cmd.Wait() +} + +func (s *Session) Kill() { + s.cmd.Process.Kill() + <-s.done + s.cmd.Wait() +} + +func (s *Session) write(m message) error { + b, err := json.Marshal(m) + if err != nil { + return err + } + + s.writeMu.Lock() + defer s.writeMu.Unlock() + + s.record("send", b) + + _, err = s.stdin.Write(append(b, '\n')) + return err +} + +var emailField = regexp.MustCompile(`"email":"[^"]*"`) + +func (s *Session) record(dir string, line []byte) { + if s.transcript == nil { + return + } + + line = emailField.ReplaceAll(line, []byte(`"email":"[redacted]"`)) + + b, err := json.Marshal(map[string]any{"dir": dir, "msg": json.RawMessage(line)}) + if err != nil { + slog.Error("record transcript", "err", err) + return + } + + s.recordMu.Lock() + defer s.recordMu.Unlock() + s.transcript.Write(append(b, '\n')) +} + +func (s *Session) readLoop(stdout io.Reader) { + defer close(s.done) + defer close(s.events) + + r := bufio.NewReader(stdout) + for { + line, err := r.ReadBytes('\n') + line = bytes.TrimRight(line, "\r\n") + if len(line) > 0 { + s.lastLine.Store(time.Now().UnixNano()) + } + if len(line) > 0 && line[0] == '{' { + s.handleLine(line) + } else if len(line) > 0 { + s.badLine(line, "not a JSON object") + } + if err != nil { + if err != io.EOF { + slog.Error("read codex stdout", "err", err) + } + return + } + } +} + +func (s *Session) handleLine(line []byte) { + read := time.Now() + m := message{} + err := json.Unmarshal(line, &m) + if err != nil { + s.badLine(line, err.Error()) + return + } + + s.record("recv", line) + + if m.Method == "" { + s.handleResponse(line, m) + return + } + + if len(m.ID) > 0 { + go s.handleServerRequest(m) + return + } + + if _, ok := notificationParams[m.Method]; !ok { + s.badLine(line, fmt.Sprintf("unrecognised method %q", m.Method)) + } + + s.trackTurn(m) + s.events <- Event{Method: m.Method, Params: append(json.RawMessage{}, m.Params...), Read: read} +} + +func (s *Session) trackTurn(m message) { + switch m.Method { + case MethodTurnStarted: + n := TurnStartedNotification{} + if json.Unmarshal(m.Params, &n) == nil { + s.stateMu.Lock() + s.turnID = n.Turn.ID + s.stateMu.Unlock() + } + case MethodTurnCompleted: + n := TurnCompletedNotification{} + if json.Unmarshal(m.Params, &n) == nil { + s.stateMu.Lock() + if s.turnID == n.Turn.ID { + s.turnID = "" + } + s.stateMu.Unlock() + } + } +} + +func (s *Session) handleResponse(line []byte, m message) { + id, err := strconv.ParseInt(string(m.ID), 10, 64) + if err != nil { + s.badLine(line, "response with a non-numeric id") + return + } + + s.pendingMu.Lock() + ch := s.pending[id] + s.pendingMu.Unlock() + + if ch == nil { + slog.Warn("codex response for unknown request", "id", id) + return + } + + if m.Error != nil { + ch <- rpcResult{err: m.Error} + return + } + ch <- rpcResult{result: m.Result} +} + +func (s *Session) handleServerRequest(m message) { + result, err := s.answerServerRequest(m) + if err != nil { + slog.Error("codex server request failed", "method", m.Method, "err", err) + s.write(message{ID: m.ID, Error: &RPCError{Code: -32601, Message: err.Error()}}) + return + } + + raw, err := json.Marshal(result) + if err != nil { + slog.Error("encode codex server response", "method", m.Method, "err", err) + return + } + s.write(message{ID: m.ID, Result: raw}) +} + +func (s *Session) answerServerRequest(m message) (any, error) { + switch m.Method { + case MethodItemCommandExecutionRequestApproval: + return CommandExecutionRequestApprovalResponse{Decision: json.RawMessage(`"accept"`)}, nil + case MethodItemFileChangeRequestApproval: + return FileChangeRequestApprovalResponse{Decision: "accept"}, nil + } + return nil, fmt.Errorf("unsupported server request %s", m.Method) +} + +func (s *Session) badLine(line []byte, reason string) { + slog.Warn("bad codex line", "reason", reason, "line", string(line)) + if s.onBadLine != nil { + s.onBadLine(line, reason) + } +} diff --git a/internal/codex/session_internal_test.go b/internal/codex/session_internal_test.go new file mode 100644 index 0000000..3e6360f --- /dev/null +++ b/internal/codex/session_internal_test.go @@ -0,0 +1,665 @@ +package codex + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "image" + "image/color" + "image/draw" + "image/png" + "io" + "os" + "os/exec" + "path/filepath" + "reflect" + "strings" + "sync" + "testing" + "time" +) + +const ( + testModel = "gpt-5.6-luna" + switchModel = "gpt-5.6-terra" + gitName = "Byre Test" + gitEmail = "test@byre.invalid" +) + +type scenario struct { + name string + run func(h *harness) +} + +var scenarios = []scenario{ + {"CommitIdentity", scenarioCommitIdentity}, + {"TextDeltas", scenarioTextDeltas}, + {"Interrupt", scenarioInterrupt}, + {"ImageInput", scenarioImageInput}, + {"Resume", scenarioResume}, + {"ModelSwitch", scenarioModelSwitch}, + {"Compact", scenarioCompact}, +} + +func TestLive(t *testing.T) { + for _, sc := range scenarios { + t.Run(sc.name, func(t *testing.T) { + t.Parallel() + h := &harness{t: t, name: sc.name, live: true, ctx: testContext(t, 5*time.Minute), repo: scratchRepo(t)} + sc.run(h) + h.closeAll() + for _, path := range h.files { + checkTranscript(t, path) + } + }) + } +} + +func TestContract(t *testing.T) { + for _, sc := range scenarios { + t.Run(sc.name, func(t *testing.T) { + t.Parallel() + h := &harness{t: t, name: sc.name, ctx: testContext(t, 30*time.Second), repo: t.TempDir()} + sc.run(h) + h.closeAll() + for _, path := range h.files { + checkTranscript(t, path) + } + }) + } +} + +func scenarioCommitIdentity(h *harness) { + s := h.start("", Options{}) + h.send(s, `Create a file hello.txt containing exactly the word hi, then git add and git commit it with the message "add hello". Reply done when finished.`) + turn := h.waitTurn(s, nil) + if turn.Status != TurnStatusCompleted { + h.t.Fatalf("turn ended %s", turn.Status) + } + + if !h.live { + return + } + log := git(h.t, h.repo, "log", "-1", "--format=%an <%ae>%n%cn <%ce>%n%B") + want := gitName + " <" + gitEmail + ">\n" + gitName + " <" + gitEmail + ">\nadd hello" + if !strings.HasPrefix(log, want) { + h.t.Fatalf("unexpected commit:\n%s", log) + } + lower := strings.ToLower(log) + if strings.Contains(lower, "co-authored-by") || strings.Contains(lower, "codex") { + h.t.Fatalf("agent attribution in commit:\n%s", log) + } +} + +func scenarioTextDeltas(h *harness) { + s := h.start("", Options{}) + h.send(s, "Without using any tools, count from one to twenty in words, separated by spaces.") + + deltas := map[string][]string{} + h.waitTurn(s, func(ev Event) { + if ev.Method != MethodItemAgentMessageDelta { + return + } + d := decode[*AgentMessageDeltaNotification](h.t, ev) + deltas[d.ItemID] = append(deltas[d.ItemID], d.Delta) + }) + + msgs := h.messages[s] + if len(msgs) == 0 { + h.t.Fatalf("no agent message") + } + last := msgs[len(msgs)-1] + got := deltas[last.ID] + if len(got) < 2 { + h.t.Fatalf("expected several text deltas for %s, got %d", last.ID, len(got)) + } + if strings.Join(got, "") != last.Text { + h.t.Fatalf("deltas %q don't add up to the final text %q", got, last.Text) + } +} + +func scenarioInterrupt(h *harness) { + s := h.start("", Options{}) + h.send(s, "Run the shell command `ping -c 120 127.0.0.1` and wait for it to finish, then say done.") + + interruptedAt := time.Time{} + turn := h.waitTurn(s, func(ev Event) { + if !interruptedAt.IsZero() || ev.Method != MethodItemStarted { + return + } + item := decode[*ItemStartedNotification](h.t, ev).Item + if item.Type != ThreadItemTypeCommandExecution { + return + } + if h.live { + time.Sleep(2 * time.Second) + } + interruptedAt = time.Now() + err := s.Interrupt(h.ctx) + if err != nil { + h.t.Errorf("interrupt: %v", err) + } + }) + + if interruptedAt.IsZero() { + h.t.Fatalf("never saw a command to interrupt") + } + if turn.Status != TurnStatusInterrupted { + h.t.Fatalf("turn ended %s, want interrupted", turn.Status) + } + elapsed := time.Since(interruptedAt) + h.t.Logf("turn ended %s after interrupt", elapsed) + if elapsed > 30*time.Second { + h.t.Fatalf("interrupt took %s to end the turn", elapsed) + } + + h.send(s, "Reply with the single word ok.") + h.waitTurn(s, nil) + if !strings.Contains(strings.ToLower(h.lastText(s)), "ok") { + h.t.Fatalf("session unusable after interrupt; assistant said %q", h.lastText(s)) + } +} + +func scenarioImageInput(h *harness) { + s := h.start("", Options{}) + + img := image.NewRGBA(image.Rect(0, 0, 64, 64)) + draw.Draw(img, img.Bounds(), &image.Uniform{C: color.RGBA{R: 255, A: 255}}, image.Point{}, draw.Src) + buf := bytes.Buffer{} + err := png.Encode(&buf, img) + if err != nil { + h.t.Fatalf("encode png: %v", err) + } + + _, err = s.Send(h.ctx, "Without using any tools, what single colour fills the attached image? Reply with just the colour name.", Image{MediaType: "image/png", Data: buf.Bytes()}) + if err != nil { + h.t.Fatalf("send: %v", err) + } + h.waitTurn(s, nil) + + if !strings.Contains(strings.ToLower(h.lastText(s)), "red") { + h.t.Fatalf("model didn't see the image; assistant said %q", h.lastText(s)) + } +} + +func scenarioResume(h *harness) { + first := h.start("first", Options{}) + h.send(first, "Remember the codeword AZURE-17. Reply with the single word ok.") + h.waitTurn(first, nil) + id := first.ID() + h.close(first) + + if id == "" { + h.t.Fatalf("no thread id from first session") + } + + resumed := h.start("resumed", Options{Resume: id}) + h.send(resumed, "What was the codeword? Reply with just the codeword.") + h.waitTurn(resumed, nil) + + if !strings.Contains(h.lastText(resumed), "AZURE-17") { + h.t.Fatalf("resumed session lost context; assistant said %q", h.lastText(resumed)) + } + if resumed.ID() != id { + h.t.Fatalf("resume changed thread id: want %s, got %s", id, resumed.ID()) + } +} + +func scenarioModelSwitch(h *harness) { + s := h.start("", Options{}) + h.send(s, "Reply with the single word ok.") + h.waitTurn(s, nil) + + before := h.threadModel(s) + if before != testModel { + h.t.Fatalf("thread model %q before the switch, want %s", before, testModel) + } + + s.SetModel(switchModel) + h.send(s, "Reply with the single word ok.") + turn := h.waitTurn(s, nil) + if turn.Status != TurnStatusCompleted { + h.t.Fatalf("turn on %s ended %s: %+v", switchModel, turn.Status, turn.Error) + } + + after := h.threadModel(s) + if after != switchModel { + h.t.Fatalf("thread model %q after the switch, want %s", after, switchModel) + } +} + +func (h *harness) threadModel(s *Session) string { + resp := ThreadReadResponse{} + err := s.Call(h.ctx, MethodThreadRead, ThreadReadParams{ThreadID: s.ID()}, &resp) + if err != nil { + h.t.Fatalf("read thread: %v", err) + } + return resp.Thread.Model +} + +func scenarioCompact(h *harness) { + s := h.start("", Options{}) + h.send(s, "Remember the codeword CORAL-42. Reply with the single word ok.") + h.waitTurn(s, nil) + + err := s.Compact(h.ctx) + if err != nil { + h.t.Fatalf("compact: %v", err) + } + compacted := false + h.waitTurn(s, func(ev Event) { + if ev.Method == MethodThreadCompacted { + compacted = true + } + if ev.Method == MethodItemCompleted && decode[*ItemCompletedNotification](h.t, ev).Item.Type == ThreadItemTypeContextCompaction { + compacted = true + } + }) + if !compacted { + h.t.Fatalf("compaction turn ended without compacting") + } + + h.send(s, "What was the codeword? Reply with just the codeword.") + h.waitTurn(s, nil) + if !strings.Contains(h.lastText(s), "CORAL-42") { + h.t.Fatalf("compacted session lost context; assistant said %q", h.lastText(s)) + } +} + +type harness struct { + t *testing.T + name string + live bool + ctx context.Context + repo string + + files []string + sessions []*Session + closed map[*Session]bool + replays map[*Session]*replay + messages map[*Session][]ThreadItem +} + +func (h *harness) path(dir, suffix string) string { + name := h.name + if suffix != "" { + name += "-" + suffix + } + return filepath.Join("testdata", dir, name+".jsonl") +} + +func (h *harness) start(suffix string, opts Options) *Session { + opts.Cwd = h.repo + opts.Model = testModel + opts.GitName = gitName + opts.GitEmail = gitEmail + opts.OnBadLine = func(line []byte, reason string) { + h.t.Errorf("bad line (%s): %s", reason, line) + } + + if h.messages == nil { + h.messages = map[*Session][]ThreadItem{} + h.closed = map[*Session]bool{} + h.replays = map[*Session]*replay{} + } + + if h.live { + path := h.path("transcripts", suffix) + err := os.MkdirAll(filepath.Dir(path), 0o755) + if err != nil { + h.t.Fatalf("mkdir transcripts: %v", err) + } + f, err := os.Create(path) + if err != nil { + h.t.Fatalf("create transcript: %v", err) + } + h.t.Cleanup(func() { f.Close() }) + opts.Transcript = f + h.files = append(h.files, path) + + s, err := Start(h.ctx, opts) + if err != nil { + h.t.Fatalf("start: %v", err) + } + h.sessions = append(h.sessions, s) + return s + } + + path := h.path("contract", suffix) + h.files = append(h.files, path) + r := newReplay(h.t, path) + s := newSession(opts, r.clientStdin, r.clientStdout) + h.sessions = append(h.sessions, s) + h.replays[s] = r + err := s.open(h.ctx, opts) + if err != nil { + h.t.Fatalf("open: %v", err) + } + return s +} + +func (h *harness) close(s *Session) { + if h.closed[s] { + return + } + h.closed[s] = true + + if h.live { + err := s.Close() + if err != nil { + h.t.Logf("codex exit: %v", err) + } + return + } + + s.stdin.Close() + <-s.done + h.replays[s].wait() +} + +func (h *harness) closeAll() { + for _, s := range h.sessions { + h.close(s) + } +} + +func (h *harness) send(s *Session, text string) { + _, err := s.Send(h.ctx, text) + if err != nil { + h.t.Fatalf("send: %v", err) + } +} + +func (h *harness) waitTurn(s *Session, onEvent func(Event)) Turn { + for { + select { + case ev, ok := <-s.Events(): + if !ok { + h.t.Fatalf("codex exited before the turn completed") + } + if onEvent != nil { + onEvent(ev) + } + if ev.Method == MethodItemCompleted { + item := decode[*ItemCompletedNotification](h.t, ev).Item + if item.Type == ThreadItemTypeAgentMessage { + h.messages[s] = append(h.messages[s], item) + } + } + if ev.Method == MethodTurnCompleted { + turn := decode[*TurnCompletedNotification](h.t, ev).Turn + h.t.Logf("turn %s %s", turn.ID, turn.Status) + return turn + } + case <-h.ctx.Done(): + h.t.Fatalf("timed out waiting for the turn to complete") + } + } +} + +func (h *harness) lastText(s *Session) string { + msgs := h.messages[s] + if len(msgs) == 0 { + return "" + } + return msgs[len(msgs)-1].Text +} + +func decode[T any](t *testing.T, ev Event) T { + v, err := ev.Decode() + if err != nil { + t.Fatalf("decode %s: %v", ev.Method, err) + } + out, ok := v.(T) + if !ok { + t.Fatalf("decode %s: got %T", ev.Method, v) + } + return out +} + +type entry struct { + Dir string `json:"dir"` + Msg json.RawMessage `json:"msg"` +} + +func readTranscript(t *testing.T, path string) []entry { + b, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read transcript: %v", err) + } + out := []entry{} + for _, line := range bytes.Split(bytes.TrimSpace(b), []byte("\n")) { + e := entry{} + err := json.Unmarshal(line, &e) + if err != nil { + t.Fatalf("parse transcript line %s: %v", line, err) + } + out = append(out, e) + } + return out +} + +func strict(raw json.RawMessage, v any) error { + d := json.NewDecoder(bytes.NewReader(raw)) + d.DisallowUnknownFields() + return d.Decode(v) +} + +func checkTranscript(t *testing.T, path string) { + methods := map[string]string{} + for i, e := range readTranscript(t, path) { + m := message{} + err := json.Unmarshal(e.Msg, &m) + if err != nil { + t.Fatalf("%s:%d: %v", path, i+1, err) + } + + if e.Dir == "send" { + if m.Method != "" && len(m.ID) > 0 { + methods[string(m.ID)] = m.Method + } + continue + } + + var ctor func() any + var raw json.RawMessage + label := m.Method + switch { + case m.Method == "": + label = methods[string(m.ID)] + " response" + c, ok := clientResults[methods[string(m.ID)]] + if !ok { + t.Errorf("%s:%d: response to unknown request %s", path, i+1, m.ID) + continue + } + if m.Error != nil { + continue + } + ctor, raw = c, m.Result + case len(m.ID) > 0: + c, ok := serverRequestParams[m.Method] + if !ok { + t.Errorf("%s:%d: unknown server request %s", path, i+1, m.Method) + continue + } + ctor, raw = c, m.Params + default: + c, ok := notificationParams[m.Method] + if !ok { + t.Errorf("%s:%d: unknown notification %s", path, i+1, m.Method) + continue + } + ctor, raw = c, m.Params + } + if ctor == nil { + continue + } + err = strict(raw, ctor()) + if err != nil { + t.Errorf("%s:%d: %s doesn't match the generated types: %v", path, i+1, label, err) + } + } +} + +type replay struct { + t *testing.T + entries []entry + + clientStdin io.WriteCloser + clientStdout io.Reader + serverIn *bufio.Reader + serverOut io.WriteCloser + + ids map[string]json.RawMessage + done chan struct{} + once sync.Once +} + +func newReplay(t *testing.T, path string) *replay { + inR, inW := io.Pipe() + outR, outW := io.Pipe() + r := &replay{ + t: t, + entries: readTranscript(t, path), + clientStdin: inW, + clientStdout: outR, + serverIn: bufio.NewReader(inR), + serverOut: outW, + ids: map[string]json.RawMessage{}, + done: make(chan struct{}), + } + go r.run() + return r +} + +func (r *replay) wait() { + <-r.done +} + +func (r *replay) run() { + defer close(r.done) + defer r.serverOut.Close() + + for i, e := range r.entries { + if e.Dir == "recv" { + _, err := r.serverOut.Write(append(r.rewrite(e.Msg), '\n')) + if err != nil { + r.t.Errorf("replay entry %d: client stopped reading: %v", i+1, err) + return + } + continue + } + + line, err := r.serverIn.ReadBytes('\n') + if err != nil { + r.t.Errorf("replay entry %d: client closed instead of sending %s", i+1, e.Msg) + return + } + r.match(i+1, e.Msg, bytes.TrimSpace(line)) + } + + extra, err := r.serverIn.ReadBytes('\n') + if len(bytes.TrimSpace(extra)) > 0 { + r.t.Errorf("client sent more than the transcript: %s", extra) + } + if err == nil { + r.t.Errorf("client kept stdin open after the transcript ended") + } +} + +func (r *replay) rewrite(raw json.RawMessage) json.RawMessage { + m := message{} + err := json.Unmarshal(raw, &m) + if err != nil || m.Method != "" || len(m.ID) == 0 { + return raw + } + id, ok := r.ids[string(m.ID)] + if !ok { + return raw + } + m.ID = id + b, err := json.Marshal(m) + if err != nil { + r.t.Errorf("rewrite response: %v", err) + return raw + } + return b +} + +func (r *replay) match(n int, want, got json.RawMessage) { + w, g := message{}, message{} + err := json.Unmarshal(want, &w) + if err != nil { + r.t.Errorf("replay entry %d: %v", n, err) + return + } + err = json.Unmarshal(got, &g) + if err != nil { + r.t.Errorf("replay entry %d: client sent %s: %v", n, got, err) + return + } + + if w.Method != "" && len(w.ID) > 0 { + r.ids[string(w.ID)] = g.ID + } else if !bytes.Equal(w.ID, g.ID) { + r.t.Errorf("replay entry %d: id %s, want %s", n, g.ID, w.ID) + } + + if w.Method != g.Method { + r.t.Errorf("replay entry %d: client sent %s, want %s", n, got, want) + return + } + if !sameJSON(w.Params, g.Params) || !sameJSON(w.Result, g.Result) { + r.t.Errorf("replay entry %d: client sent\n%s\nwant\n%s", n, got, want) + } +} + +func sameJSON(a, b json.RawMessage) bool { + if len(a) == 0 || len(b) == 0 { + return len(a) == len(b) + } + var x, y any + if json.Unmarshal(a, &x) != nil || json.Unmarshal(b, &y) != nil { + return false + } + return reflect.DeepEqual(dropCwd(x), dropCwd(y)) +} + +func dropCwd(v any) any { + m, ok := v.(map[string]any) + if !ok { + return v + } + delete(m, "cwd") + return m +} + +func testContext(t *testing.T, d time.Duration) context.Context { + ctx, cancel := context.WithTimeout(context.Background(), d) + t.Cleanup(cancel) + return ctx +} + +func scratchRepo(t *testing.T) string { + dir := t.TempDir() + git(t, dir, "init", "--initial-branch=main") + git(t, dir, "commit", "--allow-empty", "--message", "root") + return dir +} + +func git(t *testing.T, dir string, args ...string) string { + cmd := exec.Command("git", args...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), + "GIT_AUTHOR_NAME="+gitName, + "GIT_AUTHOR_EMAIL="+gitEmail, + "GIT_COMMITTER_NAME="+gitName, + "GIT_COMMITTER_EMAIL="+gitEmail, + ) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("git %v: %v\n%s", args, err, out) + } + return string(out) +} diff --git a/internal/codex/testdata/contract/CommitIdentity.jsonl b/internal/codex/testdata/contract/CommitIdentity.jsonl new file mode 100644 index 0000000..611b3e5 --- /dev/null +++ b/internal/codex/testdata/contract/CommitIdentity.jsonl @@ -0,0 +1,60 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479442}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28db-7702-bc16-eca470bfa3f8","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001"]}],"extra":null,"sessionId":"01a14146-28db-7702-bc16-eca470bfa3f8","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28db-7702-bc16-eca470bfa3f8.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28db-7702-bc16-eca470bfa3f8","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001"]}],"extra":null,"sessionId":"01a14146-28db-7702-bc16-eca470bfa3f8","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28db-7702-bc16-eca470bfa3f8.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479589}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479589}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479589}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479589}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Create a file hello.txt containing exactly the word hi, then git add and git commit it with the message \"add hello\". Reply done when finished.","type":"text"}],"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-2966-7090-b823-03570c64c0ad","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479617}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turn":{"id":"01a14146-2966-7090-b823-03570c64c0ad","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479617}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479950}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479974}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480139}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3fc2-7102-8484-83c055989b99","clientId":null,"content":[{"type":"text","text":"Create a file hello.txt containing exactly the word hi, then git add and git commit it with the message \"add hello\". Reply done when finished.","text_elements":[]}]},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096485315},"emittedAtMs":1792096485315}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3fc2-7102-8484-83c055989b99","clientId":null,"content":[{"type":"text","text":"Create a file hello.txt containing exactly the word hi, then git add and git commit it with the message \"add hello\". Reply done when finished.","text_elements":[]}]},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096485315},"emittedAtMs":1792096485317}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"codex_apps","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487079}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487079}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487079}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"reasoning","id":"rs_0a8961c525780e95016ad138e99e24819abf35d24f0819ba42","summary":[],"content":[]},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096489663},"emittedAtMs":1792096489664}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"reasoning","id":"rs_0a8961c525780e95016ad138e99e24819abf35d24f0819ba42","summary":[],"content":[]},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096489664},"emittedAtMs":1792096489665}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","text":"","phase":"commentary","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096489674},"emittedAtMs":1792096489674}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":"I"},"emittedAtMs":1792096489674}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":"’ll"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" create"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" `"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":"hello"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":".txt"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":"`,"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" stage"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" it"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":","},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" and"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" commit"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" it"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" with"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" the"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" requested"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":" message"},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","delta":"."},"emittedAtMs":1792096489683}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0a8961c525780e95016ad138e9a2ec819aba3a3be150a178c3","text":"I’ll create `hello.txt`, stage it, and commit it with the requested message.","phase":"commentary","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096489686},"emittedAtMs":1792096489687}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"fileChange","id":"exec-c559cae4-a8ba-4ab9-9ec8-a9e5648e3959","changes":[{"path":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001/hello.txt","kind":{"type":"add"},"diff":"hi\n"}],"status":"inProgress"},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096489937},"emittedAtMs":1792096489938}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"fileChange","id":"exec-c559cae4-a8ba-4ab9-9ec8-a9e5648e3959","changes":[{"path":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001/hello.txt","kind":{"type":"add"},"diff":"hi\n"}],"status":"completed"},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096489938},"emittedAtMs":1792096489939}} +{"dir":"recv","msg":{"method":"turn/diff/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","diff":"diff --git a/hello.txt b/hello.txt\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..45b983be36b73c0788dc9cbcb76cbb80fc7bb057\n--- /dev/null\n+++ b/hello.txt\n@@ -0,0 +1 @@\n+hi\n"},"emittedAtMs":1792096489939}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"commandExecution","id":"exec-82bc3b95-1898-44d8-ad3a-77d6ab56e05f","pluginId":null,"scriptPath":null,"command":"/bin/zsh -lc \"git add hello.txt \u0026\u0026 git commit -m 'add hello'\"","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","processId":"45677","source":"unifiedExecStartup","status":"inProgress","commandActions":[{"type":"unknown","command":"git add hello.txt \u0026\u0026 git commit -m 'add hello'"}],"aggregatedOutput":null,"exitCode":null,"durationMs":null},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096489998},"emittedAtMs":1792096489999}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"commandExecution","id":"exec-82bc3b95-1898-44d8-ad3a-77d6ab56e05f","pluginId":null,"scriptPath":null,"command":"/bin/zsh -lc \"git add hello.txt \u0026\u0026 git commit -m 'add hello'\"","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCommitIdentity3341440010/001","processId":"45677","source":"unifiedExecStartup","status":"completed","commandActions":[{"type":"unknown","command":"git add hello.txt \u0026\u0026 git commit -m 'add hello'"}],"aggregatedOutput":"[main c31018c] add hello\n 1 file changed, 1 insertion(+)\n create mode 100644 hello.txt\n","exitCode":0,"durationMs":0},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096489998},"emittedAtMs":1792096490000}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","tokenUsage":{"total":{"totalTokens":13662,"inputTokens":13338,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":324,"reasoningOutputTokens":177},"last":{"totalTokens":13662,"inputTokens":13338,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":324,"reasoningOutputTokens":177},"modelContextWindow":258400}},"emittedAtMs":1792096490002}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096490002}} +{"dir":"recv","msg":{"method":"turn/diff/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","diff":"diff --git a/hello.txt b/hello.txt\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..45b983be36b73c0788dc9cbcb76cbb80fc7bb057\n--- /dev/null\n+++ b/hello.txt\n@@ -0,0 +1 @@\n+hi\n"},"emittedAtMs":1792096490002}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0a8961c525780e95016ad138ecc97c819aa6d8c84f3ec59bc5","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","startedAtMs":1792096492821},"emittedAtMs":1792096492821}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","itemId":"msg_0a8961c525780e95016ad138ecc97c819aa6d8c84f3ec59bc5","delta":"done"},"emittedAtMs":1792096492824}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0a8961c525780e95016ad138ecc97c819aa6d8c84f3ec59bc5","text":"done","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","completedAtMs":1792096492854},"emittedAtMs":1792096492856}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","tokenUsage":{"total":{"totalTokens":27381,"inputTokens":27052,"cachedInputTokens":22016,"cacheWriteInputTokens":0,"outputTokens":329,"reasoningOutputTokens":177},"last":{"totalTokens":13719,"inputTokens":13714,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096492910}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096492910}} +{"dir":"recv","msg":{"method":"turn/diff/updated","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turnId":"01a14146-2966-7090-b823-03570c64c0ad","diff":"diff --git a/hello.txt b/hello.txt\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..45b983be36b73c0788dc9cbcb76cbb80fc7bb057\n--- /dev/null\n+++ b/hello.txt\n@@ -0,0 +1 @@\n+hi\n"},"emittedAtMs":1792096492910}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","status":{"type":"idle"}},"emittedAtMs":1792096492916}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28db-7702-bc16-eca470bfa3f8","turn":{"id":"01a14146-2966-7090-b823-03570c64c0ad","items":[{"type":"agentMessage","id":"msg_0a8961c525780e95016ad138ecc97c819aa6d8c84f3ec59bc5","text":"done","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096492,"durationMs":13322}},"emittedAtMs":1792096492916}} diff --git a/internal/codex/testdata/contract/Compact.jsonl b/internal/codex/testdata/contract/Compact.jsonl new file mode 100644 index 0000000..522b673 --- /dev/null +++ b/internal/codex/testdata/contract/Compact.jsonl @@ -0,0 +1,55 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479444}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001"]}],"extra":null,"sessionId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28dd-7ef3-bf01-c9f810a30f8a.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Remember the codeword CORAL-42. Reply with the single word ok.","type":"text"}],"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001"]}],"extra":null,"sessionId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28dd-7ef3-bf01-c9f810a30f8a.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveCompact1284327933/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-2991-79c0-84a6-01e2ef975043","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479675}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-2991-79c0-84a6-01e2ef975043","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479675}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479983}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096480016}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480236}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3db2-7973-bdb3-e850b18d3672","clientId":null,"content":[{"type":"text","text":"Remember the codeword CORAL-42. Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","startedAtMs":1792096484787},"emittedAtMs":1792096484787}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3db2-7973-bdb3-e850b18d3672","clientId":null,"content":[{"type":"text","text":"Remember the codeword CORAL-42. Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","completedAtMs":1792096484787},"emittedAtMs":1792096484788}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"codex_apps","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487096}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487097}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487097}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138e73cfc8198af1c320121d894b6","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","startedAtMs":1792096487342},"emittedAtMs":1792096487342}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","itemId":"msg_042cf8aa4f484680016ad138e73cfc8198af1c320121d894b6","delta":"ok"},"emittedAtMs":1792096487342}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138e73cfc8198af1c320121d894b6","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","completedAtMs":1792096487342},"emittedAtMs":1792096487344}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-2991-79c0-84a6-01e2ef975043","tokenUsage":{"total":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096487503}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096487503}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"idle"}},"emittedAtMs":1792096487511}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-2991-79c0-84a6-01e2ef975043","items":[{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138e73cfc8198af1c320121d894b6","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096487,"durationMs":7873}},"emittedAtMs":1792096487511}} +{"dir":"send","msg":{"id":4,"method":"thread/compact/start","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a"}}} +{"dir":"recv","msg":{"id":4,"result":{}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096487561}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-4859-76d2-b7db-25215796e0f1","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096487,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096487562}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"contextCompaction","id":"01a14146-488a-71b0-9be0-0ec24b0d1cde"},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4859-76d2-b7db-25215796e0f1","startedAtMs":1792096487562},"emittedAtMs":1792096487562}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4859-76d2-b7db-25215796e0f1","tokenUsage":{"total":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":4735,"inputTokens":0,"cachedInputTokens":0,"cacheWriteInputTokens":0,"outputTokens":0,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096489263}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096489263}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"contextCompaction","id":"01a14146-488a-71b0-9be0-0ec24b0d1cde"},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4859-76d2-b7db-25215796e0f1","completedAtMs":1792096489263},"emittedAtMs":1792096489264}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"idle"}},"emittedAtMs":1792096489267}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-4859-76d2-b7db-25215796e0f1","items":[],"itemsView":"notLoaded","status":"completed","error":null,"startedAt":1792096487,"completedAt":1792096489,"durationMs":1737}},"emittedAtMs":1792096489267}} +{"dir":"send","msg":{"id":5,"method":"turn/start","params":{"input":[{"text":"What was the codeword? Reply with just the codeword.","type":"text"}],"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a"}}} +{"dir":"recv","msg":{"id":5,"result":{"turn":{"id":"01a14146-4f34-72f3-ac5c-c63714427e34","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096489286}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-4f34-72f3-ac5c-c63714427e34","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096489,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096489286}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-4f5e-7721-9699-409dd89b6de8","clientId":null,"content":[{"type":"text","text":"What was the codeword? Reply with just the codeword.","text_elements":[]}]},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","startedAtMs":1792096489310},"emittedAtMs":1792096489310}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-4f5e-7721-9699-409dd89b6de8","clientId":null,"content":[{"type":"text","text":"What was the codeword? Reply with just the codeword.","text_elements":[]}]},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","completedAtMs":1792096489310},"emittedAtMs":1792096489311}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","startedAtMs":1792096490720},"emittedAtMs":1792096490720}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","itemId":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","delta":"COR"},"emittedAtMs":1792096490720}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","itemId":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","delta":"AL"},"emittedAtMs":1792096490720}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","itemId":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","delta":"-"},"emittedAtMs":1792096490720}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","itemId":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","delta":"42"},"emittedAtMs":1792096490720}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","text":"CORAL-42","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","completedAtMs":1792096490722},"emittedAtMs":1792096490723}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turnId":"01a14146-4f34-72f3-ac5c-c63714427e34","tokenUsage":{"total":{"totalTokens":28212,"inputTokens":28199,"cachedInputTokens":22016,"cacheWriteInputTokens":0,"outputTokens":13,"reasoningOutputTokens":0},"last":{"totalTokens":14885,"inputTokens":14877,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":8,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096490825}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096490825}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","status":{"type":"idle"}},"emittedAtMs":1792096490829}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28dd-7ef3-bf01-c9f810a30f8a","turn":{"id":"01a14146-4f34-72f3-ac5c-c63714427e34","items":[{"type":"agentMessage","id":"msg_042cf8aa4f484680016ad138eab0748198b3fb4268234afb3d","text":"CORAL-42","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096489,"completedAt":1792096490,"durationMs":1551}},"emittedAtMs":1792096490829}} diff --git a/internal/codex/testdata/contract/ImageInput.jsonl b/internal/codex/testdata/contract/ImageInput.jsonl new file mode 100644 index 0000000..240c540 --- /dev/null +++ b/internal/codex/testdata/contract/ImageInput.jsonl @@ -0,0 +1,26 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479435}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28d5-7b11-9b11-057424480eac","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001"]}],"extra":null,"sessionId":"01a14146-28d5-7b11-9b11-057424480eac","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d5-7b11-9b11-057424480eac.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28d5-7b11-9b11-057424480eac","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001"]}],"extra":null,"sessionId":"01a14146-28d5-7b11-9b11-057424480eac","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d5-7b11-9b11-057424480eac.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveImageInput1670751957/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479614}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479614}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479614}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479614}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"type":"image","url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAZElEQVR4nOzPUQkAIBTAQBH7V9YQfhwPdgm2c9dsWwf8akBrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0B7AQAA///jRQGCmaQfxwAAAABJRU5ErkJggg=="},{"text":"Without using any tools, what single colour fills the attached image? Reply with just the colour name.","type":"text"}],"threadId":"01a14146-28d5-7b11-9b11-057424480eac"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-297f-77c0-bb6c-61ed1ee80281","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479651}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turn":{"id":"01a14146-297f-77c0-bb6c-61ed1ee80281","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479651}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479964}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096480009}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480594}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3e15-7fb0-8c35-955cd396e9f5","clientId":null,"content":[{"type":"image","url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAZElEQVR4nOzPUQkAIBTAQBH7V9YQfhwPdgm2c9dsWwf8akBrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0B7AQAA///jRQGCmaQfxwAAAABJRU5ErkJggg==","detail":null},{"type":"text","text":"Without using any tools, what single colour fills the attached image? Reply with just the colour name.","text_elements":[]}]},"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","startedAtMs":1792096484885},"emittedAtMs":1792096484885}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3e15-7fb0-8c35-955cd396e9f5","clientId":null,"content":[{"type":"image","url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAZElEQVR4nOzPUQkAIBTAQBH7V9YQfhwPdgm2c9dsWwf8akBrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0B7AQAA///jRQGCmaQfxwAAAABJRU5ErkJggg==","detail":null},{"type":"text","text":"Without using any tools, what single colour fills the attached image? Reply with just the colour name.","text_elements":[]}]},"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","completedAtMs":1792096484885},"emittedAtMs":1792096484887}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_003f5203aafd0ba2016ad138e603c0819aa870798a22a6a937","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","startedAtMs":1792096486158},"emittedAtMs":1792096486158}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","itemId":"msg_003f5203aafd0ba2016ad138e603c0819aa870798a22a6a937","delta":"Red"},"emittedAtMs":1792096486161}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_003f5203aafd0ba2016ad138e603c0819aa870798a22a6a937","text":"Red","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","completedAtMs":1792096486169},"emittedAtMs":1792096486170}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turnId":"01a14146-297f-77c0-bb6c-61ed1ee80281","tokenUsage":{"total":{"totalTokens":13338,"inputTokens":13333,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":13338,"inputTokens":13333,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096486213}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096486213}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","status":{"type":"idle"}},"emittedAtMs":1792096486215}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28d5-7b11-9b11-057424480eac","turn":{"id":"01a14146-297f-77c0-bb6c-61ed1ee80281","items":[{"type":"agentMessage","id":"msg_003f5203aafd0ba2016ad138e603c0819aa870798a22a6a937","text":"Red","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096486,"durationMs":6596}},"emittedAtMs":1792096486215}} diff --git a/internal/codex/testdata/contract/Interrupt.jsonl b/internal/codex/testdata/contract/Interrupt.jsonl new file mode 100644 index 0000000..26ce2fb --- /dev/null +++ b/internal/codex/testdata/contract/Interrupt.jsonl @@ -0,0 +1,69 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479441}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28db-7511-baef-076c316a5416","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001"]}],"extra":null,"sessionId":"01a14146-28db-7511-baef-076c316a5416","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28db-7511-baef-076c316a5416.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28db-7511-baef-076c316a5416","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001"]}],"extra":null,"sessionId":"01a14146-28db-7511-baef-076c316a5416","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28db-7511-baef-076c316a5416.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479570}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479570}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479570}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479570}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Run the shell command `ping -c 120 127.0.0.1` and wait for it to finish, then say done.","type":"text"}],"threadId":"01a14146-28db-7511-baef-076c316a5416"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-2953-7ea3-a785-043edc78d8c6","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479594}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turn":{"id":"01a14146-2953-7ea3-a785-043edc78d8c6","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479594}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479949}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479949}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480226}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3d6f-7271-bcbd-8888e8e51ee2","clientId":null,"content":[{"type":"text","text":"Run the shell command `ping -c 120 127.0.0.1` and wait for it to finish, then say done.","text_elements":[]}]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","startedAtMs":1792096484720},"emittedAtMs":1792096484720}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3d6f-7271-bcbd-8888e8e51ee2","clientId":null,"content":[{"type":"text","text":"Run the shell command `ping -c 120 127.0.0.1` and wait for it to finish, then say done.","text_elements":[]}]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","completedAtMs":1792096484720},"emittedAtMs":1792096484722}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"reasoning","id":"rs_0061b9e36d0591e7016ad138e5cf708199af350d08cb9c1513","summary":[],"content":[]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","startedAtMs":1792096485948},"emittedAtMs":1792096485948}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"reasoning","id":"rs_0061b9e36d0591e7016ad138e5cf708199af350d08cb9c1513","summary":[],"content":[]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","completedAtMs":1792096485951},"emittedAtMs":1792096485953}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","text":"","phase":"commentary","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","startedAtMs":1792096485970},"emittedAtMs":1792096485970}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":"I"},"emittedAtMs":1792096485970}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":"’m"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" running"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" the"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" ping"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" command"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" now"},"emittedAtMs":1792096486109}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" and"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" will"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" wait"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" until"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" all"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" "},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":"120"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" packets"},"emittedAtMs":1792096486110}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":" complete"},"emittedAtMs":1792096486112}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","delta":"."},"emittedAtMs":1792096486112}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0061b9e36d0591e7016ad138e5d7cc8199be92bdd887c37653","text":"I’m running the ping command now and will wait until all 120 packets complete.","phase":"commentary","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","completedAtMs":1792096486112},"emittedAtMs":1792096486112}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"codex_apps","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096486282}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096486282}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096486282}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"commandExecution","id":"exec-7fee28e4-c913-42ae-808f-239e3eea9c6d","pluginId":null,"scriptPath":null,"command":"/bin/zsh -lc 'ping -c 120 127.0.0.1'","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveInterrupt1556170134/001","processId":"1420","source":"unifiedExecStartup","status":"inProgress","commandActions":[{"type":"unknown","command":"ping -c 120 127.0.0.1"}],"aggregatedOutput":null,"exitCode":null,"durationMs":null},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","startedAtMs":1792096486518},"emittedAtMs":1792096486518}} +{"dir":"recv","msg":{"method":"item/commandExecution/outputDelta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"exec-7fee28e4-c913-42ae-808f-239e3eea9c6d","delta":"64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms\r\n"},"emittedAtMs":1792096487520}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","tokenUsage":{"total":{"totalTokens":13456,"inputTokens":13336,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":120,"reasoningOutputTokens":39},"last":{"totalTokens":13456,"inputTokens":13336,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":120,"reasoningOutputTokens":39},"modelContextWindow":258400}},"emittedAtMs":1792096487525}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096487525}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"reasoning","id":"rs_0061b9e36d0591e7016ad138e81ab0819983ccfb827126edf6","summary":[],"content":[]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","startedAtMs":1792096488130},"emittedAtMs":1792096488130}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"reasoning","id":"rs_0061b9e36d0591e7016ad138e81ab0819983ccfb827126edf6","summary":[],"content":[]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","completedAtMs":1792096488130},"emittedAtMs":1792096488132}} +{"dir":"send","msg":{"id":4,"method":"turn/interrupt","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6"}}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","tokenUsage":{"total":{"totalTokens":27082,"inputTokens":26901,"cachedInputTokens":24064,"cacheWriteInputTokens":0,"outputTokens":181,"reasoningOutputTokens":52},"last":{"totalTokens":13626,"inputTokens":13565,"cachedInputTokens":13056,"cacheWriteInputTokens":0,"outputTokens":61,"reasoningOutputTokens":13},"modelContextWindow":258400}},"emittedAtMs":1792096488527}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096488527}} +{"dir":"recv","msg":{"id":4,"result":{}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","status":{"type":"idle"}},"emittedAtMs":1792096488535}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turn":{"id":"01a14146-2953-7ea3-a785-043edc78d8c6","items":[],"itemsView":"notLoaded","status":"interrupted","error":null,"startedAt":1792096479,"completedAt":1792096488,"durationMs":8961}},"emittedAtMs":1792096488535}} +{"dir":"send","msg":{"id":5,"method":"turn/start","params":{"input":[{"text":"Reply with the single word ok.","type":"text"}],"threadId":"01a14146-28db-7511-baef-076c316a5416"}}} +{"dir":"recv","msg":{"id":5,"result":{"turn":{"id":"01a14146-4c59-7dd0-a5ce-3371594d7b95","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096488558}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turn":{"id":"01a14146-4c59-7dd0-a5ce-3371594d7b95","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096488,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096488558}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-4c85-7ea2-8eeb-8810f4b903a4","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","startedAtMs":1792096488582},"emittedAtMs":1792096488582}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-4c85-7ea2-8eeb-8810f4b903a4","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","completedAtMs":1792096488582},"emittedAtMs":1792096488583}} +{"dir":"recv","msg":{"method":"item/commandExecution/outputDelta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-2953-7ea3-a785-043edc78d8c6","itemId":"exec-7fee28e4-c913-42ae-808f-239e3eea9c6d","delta":"64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.081 ms\r\n"},"emittedAtMs":1792096488653}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0061b9e36d0591e7016ad138e96ef48199b3c586603e1dad65","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","startedAtMs":1792096489469},"emittedAtMs":1792096489469}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","itemId":"msg_0061b9e36d0591e7016ad138e96ef48199b3c586603e1dad65","delta":"ok"},"emittedAtMs":1792096489469}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0061b9e36d0591e7016ad138e96ef48199b3c586603e1dad65","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","completedAtMs":1792096489469},"emittedAtMs":1792096489471}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turnId":"01a14146-4c59-7dd0-a5ce-3371594d7b95","tokenUsage":{"total":{"totalTokens":43394,"inputTokens":43208,"cachedInputTokens":37120,"cacheWriteInputTokens":0,"outputTokens":186,"reasoningOutputTokens":52},"last":{"totalTokens":16312,"inputTokens":16307,"cachedInputTokens":13056,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096489586}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096489586}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","status":{"type":"idle"}},"emittedAtMs":1792096489593}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28db-7511-baef-076c316a5416","turn":{"id":"01a14146-4c59-7dd0-a5ce-3371594d7b95","items":[{"type":"agentMessage","id":"msg_0061b9e36d0591e7016ad138e96ef48199b3c586603e1dad65","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096488,"completedAt":1792096489,"durationMs":1041}},"emittedAtMs":1792096489593}} diff --git a/internal/codex/testdata/contract/ModelSwitch.jsonl b/internal/codex/testdata/contract/ModelSwitch.jsonl new file mode 100644 index 0000000..6609c24 --- /dev/null +++ b/internal/codex/testdata/contract/ModelSwitch.jsonl @@ -0,0 +1,45 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479431}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28ce-71d0-a96f-7f35dfab2b48","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001"]}],"extra":null,"sessionId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28ce-71d0-a96f-7f35dfab2b48.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28ce-71d0-a96f-7f35dfab2b48","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001"]}],"extra":null,"sessionId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28ce-71d0-a96f-7f35dfab2b48.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479610}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479610}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479610}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479610}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Reply with the single word ok.","type":"text"}],"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-297b-7661-9c1b-5a4c4fb8a225","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479650}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turn":{"id":"01a14146-297b-7661-9c1b-5a4c4fb8a225","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479650}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479963}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479993}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480238}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3e1a-70b0-9122-78f1d06d1289","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","startedAtMs":1792096484891},"emittedAtMs":1792096484891}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3e1a-70b0-9122-78f1d06d1289","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","completedAtMs":1792096484891},"emittedAtMs":1792096484892}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e5e61481998e8499d35405d083","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","startedAtMs":1792096486018},"emittedAtMs":1792096486018}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","itemId":"msg_093c6ba0168b299d016ad138e5e61481998e8499d35405d083","delta":"ok"},"emittedAtMs":1792096486018}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e5e61481998e8499d35405d083","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","completedAtMs":1792096486020},"emittedAtMs":1792096486021}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-297b-7661-9c1b-5a4c4fb8a225","tokenUsage":{"total":{"totalTokens":13320,"inputTokens":13315,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":13320,"inputTokens":13315,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096486119}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096486119}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","status":{"type":"idle"}},"emittedAtMs":1792096486121}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turn":{"id":"01a14146-297b-7661-9c1b-5a4c4fb8a225","items":[{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e5e61481998e8499d35405d083","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096486,"durationMs":6506}},"emittedAtMs":1792096486121}} +{"dir":"send","msg":{"id":4,"method":"thread/read","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48"}}} +{"dir":"recv","msg":{"id":4,"result":{"thread":{"id":"01a14146-28ce-71d0-a96f-7f35dfab2b48","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001"]}],"extra":null,"sessionId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","forkedFromId":null,"parentThreadId":null,"preview":"Reply with the single word ok.","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096486,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28ce-71d0-a96f-7f35dfab2b48.jsonl","cwd":"/private/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":{"sha":"a35c357cdbcb9ea71ea2429449ace374203fdf43","branch":"main","originUrl":null},"name":null,"daybreakEnabled":null,"turns":[]}}}} +{"dir":"send","msg":{"id":5,"method":"turn/start","params":{"input":[{"text":"Reply with the single word ok.","type":"text"}],"model":"gpt-5.6-terra","threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48"}}} +{"dir":"recv","msg":{"id":5,"result":{"turn":{"id":"01a14146-42ea-7db3-a7f8-8723e07c8706","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096486131}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turn":{"id":"01a14146-42ea-7db3-a7f8-8723e07c8706","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096486,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096486131}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-4304-7351-b794-342d22541b99","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","startedAtMs":1792096486148},"emittedAtMs":1792096486148}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-4304-7351-b794-342d22541b99","clientId":null,"content":[{"type":"text","text":"Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","completedAtMs":1792096486148},"emittedAtMs":1792096486149}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"codex_apps","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487192}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096487192}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e6fed081998ad337beb2777920","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","startedAtMs":1792096487283},"emittedAtMs":1792096487283}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","itemId":"msg_093c6ba0168b299d016ad138e6fed081998ad337beb2777920","delta":"ok"},"emittedAtMs":1792096487283}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e6fed081998ad337beb2777920","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","completedAtMs":1792096487283},"emittedAtMs":1792096487285}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turnId":"01a14146-42ea-7db3-a7f8-8723e07c8706","tokenUsage":{"total":{"totalTokens":32841,"inputTokens":32831,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":10,"reasoningOutputTokens":0},"last":{"totalTokens":19521,"inputTokens":19516,"cachedInputTokens":0,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096487306}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096487306}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","status":{"type":"idle"}},"emittedAtMs":1792096487314}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","turn":{"id":"01a14146-42ea-7db3-a7f8-8723e07c8706","items":[{"type":"agentMessage","id":"msg_093c6ba0168b299d016ad138e6fed081998ad337beb2777920","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096486,"completedAt":1792096487,"durationMs":1182}},"emittedAtMs":1792096487314}} +{"dir":"send","msg":{"id":6,"method":"thread/read","params":{"threadId":"01a14146-28ce-71d0-a96f-7f35dfab2b48"}}} +{"dir":"recv","msg":{"id":6,"result":{"thread":{"id":"01a14146-28ce-71d0-a96f-7f35dfab2b48","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001"]}],"extra":null,"sessionId":"01a14146-28ce-71d0-a96f-7f35dfab2b48","forkedFromId":null,"parentThreadId":null,"preview":"Reply with the single word ok.","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-terra","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096487,"recencyAt":1792096486,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28ce-71d0-a96f-7f35dfab2b48.jsonl","cwd":"/private/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveModelSwitch3673855641/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":{"sha":"a35c357cdbcb9ea71ea2429449ace374203fdf43","branch":"main","originUrl":null},"name":null,"daybreakEnabled":null,"turns":[]}}}} diff --git a/internal/codex/testdata/contract/Resume-first.jsonl b/internal/codex/testdata/contract/Resume-first.jsonl new file mode 100644 index 0000000..a71b96a --- /dev/null +++ b/internal/codex/testdata/contract/Resume-first.jsonl @@ -0,0 +1,26 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479438}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28d9-72b1-b0e7-97cece4370b5","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001"]}],"extra":null,"sessionId":"01a14146-28d9-72b1-b0e7-97cece4370b5","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d9-72b1-b0e7-97cece4370b5.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28d9-72b1-b0e7-97cece4370b5","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001"]}],"extra":null,"sessionId":"01a14146-28d9-72b1-b0e7-97cece4370b5","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d9-72b1-b0e7-97cece4370b5.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479537}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479537}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479537}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479537}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Remember the codeword AZURE-17. Reply with the single word ok.","type":"text"}],"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-2932-7351-84fa-cc578f1f086f","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479558}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turn":{"id":"01a14146-2932-7351-84fa-cc578f1f086f","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479558}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479657}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479817}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480238}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3e0f-7582-b1c4-bd550ab1bd4f","clientId":null,"content":[{"type":"text","text":"Remember the codeword AZURE-17. Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","startedAtMs":1792096484880},"emittedAtMs":1792096484880}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3e0f-7582-b1c4-bd550ab1bd4f","clientId":null,"content":[{"type":"text","text":"Remember the codeword AZURE-17. Reply with the single word ok.","text_elements":[]}]},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","completedAtMs":1792096484880},"emittedAtMs":1792096484882}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_06ee69f0166f2632016ad138e5bf7c819b87f791e9b6effb7d","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","startedAtMs":1792096485913},"emittedAtMs":1792096485913}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","itemId":"msg_06ee69f0166f2632016ad138e5bf7c819b87f791e9b6effb7d","delta":"ok"},"emittedAtMs":1792096485913}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_06ee69f0166f2632016ad138e5bf7c819b87f791e9b6effb7d","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","completedAtMs":1792096485914},"emittedAtMs":1792096485917}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","tokenUsage":{"total":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096485959}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096485959}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","status":{"type":"idle"}},"emittedAtMs":1792096485967}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turn":{"id":"01a14146-2932-7351-84fa-cc578f1f086f","items":[{"type":"agentMessage","id":"msg_06ee69f0166f2632016ad138e5bf7c819b87f791e9b6effb7d","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096485,"durationMs":6425}},"emittedAtMs":1792096485967}} diff --git a/internal/codex/testdata/contract/Resume-resumed.jsonl b/internal/codex/testdata/contract/Resume-resumed.jsonl new file mode 100644 index 0000000..f769f74 --- /dev/null +++ b/internal/codex/testdata/contract/Resume-resumed.jsonl @@ -0,0 +1,35 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096486019}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/resume","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","model":"gpt-5.6-luna","sandbox":"danger-full-access","threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5"}}} +{"dir":"recv","msg":{"method":"deprecationNotice","params":{"summary":"Full-history hydration is deprecated for paginated threads; use `excludeTurns: true`, then page with `thread/turns/list` and `thread/items/list`.","details":null},"emittedAtMs":1792096486021}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096486053}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096486053}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096486053}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","status":{"type":"idle"}},"emittedAtMs":1792096486054}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28d9-72b1-b0e7-97cece4370b5","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001"]}],"extra":null,"sessionId":"01a14146-28d9-72b1-b0e7-97cece4370b5","forkedFromId":null,"parentThreadId":null,"preview":"Remember the codeword AZURE-17. Reply with the single word ok.","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096486,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d9-72b1-b0e7-97cece4370b5.jsonl","cwd":"/private/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":{"sha":"a35c357cdbcb9ea71ea2429449ace374203fdf43","branch":"main","originUrl":null},"name":null,"daybreakEnabled":null,"turns":[{"id":"01a14146-2932-7351-84fa-cc578f1f086f","items":[{"type":"userMessage","id":"01a14146-3e0f-7582-b1c4-bd550ab1bd4f","clientId":null,"content":[{"type":"text","text":"Remember the codeword AZURE-17. Reply with the single word ok.","text_elements":[]}]},{"type":"agentMessage","id":"msg_06ee69f0166f2632016ad138e5bf7c819b87f791e9b6effb7d","text":"ok","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"full","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096485,"durationMs":6425}]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveResume3756690609/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"collaborationMode":{"mode":"default","settings":{"model":"gpt-5.6-luna","reasoning_effort":null,"developer_instructions":null}},"multiAgentMode":"explicitRequestOnly","initialTurnsPage":null,"turnsBackwardsCursor":"{\"requestedThreadId\":\"01a14146-28d9-72b1-b0e7-97cece4370b5\",\"rolloutOrdinal\":1,\"includeAnchor\":true,\"scope\":{\"kind\":\"turns\"}}","itemsBackwardsCursor":"{\"requestedThreadId\":\"01a14146-28d9-72b1-b0e7-97cece4370b5\",\"rolloutOrdinal\":8,\"includeAnchor\":true,\"scope\":{\"kind\":\"itemsByCreatedAtOrdinal\"}}"}}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-2932-7351-84fa-cc578f1f086f","tokenUsage":{"total":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"last":{"totalTokens":13327,"inputTokens":13322,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":5,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096486054}} +{"dir":"recv","msg":{"method":"thread/goal/cleared","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5"},"emittedAtMs":1792096486055}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"What was the codeword? Reply with just the codeword.","type":"text"}],"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5"}}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-42a7-7f23-8863-7bf831292caf","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096486059}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turn":{"id":"01a14146-42a7-7f23-8863-7bf831292caf","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096486,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096486059}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096486139}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096486160}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096486639}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-4a61-78c1-a931-09ce813326ec","clientId":null,"content":[{"type":"text","text":"What was the codeword? Reply with just the codeword.","text_elements":[]}]},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","startedAtMs":1792096488034},"emittedAtMs":1792096488034}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-4a61-78c1-a931-09ce813326ec","clientId":null,"content":[{"type":"text","text":"What was the codeword? Reply with just the codeword.","text_elements":[]}]},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","completedAtMs":1792096488034},"emittedAtMs":1792096488037}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"codex_apps","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096488079}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096488079}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096488079}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","startedAtMs":1792096488771},"emittedAtMs":1792096488771}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","itemId":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","delta":"AZ"},"emittedAtMs":1792096488771}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","itemId":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","delta":"URE"},"emittedAtMs":1792096488771}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","itemId":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","delta":"-"},"emittedAtMs":1792096488771}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","itemId":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","delta":"17"},"emittedAtMs":1792096488771}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","text":"AZURE-17","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","completedAtMs":1792096488771},"emittedAtMs":1792096488773}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turnId":"01a14146-42a7-7f23-8863-7bf831292caf","tokenUsage":{"total":{"totalTokens":26681,"inputTokens":26668,"cachedInputTokens":22016,"cacheWriteInputTokens":0,"outputTokens":13,"reasoningOutputTokens":0},"last":{"totalTokens":13354,"inputTokens":13346,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":8,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096488832}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096488832}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","status":{"type":"idle"}},"emittedAtMs":1792096488839}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28d9-72b1-b0e7-97cece4370b5","turn":{"id":"01a14146-42a7-7f23-8863-7bf831292caf","items":[{"type":"agentMessage","id":"msg_0c627f0038d30314016ad138e8b5e0819b9ad0c3c267f94479","text":"AZURE-17","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096486,"completedAt":1792096488,"durationMs":2780}},"emittedAtMs":1792096488839}} diff --git a/internal/codex/testdata/contract/TextDeltas.jsonl b/internal/codex/testdata/contract/TextDeltas.jsonl new file mode 100644 index 0000000..e76e583 --- /dev/null +++ b/internal/codex/testdata/contract/TextDeltas.jsonl @@ -0,0 +1,45 @@ +{"dir":"send","msg":{"id":1,"method":"initialize","params":{"clientInfo":{"name":"byre","title":"byre","version":"0.0.0"}}}} +{"dir":"recv","msg":{"id":1,"result":{"userAgent":"byre/0.159.0 (Mac OS 27.0.1; arm64) unknown (byre; 0.0.0)","codexHome":"/Users/flamingcow/.codex","platformFamily":"unix","platformOs":"macos"}}} +{"dir":"send","msg":{"method":"initialized"}} +{"dir":"send","msg":{"id":2,"method":"thread/start","params":{"approvalPolicy":"never","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","model":"gpt-5.6-luna","sandbox":"danger-full-access"}}} +{"dir":"recv","msg":{"method":"remoteControl/status/changed","params":{"status":"disabled","serverName":"roc.tailcecab.ts.net","installationId":"7b5574fb-530f-4cdf-925d-13b538911a88","environmentId":null},"emittedAtMs":1792096479437}} +{"dir":"recv","msg":{"id":2,"result":{"thread":{"id":"01a14146-28d9-7d80-93f9-84270a319777","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001"]}],"extra":null,"sessionId":"01a14146-28d9-7d80-93f9-84270a319777","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d9-7d80-93f9-84270a319777.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]},"model":"gpt-5.6-luna","modelProvider":"openai","serviceTier":null,"disabledPluginIds":[],"cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001"],"instructionSources":[],"approvalPolicy":"never","approvalsReviewer":"user","sandbox":{"type":"dangerFullAccess"},"activePermissionProfile":null,"reasoningEffort":null,"multiAgentMode":"explicitRequestOnly"}}} +{"dir":"send","msg":{"id":3,"method":"turn/start","params":{"input":[{"text":"Without using any tools, count from one to twenty in words, separated by spaces.","type":"text"}],"threadId":"01a14146-28d9-7d80-93f9-84270a319777"}}} +{"dir":"recv","msg":{"method":"thread/started","params":{"thread":{"id":"01a14146-28d9-7d80-93f9-84270a319777","environments":[{"environmentId":"local","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","runtimeWorkspaceRoots":["/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001"]}],"extra":null,"sessionId":"01a14146-28d9-7d80-93f9-84270a319777","forkedFromId":null,"parentThreadId":null,"preview":"","ephemeral":false,"section":null,"sectionEnteredAt":null,"projectId":null,"historyMode":"paginated","modelProvider":"openai","model":"gpt-5.6-luna","reasoningEffort":null,"createdAt":1792096479,"updatedAt":1792096479,"recencyAt":1792096479,"status":{"type":"idle"},"path":"/Users/flamingcow/.codex/sessions/2026/10/15/rollout-2026-10-15T13-34-39-01a14146-28d9-7d80-93f9-84270a319777.jsonl","cwd":"/var/folders/r4/m529kfnd537_x0xfbgcgqfs40000gn/T/TestLiveTextDeltas434632043/001","cliVersion":"0.159.0","originator":"byre","source":"vscode","canAcceptDirectInput":true,"threadSource":null,"agentNickname":null,"agentRole":null,"gitInfo":null,"name":null,"daybreakEnabled":null,"turns":[]}},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","name":"codex_apps","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","name":"cua_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","name":"node_repl","status":"starting","error":null,"failureReason":null},"emittedAtMs":1792096479631}} +{"dir":"recv","msg":{"id":3,"result":{"turn":{"id":"01a14146-2991-7f32-9188-16b05815294f","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":null,"completedAt":null,"durationMs":null}}}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","status":{"type":"active","activeFlags":[]}},"emittedAtMs":1792096479665}} +{"dir":"recv","msg":{"method":"turn/started","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turn":{"id":"01a14146-2991-7f32-9188-16b05815294f","items":[],"itemsView":"notLoaded","status":"inProgress","error":null,"startedAt":1792096479,"completedAt":null,"durationMs":null}},"emittedAtMs":1792096479665}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","name":"node_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096479986}} +{"dir":"recv","msg":{"method":"mcpServer/startupStatus/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","name":"cua_repl","status":"ready","error":null,"failureReason":null},"emittedAtMs":1792096480005}} +{"dir":"recv","msg":{"method":"account/updated","params":{"authMode":"chatgpt","planType":"prolite"},"emittedAtMs":1792096480233}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"userMessage","id":"01a14146-3dbb-7813-9cea-4ff8db66b023","clientId":null,"content":[{"type":"text","text":"Without using any tools, count from one to twenty in words, separated by spaces.","text_elements":[]}]},"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","startedAtMs":1792096484796},"emittedAtMs":1792096484796}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"userMessage","id":"01a14146-3dbb-7813-9cea-4ff8db66b023","clientId":null,"content":[{"type":"text","text":"Without using any tools, count from one to twenty in words, separated by spaces.","text_elements":[]}]},"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","completedAtMs":1792096484796},"emittedAtMs":1792096484797}} +{"dir":"recv","msg":{"method":"item/started","params":{"item":{"type":"agentMessage","id":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","text":"","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","startedAtMs":1792096485703},"emittedAtMs":1792096485703}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":"one"},"emittedAtMs":1792096485703}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" two"},"emittedAtMs":1792096485805}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" three"},"emittedAtMs":1792096485808}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" four"},"emittedAtMs":1792096485808}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" five"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" six"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" seven"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" eight"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" nine"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" ten"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" eleven"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" twelve"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" thirteen"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" fourteen"},"emittedAtMs":1792096485809}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" fifteen"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" sixteen"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" seventeen"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" eighteen"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" nineteen"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/agentMessage/delta","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","itemId":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","delta":" twenty"},"emittedAtMs":1792096485915}} +{"dir":"recv","msg":{"method":"item/completed","params":{"item":{"type":"agentMessage","id":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","text":"one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null},"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","completedAtMs":1792096485915},"emittedAtMs":1792096485923}} +{"dir":"recv","msg":{"method":"thread/tokenUsage/updated","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turnId":"01a14146-2991-7f32-9188-16b05815294f","tokenUsage":{"total":{"totalTokens":13349,"inputTokens":13325,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":24,"reasoningOutputTokens":0},"last":{"totalTokens":13349,"inputTokens":13325,"cachedInputTokens":11008,"cacheWriteInputTokens":0,"outputTokens":24,"reasoningOutputTokens":0},"modelContextWindow":258400}},"emittedAtMs":1792096485974}} +{"dir":"recv","msg":{"method":"account/rateLimits/updated","params":{"rateLimits":{"limitId":"codex","limitName":null,"normalModelSlug":null,"primary":{"usedPercent":0,"windowDurationMins":10080,"resetsAt":1792701205},"secondary":null,"credits":{"hasCredits":false,"unlimited":false,"balance":"0"},"individualLimit":null,"spendControlReached":null,"planType":"prolite","rateLimitReachedType":null}},"emittedAtMs":1792096485974}} +{"dir":"recv","msg":{"method":"thread/status/changed","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","status":{"type":"idle"}},"emittedAtMs":1792096485981}} +{"dir":"recv","msg":{"method":"turn/completed","params":{"threadId":"01a14146-28d9-7d80-93f9-84270a319777","turn":{"id":"01a14146-2991-7f32-9188-16b05815294f","items":[{"type":"agentMessage","id":"msg_0870b29190278ff0016ad138e5987c8198b5fcb07f868c7df2","text":"one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty","phase":"final_answer","memoryCitation":null,"delivery":null,"questions":null}],"itemsView":"summary","status":"completed","error":null,"startedAt":1792096479,"completedAt":1792096485,"durationMs":6342}},"emittedAtMs":1792096485981}}