From 586f2bce8fd568d2451138e7f2a01fb991fcd8c2 Mon Sep 17 00:00:00 2001 From: yetone Date: Thu, 8 Oct 2026 05:10:45 +0800 Subject: [PATCH] context: magpie inspects the context window of every request, session and agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gateway reads each request's prompt into its parts (system prompt, tools and MCP servers, memory, files, tool results, chat), measured against the model's window and calibrated to the tokens the vendor counted. Routing shows a request's window as a card: a 400-cell grid by part, a hover naming what is largest in a cell, and the contents by part. The Usage page's Context tab scores each agent out of 100 (cache reuse, how lean it starts, how fast it grows, how reliably it answers), tags it (lean, cache-friendly, mcp-heavy, compacts, near-full…), and draws each session's growth with its latest request's card. Older Safari (15) gets media-query and solid-colour fallbacks for the card's container queries and color-mix. --- docs/subsystems/gateway-routing.md | 1 + docs/subsystems/gui-shell.md | 2 +- internal/gateway/codex_backend.go | 8 +- internal/gateway/gateway.go | 12 +- internal/gateway/prompt.go | 1061 ++++++++++++++++ internal/gateway/prompt_test.go | 286 +++++ .../gateway/testdata/context/claude-code.json | 1131 +++++++++++++++++ internal/gateway/testdata/context/codex.json | 527 ++++++++ internal/gateway/trace.go | 6 + internal/gui/assets/app.js | 9 +- internal/gui/assets/context.css | 217 ++++ internal/gui/assets/context.js | 619 +++++++++ internal/gui/assets/i18n.js | 436 +++++++ internal/gui/assets/index.html | 3 + internal/gui/assets/routing.js | 35 +- internal/gui/assets_revalidate_test.go | 2 +- internal/gui/context.go | 442 +++++++ internal/gui/context_test.go | 148 +++ internal/gui/providers.go | 1 + internal/gui/tests/README.md | 9 + internal/gui/tests/context-window.test.cjs | 182 +++ site/public/docs/ja/start.html | 1 + site/public/docs/start.html | 1 + site/public/docs/zh/start.html | 1 + 24 files changed, 5133 insertions(+), 7 deletions(-) create mode 100644 internal/gateway/prompt.go create mode 100644 internal/gateway/prompt_test.go create mode 100644 internal/gateway/testdata/context/claude-code.json create mode 100644 internal/gateway/testdata/context/codex.json create mode 100644 internal/gui/assets/context.css create mode 100644 internal/gui/assets/context.js create mode 100644 internal/gui/context.go create mode 100644 internal/gui/context_test.go create mode 100644 internal/gui/tests/context-window.test.cjs diff --git a/docs/subsystems/gateway-routing.md b/docs/subsystems/gateway-routing.md index 08426460..7b69ac27 100644 --- a/docs/subsystems/gateway-routing.md +++ b/docs/subsystems/gateway-routing.md @@ -24,6 +24,7 @@ served by a plugin are in [Provider and plugin ownership](provider-plugins.md). | Affinity | A conversation stays with the key or account that answered it, so the vendor's prompt cache is read again. Modes: auto (""), `session`, `turn`, `off`. Stored in `affinity.json` next to `providers.json`. | [`affinity.go`](../../internal/gateway/affinity.go) | | One try | `attempt` sends one candidate the request. It goes through the provider's proxy (`p.Via`). A subscription with its own client is served specially, such as Claude through the genuine Claude Code. The request is relayed as is (`passthrough`) when the model is usable on the agent's API, except that a Claude model where the provider has an Anthropic URL is translated to Messages from Chat or Responses too (`OnMessages`: OpenCode speaks Chat for every model, and a relay drops cache_control there), unless the user set the model's API or the vendor's list names its APIs. A request offering web search to a provider that doesn't search by itself is translated too, so magpie can search for it (`search.go`), but on the agent's own API where the provider serves it and no `ResponsesFirst`/`MessagesFirst` rule prefers another: Codex offers web_search on every turn, and each went out as Chat (#997). Otherwise it is translated (`translate`) to the first API `usable` gives: Chat, except Responses for OpenAI's models where their maker serves them (`ResponsesFirst`) and Anthropic's Messages for a Claude model where the provider has an Anthropic URL (`MessagesFirst`, which keeps its cache breakpoints, #997). `Provider.Native`, the API agents with a per-model API (Pi, omp, droid) are wired to ask on, follows the same order. | [`gateway.go`](../../internal/gateway/gateway.go) | | Trace | The Routing view's record of each decision, written where the decision is made: candidates, rests, which try answered. | [`trace.go`](../../internal/gateway/trace.go) | +| Prompt | What each request's prompt held, part by part: the agent's system prompt, tool definitions (an MCP server's tools as one item), instruction files and skills, files its tools read, their other output, and the conversation. `inspectPrompt` reads it from the body as the agent sent it, before translation; `calibrated` scales the estimate to the prompt the vendor counted and sets the window of the model that answered. Only names are kept, never the text. It goes on the trace as `Route.Prompt`, with `Route.Conv` naming a conversation that has no session id. The GUI's `/api/context` scores each agent from it (`internal/gui/context.go`). | [`prompt.go`](../../internal/gateway/prompt.go) | ## Runtime path diff --git a/docs/subsystems/gui-shell.md b/docs/subsystems/gui-shell.md index 804707a2..8adbf685 100644 --- a/docs/subsystems/gui-shell.md +++ b/docs/subsystems/gui-shell.md @@ -15,7 +15,7 @@ three. | Backend | `startBackend` starts the gateway this process serves, unless another magpie already serves it. In that case this process only shows the other one's status (`gw` is nil). `stopServing` drains requests in flight. | [`backend.go`](../../internal/gui/backend.go) | | API and assets | `Handler` serves `assets/` (embedded with `//go:embed assets`) and the `/api/*` routes, such as `/api/state`, `/api/set` and `/api/agents/{action}/{id}`. `held` lets one API request's reads share one catalog build (`provider.Hold`), and drops it after any write. `revalidated` and `versionedPage` name each script by its content hash, so a cache never serves an old `app.js` under a new page. | [`api.go`](../../internal/gui/api.go) | | Browser mode | `StartWeb` serves the page and the gateway for `magpie web`. The browser signs in with a run key in a link. Gateway mode shows only Providers, Gateway, Routing, Usage, Plugins and Settings on a machine that is only a gateway. | [`web.go`](../../internal/gui/web.go), [`gatewaymode.go`](../../internal/gui/gatewaymode.go) | -| The page | `app.js` keeps one state object per view and renders it into a list, with no framework. The views have their own files: `routing.js`, `library.js`, `plugins.js` and `sessions.js`. Strings go through `t()` with translations in `i18n.js` (zh, zh-TW, ja and de; the English text is the key and the fallback). zh-TW is Traditional Chinese with Taiwan's words; a system language of zh-TW, zh-HK, zh-MO or any zh-Hant picks it, and the tray menu and notifications follow (`trayLang`). Dropdowns use `openProtoMenu`. Scrolling is done only by `scrollOnPurpose(e)` with the reader's event. | [`assets/app.js`](../../internal/gui/assets/app.js), [`assets/i18n.js`](../../internal/gui/assets/i18n.js) | +| The page | `app.js` keeps one state object per view and renders it into a list, with no framework. The views have their own files: `routing.js`, `library.js`, `plugins.js`, `sessions.js` and `context.js` (Usage's Context tab, and the context window card the Routing page draws under a request's story, fed by `/api/context` in `context.go`, which scores and tags each agent). Strings go through `t()` with translations in `i18n.js` (zh, zh-TW, ja and de; the English text is the key and the fallback). zh-TW is Traditional Chinese with Taiwan's words; a system language of zh-TW, zh-HK, zh-MO or any zh-Hant picks it, and the tray menu and notifications follow (`trayLang`). Dropdowns use `openProtoMenu`. Scrolling is done only by `scrollOnPurpose(e)` with the reader's event. | [`assets/app.js`](../../internal/gui/assets/app.js), [`assets/i18n.js`](../../internal/gui/assets/i18n.js) | | No GUI build | `-tags nogui` builds magpie without the GUI: `hasGUI` is false and `runGUI` says to use `magpie tui`. The files of `internal/gui` that need Wails build under `!nogui`. | [`gui_off.go`](../../gui_off.go) | ## Runtime path diff --git a/internal/gateway/codex_backend.go b/internal/gateway/codex_backend.go index aa34df30..5d90efa0 100644 --- a/internal/gateway/codex_backend.go +++ b/internal/gateway/codex_backend.go @@ -19,6 +19,7 @@ import ( "github.com/klauspost/compress/zstd" "github.com/yetone/magpie/internal/access" + "github.com/yetone/magpie/internal/catalog" "github.com/yetone/magpie/internal/codexcat" "github.com/yetone/magpie/internal/provider" "github.com/yetone/magpie/internal/usage" @@ -429,8 +430,9 @@ func (s *Server) codexUpstream(w http.ResponseWriter, r *http.Request, rest stri seat := Weighed{ID: "codex", Provider: "openai", Name: "OpenAI", Icon: "openai", Who: who, Kind: "account", Agent: "codex", Model: model} link := s.titlePrompts.observe(r, body, metadata, kind, start) captureTitle = link != nil && isTitleKind(kind) - tr = s.trace.begin(Route{imageTurn: drawingTurnID(metadata.Turn), imageCaller: codexTurnKey(r, callerOf(r).agent), imageProvider: imageProvider, TitleLink: link, Time: start, Agent: agentOf(r), Session: sessionOf(r.Header), ParentSession: titleParentSession(r.Header, metadata, kind), Kind: kind, Model: model, Effort: effort, Provider: "openai", + tr = s.trace.begin(Route{imageTurn: drawingTurnID(metadata.Turn), imageCaller: codexTurnKey(r, callerOf(r).agent), imageProvider: imageProvider, TitleLink: link, Time: start, Agent: agentOf(r), Session: sessionOf(r.Header), Conv: convOf(r.Header, body), ParentSession: titleParentSession(r.Header, metadata, kind), Kind: kind, Model: model, Effort: effort, Provider: "openai", Order: []Weighed{seat}, Tries: []Try{{ID: seat.ID, Model: model, Effort: effort, Start: start}}}) + promptRead := s.inspectPrompt(tr, provider.Responses, body) end = func(status int, msg string, tokens, out int) { ms := time.Since(start).Milliseconds() ttft, text := first.ms() @@ -438,6 +440,7 @@ func (s *Server) codexUpstream(w http.ResponseWriter, r *http.Request, rest stri if captureTitle && status < 400 && msg == "" && !titleReply.truncated { replyDigest = titleReplyDigest(titleReply.buf.Bytes(), nil) } + prompt := promptRead() // outside the trace's lock, which reading it takes s.trace.update(tr, func(t *Route) { t.Tries[0].Done, t.Tries[0].Status, t.Tries[0].Millis, t.Tries[0].Error = true, status, ms, msg t.Tries[0].TTFT, t.Tries[0].FirstText = ttft, text @@ -449,6 +452,9 @@ func (s *Server) codexUpstream(w http.ResponseWriter, r *http.Request, rest stri } t.Output, t.Reasoning, t.TTFT, t.FirstText = out, uu.Reasoning, ttft, text t.Usage = routeUsage("openai", model, uu) + if prompt != nil { + t.Prompt = prompt.calibrated(promptCounted(t.Usage), catalog.ContextOf(model)) + } t.Tries[0].Served, t.Tries[0].Swapped = served, swapped(model, served) t.Served, t.Swapped = t.Tries[0].Served, t.Tries[0].Swapped }) diff --git a/internal/gateway/gateway.go b/internal/gateway/gateway.go index 81e147b5..c3a5b7e4 100644 --- a/internal/gateway/gateway.go +++ b/internal/gateway/gateway.go @@ -1634,10 +1634,12 @@ func (s *Server) serve(w http.ResponseWriter, r *http.Request, from provider.Pro shown = nil // nobody else to stay away from } link := s.titlePrompts.observe(r, body, metadata, call.Kind, start) - tr := s.trace.begin(Route{imageTurn: drawingTurnID(metadata.Turn), imageCaller: codexTurnKey(r, call.Agent), TitleLink: link, Pinned: pin, Time: start, Agent: call.Agent, Session: sessionOf(r.Header), ParentSession: titleParentSession(r.Header, metadata, call.Kind), Kind: call.Kind, For: call.For, Model: call.Model, Effort: requestEffort(from, body), Provider: p.ID, Group: group, Rule: hit, Nested: nested, SealedTask: sealedTask, LeadAccount: leadAccount, Affinity: shown, Order: pl.order, Left: pl.left}) + tr := s.trace.begin(Route{imageTurn: drawingTurnID(metadata.Turn), imageCaller: codexTurnKey(r, call.Agent), TitleLink: link, Pinned: pin, Time: start, Agent: call.Agent, Session: sessionOf(r.Header), Conv: convOf(r.Header, body), ParentSession: titleParentSession(r.Header, metadata, call.Kind), Kind: call.Kind, For: call.For, Model: call.Model, Effort: requestEffort(from, body), Provider: p.ID, Group: group, Rule: hit, Nested: nested, SealedTask: sealedTask, LeadAccount: leadAccount, Affinity: shown, Order: pl.order, Left: pl.left}) if telemetry != nil { telemetry.routeID = tr.ID } + promptRead := s.inspectPrompt(tr, from, body) + var lastTried provider.Provider // the last try's, for its model's context window var skipped []string sent := "" // the reasoning the last try's model was asked for where := "" // the last try's provider.Where, for the usage @@ -1690,6 +1692,7 @@ func (s *Server) serve(w http.ResponseWriter, r *http.Request, from provider.Pro } call.Provider, call.To, call.Usage = c.p.ID, "", Usage{} model = c.model + lastTried = c.p where = c.p.Where() providerKeyID, providerKeyName = "", "" if c.p.Account == nil && c.p.Key != "" { @@ -2343,6 +2346,10 @@ func (s *Server) serve(w http.ResponseWriter, r *http.Request, from provider.Pro if link != nil && isTitleKind(call.Kind) && call.Status < 400 && call.Error == "" && !call.ResponseTruncated { replyDigest = titleReplyDigest([]byte(call.ResponseBody), replyTitleShape(r.Context())) } + prompt, window := promptRead(), 0 + if prompt != nil && lastTried.ID != "" { + window = windowOf(lastTried, model) + } s.trace.update(tr, func(t *Route) { t.Done, t.Status, t.Error, t.Millis = true, call.Status, call.Error, call.Millis if t.TitleLink != nil && isTitleKind(t.Kind) && call.Status < 400 && call.Error == "" && !call.ResponseTruncated { @@ -2355,6 +2362,9 @@ func (s *Server) serve(w http.ResponseWriter, r *http.Request, from provider.Pro } t.Tokens = call.Usage.Input + call.Usage.Output + call.Usage.CacheRead + call.Usage.CacheWrite t.Output, t.Reasoning, t.TTFT, t.FirstText = call.Usage.Output, call.Usage.Reasoning, call.TTFT, call.FirstText + if prompt != nil { + t.Prompt = prompt.calibrated(promptCounted(t.Usage), window) + } if n := len(t.Tries); n > 0 && call.Status < 400 { t.Served, t.Swapped, t.Routed = t.Tries[n-1].Served, t.Tries[n-1].Swapped, t.Tries[n-1].Routed t.Upstream = t.Tries[n-1].Upstream diff --git a/internal/gateway/prompt.go b/internal/gateway/prompt.go new file mode 100644 index 00000000..f773a11f --- /dev/null +++ b/internal/gateway/prompt.go @@ -0,0 +1,1061 @@ +package gateway + +// What a request's prompt is made of: the agent's system prompt, its tool +// definitions, the instruction files it read in (CLAUDE.md, AGENTS.md, +// skills), the files its tools read, its tools' other output, and the +// conversation, each as the tokens it takes of the model's context window. +// Read from the body the agent sent, as it sent it: the parsed Request has +// the system blocks run together, and Codex's additional_tools lifted out. +// +// The sizes are estimated as the body is read, then scaled to the prompt +// the vendor counted once it answers (calibrate). Only names are kept — the +// instruction files' and read files' paths, the tools' names, "turn 3" — +// never the prompt's text. + +import ( + "encoding/json" + "net/http" + "regexp" + "slices" + "strconv" + "strings" + "unicode/utf8" + + "github.com/yetone/magpie/internal/provider" +) + +// The kinds of a prompt's parts, in the order they are shown. +const ( + PartSystem = "system" // the agent's own prompt: system, developer and harness messages + PartTools = "tools" // tool definitions + PartMemory = "memory" // instruction files, skills, reminders + PartFiles = "files" // files and images the tools read in + PartResults = "results" // the tools' other output + PartChat = "chat" // what the user and the model said, the model's calls +) + +var partOrder = []string{PartSystem, PartTools, PartMemory, PartFiles, PartResults, PartChat} + +// Prompt is a request's prompt, part by part. +type Prompt struct { + Window int `json:"window,omitempty"` // the context window of the model that answered, when known + // Tokens: the prompt, as the vendor counted it when Counted, the parts + // scaled to it; estimated from the body before that + Tokens int `json:"tokens"` + Counted bool `json:"counted,omitempty"` + // Held: the request named a previous response, whose turns the vendor + // holds; they are in Tokens once counted, as the conversation + Held bool `json:"held,omitempty"` + Turns int `json:"turns,omitempty"` // the user's turns in it + Parts []PromptPart `json:"parts"` +} + +// PromptPart is one kind of what a prompt holds. +type PromptPart struct { + Kind string `json:"kind"` + Tokens int `json:"tokens"` + Items []PromptItem `json:"items,omitempty"` // largest first, promptItems at most +} + +// PromptItem is one thing in a part: a tool, an MCP server's tools, an +// instruction file, a file read, a turn. +type PromptItem struct { + Name string `json:"name"` + Tag string `json:"tag,omitempty"` // what it is: mcp, user, project, skills, reminder, image, read, shell, turn… + N int `json:"n,omitempty"` // how many it gathers: an MCP server's tools, a tool's results + Tokens int `json:"tokens"` +} + +// promptItems is how many items a part keeps; the rest are summed in one. +const promptItems = 24 + +// tokensOf estimates the tokens of a text: about four characters a token +// for ASCII, a token a character for the rest (CJK, mostly). +func tokensOf(s string) int { + ascii, other := 0, 0 + for i := 0; i < len(s); { + if s[i] < utf8.RuneSelf { + ascii++ + i++ + continue + } + _, n := utf8.DecodeRuneInString(s[i:]) + other++ + i += n + } + return (ascii+3)/4 + other +} + +func rawTokens(b json.RawMessage) int { return (len(b) + 3) / 4 } + +// imageTokens is what an image is taken to cost: about what Anthropic +// counts for a 1092×1092 one. +const imageTokens = 1600 + +type promptBuilder struct { + parts map[string]map[string]*PromptItem + turn int + held bool + calls map[string]toolCall // call id → what was called, for its result +} + +type toolCall struct { + name string + files []string // the files it reads, when it reads files +} + +func newPromptBuilder() *promptBuilder { + return &promptBuilder{parts: map[string]map[string]*PromptItem{}, calls: map[string]toolCall{}} +} + +func (b *promptBuilder) add(kind, name, tag string, tokens int) { + if tokens <= 0 { + return + } + m := b.parts[kind] + if m == nil { + m = map[string]*PromptItem{} + b.parts[kind] = m + } + key := tag + "\x00" + name + it := m[key] + if it == nil { + it = &PromptItem{Name: name, Tag: tag} + m[key] = it + } + it.N++ + it.Tokens += tokens +} + +// chat adds to the conversation's current turn. +func (b *promptBuilder) chat(tokens int) { + if b.turn == 0 { + b.turn = 1 + } + b.add(PartChat, strconv.Itoa(b.turn), "turn", tokens) +} + +func (b *promptBuilder) newTurn() { b.turn++ } + +func (b *promptBuilder) prompt() *Prompt { + p := &Prompt{Held: b.held, Turns: b.turn, Parts: []PromptPart{}} + for _, kind := range partOrder { + m := b.parts[kind] + if len(m) == 0 { + continue + } + part := PromptPart{Kind: kind} + items := make([]PromptItem, 0, len(m)) + for _, it := range m { + part.Tokens += it.Tokens + c := *it + if c.Tag != "mcp" && c.Tag != "namespace" && c.Tag != "result" { + c.N = 0 // a count only where it says something + } + if c.N == 1 { + c.N = 0 + } + items = append(items, c) + } + if kind == PartChat { + slices.SortFunc(items, func(a, b PromptItem) int { + x, _ := strconv.Atoi(a.Name) + y, _ := strconv.Atoi(b.Name) + return x - y + }) + // the turns keep the latest ones, oldest first + if len(items) > promptItems { + rest := PromptItem{Name: "earlier", Tag: "turns", N: len(items) - promptItems + 1} + for _, it := range items[:len(items)-promptItems+1] { + rest.Tokens += it.Tokens + } + items = append([]PromptItem{rest}, items[len(items)-promptItems+1:]...) + } + } else { + slices.SortFunc(items, func(a, b PromptItem) int { + if a.Tokens != b.Tokens { + return b.Tokens - a.Tokens + } + return strings.Compare(a.Name, b.Name) + }) + if len(items) > promptItems { + rest := PromptItem{Name: "other", Tag: "more", N: len(items) - promptItems + 1} + for _, it := range items[promptItems-1:] { + rest.Tokens += it.Tokens + } + items = append(items[:promptItems-1:promptItems-1], rest) + } + } + part.Items = items + p.Tokens += part.Tokens + p.Parts = append(p.Parts, part) + } + return p +} + +// promptOf reads what a request's prompt holds; nil when the body isn't +// one it can read. +func promptOf(from provider.Protocol, body []byte) (p *Prompt) { + defer func() { + if recover() != nil { + p = nil + } + }() + b := newPromptBuilder() + var ok bool + switch from { + case provider.Anthropic: + ok = b.anthropic(body) + case provider.Responses: + ok = b.responses(body) + case provider.Chat: + ok = b.chatCompletions(body) + case provider.Gemini: + ok = b.gemini(body) + } + if !ok { + return nil + } + return b.prompt() +} + +// calibrate scales the parts to the prompt the vendor counted, and notes +// the window of the model that answered. +func (p *Prompt) calibrate(counted, window int) { + if p == nil { + return + } + if window > 0 { + p.Window = window + } + if counted <= 0 || p.Counted { + return + } + est := p.Tokens + if est <= 0 { + return + } + scale := float64(counted) / float64(est) + sum := 0 + for i := range p.Parts { + part := &p.Parts[i] + part.Tokens = int(float64(part.Tokens)*scale + 0.5) + for j := range part.Items { + part.Items[j].Tokens = int(float64(part.Items[j].Tokens)*scale + 0.5) + } + sum += part.Tokens + } + // what rounding left goes to the largest part, so they add up + if n := len(p.Parts); n > 0 && sum != counted { + big := 0 + for i := range p.Parts { + if p.Parts[i].Tokens > p.Parts[big].Tokens { + big = i + } + } + p.Parts[big].Tokens += counted - sum + } + p.Tokens, p.Counted = counted, true +} + +// --- text: instruction files, reminders, harness messages --- + +var ( + // Claude Code: "Contents of /path/CLAUDE.md (project instructions, …):" + contentsOf = regexp.MustCompile(`(?m)^Contents of (\S.*?) \(([^()\n]*(?:\([^()\n]*\)[^()\n]*)*)\):[ \t]*$`) + // OpenCode: "Instructions from: /path/AGENTS.md" + instructionsFrom = regexp.MustCompile(`(?m)^Instructions from: (\S.*?)[ \t]*$`) + // Codex: "# AGENTS.md instructions for /path" + agentsFor = regexp.MustCompile(`^# (\S+\.md) instructions for (\S.*?)[ \t]*\n`) + leadTag = regexp.MustCompile(`^\s*<([a-zA-Z_][\w -]{0,40})>`) +) + +// memoryTag says whose an instruction file is from how the agent +// describes it, or its path. +func memoryTag(path, desc string) string { + d := strings.ToLower(desc) + switch { + case strings.Contains(d, "user's") || strings.Contains(d, "global"): + return "user" + case strings.Contains(d, "local"): + return "local" + case strings.Contains(d, "auto-memory") || strings.Contains(d, "memory"): + return "memory" + case d != "": + return "project" + } + if strings.Contains(path, "/.claude/") || strings.Contains(path, "/.codex/") || strings.Contains(path, "/.config/") { + return "user" + } + return "project" +} + +// splitMemory takes the instruction files out of a text: each is added as +// memory, and what is left is returned. +func (b *promptBuilder) splitMemory(text string) string { + type section struct { + at, body int + path, desc string + openCodeish bool + } + var ss []section + for _, m := range contentsOf.FindAllStringSubmatchIndex(text, -1) { + ss = append(ss, section{at: m[0], body: m[1], path: text[m[2]:m[3]], desc: text[m[4]:m[5]]}) + } + for _, m := range instructionsFrom.FindAllStringSubmatchIndex(text, -1) { + ss = append(ss, section{at: m[0], body: m[1], path: text[m[2]:m[3]], openCodeish: true}) + } + if len(ss) == 0 { + return text + } + slices.SortFunc(ss, func(a, b section) int { return a.at - b.at }) + var rest strings.Builder + rest.WriteString(text[:ss[0].at]) + for i, s := range ss { + end := len(text) + if i+1 < len(ss) { + end = ss[i+1].at + } + chunk := text[s.at:end] + // a reminder's closing tag and what follows it aren't the file's + if j := strings.Index(chunk, ""); j >= 0 { + rest.WriteString(chunk[j:]) + chunk = chunk[:j] + } + b.add(PartMemory, s.path, memoryTag(s.path, s.desc), tokensOf(chunk)) + } + return rest.String() +} + +// harnessName names a system or developer text by its leading tag, or +// what it is. +func harnessName(text, fallback string) string { + if m := leadTag.FindStringSubmatch(text); m != nil { + return strings.TrimSpace(m[1]) + } + if strings.HasPrefix(text, "# Environment") { + return "environment" + } + return fallback +} + +// systemText adds the agent's own prompt, with the instruction files in +// it taken out as memory. +func (b *promptBuilder) systemText(text, name string) { + rest := b.splitMemory(text) + if strings.HasPrefix(strings.TrimSpace(rest), "") { + b.add(PartMemory, "skills", "skills", tokensOf(rest)) + return + } + b.add(PartSystem, harnessName(rest, name), "", tokensOf(rest)) +} + +// userText adds a user's text: an instruction file or reminder the agent +// put in as the user, or what the user said. It says which. +func (b *promptBuilder) userText(text string) (said bool) { + t := strings.TrimSpace(text) + switch { + case strings.HasPrefix(t, ""): + rest := b.splitMemory(t) + rest = strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(rest), ""), "")) + if rest != "" { + b.add(PartMemory, "reminders", "reminder", tokensOf(rest)) + } + return false + case agentsFor.MatchString(t): + m := agentsFor.FindStringSubmatch(t) + path := strings.TrimRight(m[2], "/") + "/" + m[1] + b.add(PartMemory, path, "project", tokensOf(t)) + return false + case strings.HasPrefix(t, "") || strings.HasPrefix(t, "") || + strings.HasPrefix(t, "") || strings.HasPrefix(t, ""): + b.add(PartSystem, harnessName(t, "context"), "", tokensOf(t)) + return false + } + b.chat(tokensOf(text)) + return true +} + +// --- tool calls and what they read --- + +var ( + // the tools that read a file, and where they take its path + readTools = map[string]bool{"Read": true, "read": true, "read_file": true, "ReadFile": true, "view": true, + "View": true, "NotebookRead": true, "readFile": true, "open_file": true, "cat": true} + pathKeys = []string{"file_path", "path", "filePath", "target_file", "notebook_path", "file", "filename", "uri"} + cmdOfExec = regexp.MustCompile(`\bcmd\s*:\s*"((?:[^"\\]|\\.)*)"`) + toolOfJS = regexp.MustCompile(`\btools\.(\w+)\s*\(`) + readCmds = map[string]bool{"cat": true, "head": true, "tail": true, "nl": true, "bat": true, "less": true, "more": true} +) + +// filesOfCommand is the files a shell command reads, when all it does is +// read files: cat, head, tail, nl, bat, sed -n. +func filesOfCommand(cmd string) []string { + cmd = strings.TrimSpace(cmd) + // bash -lc "…", as Codex sends its shell tool's + for _, pre := range []string{"bash -lc ", "bash -c ", "sh -c ", "zsh -lc "} { + if strings.HasPrefix(cmd, pre) { + cmd = strings.Trim(strings.TrimSpace(cmd[len(pre):]), `"'`) + } + } + if strings.ContainsAny(cmd, "|;&><`$") { + // a pipeline or more than one command: not a plain read; but + // "cd dir && cat x" still is + if i := strings.Index(cmd, "&&"); i >= 0 && strings.HasPrefix(cmd, "cd ") && !strings.ContainsAny(cmd[i+2:], "|;&><`$") { + cmd = strings.TrimSpace(cmd[i+2:]) + } else { + return nil + } + } + f := strings.Fields(cmd) + if len(f) < 2 { + return nil + } + sed := f[0] == "sed" && slices.Contains(f, "-n") + if !readCmds[f[0]] && !sed { + return nil + } + var files []string + for i := 1; i < len(f); i++ { + a := strings.Trim(f[i], `"'`) + if strings.HasPrefix(a, "-") { + if (a == "-n" || a == "-c") && !sed && i+1 < len(f) { + i++ // head -n 40 + } + continue + } + if sed && strings.HasSuffix(a, "p") && strings.ContainsAny(a, "0123456789,") && !strings.Contains(a, "/") && !strings.Contains(a, ".") { + continue // sed -n 1,80p + } + if _, err := strconv.Atoi(a); err == nil { + continue + } + files = append(files, a) + } + return files +} + +// callOf reads what a tool call does from its name and input: the files +// it reads, and the name its results go by. +func callOf(name string, input []byte) toolCall { + c := toolCall{name: name} + var args map[string]json.RawMessage + _ = json.Unmarshal(input, &args) + str := func(k string) string { + var s string + if json.Unmarshal(args[k], &s) == nil { + return s + } + return "" + } + if readTools[name] { + for _, k := range pathKeys { + if s := str(k); s != "" { + c.files = []string{s} + return c + } + } + } + cmd := str("command") + if cmd == "" { + cmd = str("cmd") + } + if cmd == "" { + var argv []string + if json.Unmarshal(args["command"], &argv) == nil { + cmd = strings.Join(argv, " ") + } + } + if cmd == "" && args == nil { + // Codex's exec takes JavaScript: text(await tools.exec_command({cmd:"cat x"})) + s := string(input) + if m := toolOfJS.FindStringSubmatch(s); m != nil { + c.name = m[1] + } + if m := cmdOfExec.FindStringSubmatch(s); m != nil { + cmd, _ = strconv.Unquote(`"` + m[1] + `"`) + } + } + if cmd != "" { + c.files = filesOfCommand(cmd) + } + return c +} + +// result adds what a tool answered: the files it read, or its output. +func (b *promptBuilder) result(callID string, tokens int) { + c, ok := b.calls[callID] + if !ok { + c.name = "tool" + } + if len(c.files) > 0 { + each := tokens / len(c.files) + for i, f := range c.files { + n := each + if i == 0 { + n += tokens - each*len(c.files) + } + tag := "read" + if !readTools[c.name] { + tag = "shell" + } + b.add(PartFiles, f, tag, n) + } + return + } + b.add(PartResults, c.name, "result", tokens) +} + +// tool adds a tool definition: an MCP server's tools as one. +func (b *promptBuilder) tool(name string, tokens int) { + if strings.HasPrefix(name, "mcp__") { + rest := strings.TrimPrefix(name, "mcp__") + server := rest + if i := strings.Index(rest, "__"); i > 0 { + server = rest[:i] + } + b.add(PartTools, server, "mcp", tokens) + return + } + b.add(PartTools, name, "", tokens) +} + +// --- Anthropic Messages --- + +type rawBlock struct { + Type string `json:"type"` + Text string `json:"text"` + Thinking string `json:"thinking"` + Data string `json:"data"` + ID string `json:"id"` + Name string `json:"name"` + Input json.RawMessage `json:"input"` + ToolUseID string `json:"tool_use_id"` + Content json.RawMessage `json:"content"` + Source json.RawMessage `json:"source"` +} + +// blocksOf reads content that is a string or a list of blocks. +func blocksOf(c json.RawMessage) []rawBlock { + var s string + if json.Unmarshal(c, &s) == nil { + return []rawBlock{{Type: "text", Text: s}} + } + var bs []rawBlock + _ = json.Unmarshal(c, &bs) + return bs +} + +func (b *promptBuilder) anthropic(body []byte) bool { + var req struct { + System json.RawMessage `json:"system"` + Messages []struct { + Role string `json:"role"` + Content json.RawMessage `json:"content"` + } `json:"messages"` + Tools []json.RawMessage `json:"tools"` + } + if json.Unmarshal(body, &req) != nil { + return false + } + for _, s := range blocksOf(req.System) { + if strings.HasPrefix(s.Text, "x-anthropic-billing-header") { + b.add(PartSystem, "billing", "", tokensOf(s.Text)) + continue + } + b.systemText(s.Text, "prompt") + } + for _, t := range req.Tools { + var d struct { + Name string `json:"name"` + } + _ = json.Unmarshal(t, &d) + b.tool(d.Name, rawTokens(t)) + } + for _, m := range req.Messages { + bs := blocksOf(m.Content) + switch m.Role { + case "system", "developer": + for _, x := range bs { + b.systemText(x.Text, "harness") + } + continue + case "user": + // a message that answers tool calls goes on with the turn; + // one where the user says something begins one + results := slices.ContainsFunc(bs, func(x rawBlock) bool { return x.Type == "tool_result" }) + if !results && slices.ContainsFunc(bs, func(x rawBlock) bool { return x.Type == "text" && userSays(x.Text) }) { + b.newTurn() + } + } + for _, x := range bs { + b.anthropicBlock(m.Role, x) + } + } + return true +} + +// userSays tells what the user said from what the agent put in for them. +func userSays(text string) bool { + t := strings.TrimSpace(text) + return t != "" && !strings.HasPrefix(t, "") && !agentsFor.MatchString(t) && + !strings.HasPrefix(t, "") && !strings.HasPrefix(t, "") +} + +func (b *promptBuilder) anthropicBlock(role string, x rawBlock) { + switch x.Type { + case "text": + if role == "user" { + b.userText(x.Text) + } else { + b.chat(tokensOf(x.Text)) + } + case "thinking": + b.chat(tokensOf(x.Thinking)) + case "redacted_thinking": + b.chat(tokensOf(x.Data) / 4) + case "tool_use", "server_tool_use": + b.calls[x.ID] = callOf(x.Name, x.Input) + b.chat(tokensOf(x.Name) + rawTokens(x.Input)) + case "tool_result", "web_search_tool_result", "web_fetch_tool_result": + n := 0 + for _, c := range blocksOf(x.Content) { + switch c.Type { + case "image", "document": + b.add(PartFiles, c.Type, "image", imageTokens) + default: + n += tokensOf(c.Text) + } + } + if len(x.Content) > 0 && x.Content[0] != '"' && x.Content[0] != '[' { + n = rawTokens(x.Content) + } + b.result(x.ToolUseID, n) + case "image", "document": + if x.Type == "document" && len(x.Source) > 0 && !strings.Contains(string(x.Source), `"base64"`) { + b.add(PartFiles, "document", "image", rawTokens(x.Source)) + return + } + b.add(PartFiles, x.Type, "image", imageTokens) + default: + b.chat(tokensOf(x.Text)) + } +} + +// --- OpenAI Responses --- + +func (b *promptBuilder) responses(body []byte) bool { + var req struct { + Instructions json.RawMessage `json:"instructions"` + Input json.RawMessage `json:"input"` + Tools []json.RawMessage `json:"tools"` + Previous string `json:"previous_response_id"` + } + if json.Unmarshal(body, &req) != nil { + return false + } + b.held = req.Previous != "" + var ins string + if json.Unmarshal(req.Instructions, &ins) == nil && ins != "" { + b.systemText(ins, "prompt") + } + for _, t := range req.Tools { + b.responsesTool(t) + } + var s string + if json.Unmarshal(req.Input, &s) == nil { + b.newTurn() + b.userText(s) + return true + } + var items []json.RawMessage + _ = json.Unmarshal(req.Input, &items) + for _, it := range items { + b.responsesItem(it) + } + return true +} + +func (b *promptBuilder) responsesTool(t json.RawMessage) { + var d struct { + Type string `json:"type"` + Name string `json:"name"` + Tools []json.RawMessage `json:"tools"` + Function *struct { + Name string `json:"name"` + } `json:"function"` + } + _ = json.Unmarshal(t, &d) + name := d.Name + if name == "" && d.Function != nil { + name = d.Function.Name + } + if name == "" { + name = d.Type // web_search, image_generation… + } + if d.Type == "namespace" || len(d.Tools) > 0 { + // a namespace of tools: Codex's own functions one by one, any other + // as one, as an MCP server's + if name == "functions" { + for _, x := range d.Tools { + b.responsesTool(x) + } + return + } + // an MCP server's namespace is named as its tools are, mcp__…; + // Codex's own (clock, collaboration…) aren't MCP + tag := "namespace" + if rest, ok := strings.CutPrefix(name, "mcp__"); ok { + tag, name = "mcp", strings.TrimRight(strings.SplitN(rest, "__", 2)[0], "_") + } + b.add(PartTools, name, tag, rawTokens(t)) + if p := b.parts[PartTools][tag+"\x00"+name]; p != nil { + p.N += len(d.Tools) - 1 + } + return + } + b.tool(name, rawTokens(t)) +} + +func (b *promptBuilder) responsesItem(raw json.RawMessage) { + var it struct { + Type string `json:"type"` + Role string `json:"role"` + Content json.RawMessage `json:"content"` + CallID string `json:"call_id"` + Name string `json:"name"` + Arguments string `json:"arguments"` + Input string `json:"input"` + Output json.RawMessage `json:"output"` + Tools []json.RawMessage `json:"tools"` + Summary []struct { + Text string `json:"text"` + } `json:"summary"` + Encrypted string `json:"encrypted_content"` + Action json.RawMessage `json:"action"` + } + if json.Unmarshal(raw, &it) != nil { + return + } + if it.Type == "" && it.Role != "" { + it.Type = "message" + } + switch it.Type { + case "additional_tools": + for _, t := range it.Tools { + b.responsesTool(t) + } + case "message": + parts := responsesContent(it.Content) + switch it.Role { + case "system", "developer": + for _, p := range parts { + b.systemText(p.text, "prompt") + } + case "user": + if slices.ContainsFunc(parts, func(p rPart) bool { return p.image || userSays(p.text) }) { + b.newTurn() + } + for _, p := range parts { + if p.image { + b.add(PartFiles, "image", "image", imageTokens) + continue + } + b.userText(p.text) + } + default: + for _, p := range parts { + b.chat(tokensOf(p.text)) + } + } + case "reasoning": + n := 0 + for _, s := range it.Summary { + n += tokensOf(s.Text) + } + // the reasoning itself, sealed: about three quarters of its + // base64 is what was sealed + n += len(it.Encrypted) * 3 / 4 / 4 + b.chat(n) + case "function_call", "custom_tool_call", "local_shell_call", "tool_search_call": + input := []byte(it.Arguments) + if it.Type == "custom_tool_call" { + input = []byte(it.Input) + } + if it.Type == "local_shell_call" { + input = it.Action + } + b.calls[it.CallID] = callOf(it.Name, input) + b.chat(tokensOf(it.Name) + (len(input)+3)/4) + case "function_call_output", "custom_tool_call_output", "local_shell_call_output", "tool_search_output": + n := 0 + var s string + if json.Unmarshal(it.Output, &s) == nil { + n = tokensOf(s) + } else { + for _, p := range responsesContent(it.Output) { + if p.image { + b.add(PartFiles, "image", "image", imageTokens) + continue + } + n += tokensOf(p.text) + } + } + if it.Type == "tool_search_output" { + for _, t := range it.Tools { + b.responsesTool(t) + } + } + b.result(it.CallID, n) + case "compaction", "compaction_summary": + b.add(PartChat, "compacted", "compacted", rawTokens(raw)) + default: + b.chat(rawTokens(raw)) + } +} + +type rPart struct { + text string + image bool +} + +func responsesContent(c json.RawMessage) []rPart { + var s string + if json.Unmarshal(c, &s) == nil { + return []rPart{{text: s}} + } + var ps []struct { + Type string `json:"type"` + Text string `json:"text"` + } + _ = json.Unmarshal(c, &ps) + out := make([]rPart, 0, len(ps)) + for _, p := range ps { + out = append(out, rPart{text: p.Text, image: p.Type == "input_image" || p.Type == "input_file" || p.Type == "image_url"}) + } + return out +} + +// --- OpenAI Chat Completions --- + +func (b *promptBuilder) chatCompletions(body []byte) bool { + var req struct { + Messages []struct { + Role string `json:"role"` + Content json.RawMessage `json:"content"` + ToolCallID string `json:"tool_call_id"` + Reasoning string `json:"reasoning_content"` + ToolCalls []struct { + ID string `json:"id"` + Function struct { + Name string `json:"name"` + Arguments string `json:"arguments"` + } `json:"function"` + } `json:"tool_calls"` + } `json:"messages"` + Tools []json.RawMessage `json:"tools"` + } + if json.Unmarshal(body, &req) != nil { + return false + } + for _, t := range req.Tools { + b.responsesTool(t) + } + for _, m := range req.Messages { + parts := responsesContent(m.Content) + switch m.Role { + case "system", "developer": + for _, p := range parts { + b.systemText(p.text, "prompt") + } + case "user": + if slices.ContainsFunc(parts, func(p rPart) bool { return p.image || userSays(p.text) }) { + b.newTurn() + } + for _, p := range parts { + if p.image { + b.add(PartFiles, "image", "image", imageTokens) + continue + } + b.userText(p.text) + } + case "tool", "function": + n := 0 + for _, p := range parts { + if p.image { + b.add(PartFiles, "image", "image", imageTokens) + continue + } + n += tokensOf(p.text) + } + b.result(m.ToolCallID, n) + default: + n := tokensOf(m.Reasoning) + for _, p := range parts { + n += tokensOf(p.text) + } + for _, c := range m.ToolCalls { + b.calls[c.ID] = callOf(c.Function.Name, []byte(c.Function.Arguments)) + n += tokensOf(c.Function.Name) + tokensOf(c.Function.Arguments) + } + b.chat(n) + } + } + return true +} + +// --- Gemini --- + +func (b *promptBuilder) gemini(body []byte) bool { + type gPart struct { + Text string `json:"text"` + Thought bool `json:"thought"` + InlineData json.RawMessage `json:"inlineData"` + FileData json.RawMessage `json:"fileData"` + FunctionCall *struct { + ID string `json:"id"` + Name string `json:"name"` + Args json.RawMessage `json:"args"` + } `json:"functionCall"` + FunctionResponse *struct { + ID string `json:"id"` + Name string `json:"name"` + Response json.RawMessage `json:"response"` + } `json:"functionResponse"` + } + var req struct { + System *struct { + Parts []gPart `json:"parts"` + } `json:"systemInstruction"` + Contents []struct { + Role string `json:"role"` + Parts []gPart `json:"parts"` + } `json:"contents"` + Tools []struct { + Decls []json.RawMessage `json:"functionDeclarations"` + } `json:"tools"` + } + if json.Unmarshal(body, &req) != nil { + return false + } + if req.System != nil { + for _, p := range req.System.Parts { + b.systemText(p.Text, "prompt") + } + } + for _, t := range req.Tools { + for _, d := range t.Decls { + var n struct { + Name string `json:"name"` + } + _ = json.Unmarshal(d, &n) + b.tool(n.Name, rawTokens(d)) + } + } + for _, c := range req.Contents { + if c.Role != "model" && slices.ContainsFunc(c.Parts, func(p gPart) bool { return userSays(p.Text) && p.FunctionResponse == nil }) { + b.newTurn() + } + for _, p := range c.Parts { + switch { + case p.FunctionCall != nil: + // Gemini matches a response to its call by name, or id + id := p.FunctionCall.ID + if id == "" { + id = "name:" + p.FunctionCall.Name + } + b.calls[id] = callOf(p.FunctionCall.Name, p.FunctionCall.Args) + b.chat(tokensOf(p.FunctionCall.Name) + rawTokens(p.FunctionCall.Args)) + case p.FunctionResponse != nil: + id := p.FunctionResponse.ID + if id == "" { + id = "name:" + p.FunctionResponse.Name + } + if _, ok := b.calls[id]; !ok { + b.calls[id] = toolCall{name: p.FunctionResponse.Name} + } + b.result(id, rawTokens(p.FunctionResponse.Response)) + case len(p.InlineData) > 0 || len(p.FileData) > 0: + b.add(PartFiles, "image", "image", imageTokens) + case c.Role == "model": + b.chat(tokensOf(p.Text)) + default: + b.userText(p.Text) + } + } + } + return true +} + +// calibrated is the prompt scaled to what the vendor counted, as a copy: +// the trace hands out the one it holds to readers outside its lock. +func (p *Prompt) calibrated(counted, window int) *Prompt { + if p == nil { + return nil + } + c := *p + c.Parts = make([]PromptPart, len(p.Parts)) + for i, part := range p.Parts { + part.Items = append([]PromptItem(nil), part.Items...) + c.Parts[i] = part + } + c.calibrate(counted, window) + return &c +} + +// promptCounted is the prompt the vendor counted for the try that +// answered: the last billable one's input, read from its cache or not. +func promptCounted(us []RouteUsage) int { + if len(us) == 0 { + return 0 + } + u := us[len(us)-1] + return u.Input + u.CacheRead + u.CacheWrite +} + +// windowFor is the context window of a provider's model; 0 when unknown. +func windowFor(id, model string) int { + if id == "" || model == "" { + return 0 + } + p, err := provider.Find(id) + if err != nil || p == nil { + return 0 + } + return windowOf(*p, model) +} + +// inspectPrompt reads the request's prompt beside it, putting the estimate +// in the trace as soon as it is read; wait returns it, for the route's +// end to scale to what was counted. +func (s *Server) inspectPrompt(tr *Route, from provider.Protocol, body []byte) (wait func() *Prompt) { + ch := make(chan *Prompt, 1) + go func() { + p := promptOf(from, body) + if p != nil { + s.trace.update(tr, func(t *Route) { + if t.Prompt == nil { + t.Prompt = p + } + }) + } + ch <- p + }() + var p *Prompt + got := false + return func() *Prompt { + if !got { + p, got = <-ch, true + } + return p + } +} + +// convOf is the conversation of a request that names no session: a digest +// of its first user turn, the same from one request of it to the next. +func convOf(h http.Header, body []byte) string { + if sessionOf(h) != "" { + return "" + } + return conversationID(h, body) +} diff --git a/internal/gateway/prompt_test.go b/internal/gateway/prompt_test.go new file mode 100644 index 00000000..8dfc69b1 --- /dev/null +++ b/internal/gateway/prompt_test.go @@ -0,0 +1,286 @@ +package gateway + +import ( + "context" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "os" + "slices" + "strings" + "testing" + + "github.com/yetone/magpie/internal/provider" +) + +func fixturePrompt(t *testing.T, name string, from provider.Protocol) *Prompt { + t.Helper() + b, err := os.ReadFile("testdata/context/" + name) + if err != nil { + t.Fatal(err) + } + p := promptOf(from, b) + if p == nil { + t.Fatalf("%s: no prompt", name) + } + return p +} + +func partOf(p *Prompt, kind string) PromptPart { + for _, x := range p.Parts { + if x.Kind == kind { + return x + } + } + return PromptPart{} +} + +func itemOf(p *Prompt, kind, name string) (PromptItem, bool) { + for _, it := range partOf(p, kind).Items { + if it.Name == name { + return it, true + } + } + return PromptItem{}, false +} + +// A Claude Code request, as Claude Code 2.1 sends it (testdata, its text +// replaced with filler of the same length): the CLAUDE.md files in its +// first system-reminder are memory, whose they are told by how Claude Code +// describes them; an MCP server's tools are one item; the files Read read +// are files, by path; ls's output is Bash's; the harness's mid-conversation +// system messages are its own prompt. +func TestPromptOfClaudeCode(t *testing.T) { + p := fixturePrompt(t, "claude-code.json", provider.Anthropic) + var kinds []string + for _, x := range p.Parts { + kinds = append(kinds, x.Kind) + } + if !slices.Equal(kinds, []string{PartSystem, PartTools, PartMemory, PartFiles, PartResults, PartChat}) { + t.Fatalf("parts %v", kinds) + } + if it, ok := itemOf(p, PartMemory, "/home/dev/.claude/CLAUDE.md"); !ok || it.Tag != "user" { + t.Fatalf("user CLAUDE.md %+v", partOf(p, PartMemory)) + } + if it, ok := itemOf(p, PartMemory, "/home/dev/proj/CLAUDE.md"); !ok || it.Tag != "project" { + t.Fatalf("project CLAUDE.md %+v", partOf(p, PartMemory)) + } + if _, ok := itemOf(p, PartMemory, "reminders"); !ok { + t.Fatalf("the rest of the reminders %+v", partOf(p, PartMemory)) + } + if it, ok := itemOf(p, PartTools, "linear"); !ok || it.Tag != "mcp" || it.N != 3 { + t.Fatalf("linear's tools %+v", it) + } + if _, ok := itemOf(p, PartTools, "Bash"); !ok { + t.Fatal("Bash's definition") + } + for _, f := range []string{"/home/dev/proj/main.go", "/home/dev/proj/reconcile.go"} { + if it, ok := itemOf(p, PartFiles, f); !ok || it.Tag != "read" { + t.Fatalf("%s: %+v", f, partOf(p, PartFiles)) + } + } + if it, ok := itemOf(p, PartResults, "Bash"); !ok || it.Tag != "result" { + t.Fatalf("ls %+v", partOf(p, PartResults)) + } + if _, ok := itemOf(p, PartSystem, "environment"); !ok { + t.Fatalf("the # Environment system message %+v", partOf(p, PartSystem)) + } + if p.Turns != 1 || p.Counted || p.Held { + t.Fatalf("%+v", p) + } + sum := 0 + for _, x := range p.Parts { + sum += x.Tokens + } + if sum != p.Tokens || p.Tokens < 10000 { + t.Fatalf("tokens %d, parts %d", p.Tokens, sum) + } +} + +// A Codex request, as Codex 0.1xx sends ChatGPT's backend: its tools come +// in additional_tools, its own functions one by one and any other +// namespace as one; AGENTS.md comes as a user message; the skills list as +// a developer one; and exec's JavaScript reading files with cat reads them. +func TestPromptOfCodex(t *testing.T) { + p := fixturePrompt(t, "codex.json", provider.Responses) + if it, ok := itemOf(p, PartMemory, "/home/dev/proj/AGENTS.md"); !ok || it.Tag != "project" { + t.Fatalf("AGENTS.md %+v", partOf(p, PartMemory)) + } + if it, ok := itemOf(p, PartMemory, "skills"); !ok || it.Tag != "skills" { + t.Fatalf("skills %+v", partOf(p, PartMemory)) + } + if it, ok := itemOf(p, PartTools, "collaboration"); !ok || it.Tag != "namespace" || it.N < 2 { + t.Fatalf("collaboration %+v", partOf(p, PartTools)) + } + if _, ok := itemOf(p, PartTools, "exec"); !ok { + t.Fatalf("exec %+v", partOf(p, PartTools)) + } + for _, f := range []string{"main.go", "reconcile.go"} { + if it, ok := itemOf(p, PartFiles, f); !ok || it.Tag != "shell" { + t.Fatalf("%s: %+v", f, partOf(p, PartFiles)) + } + } + if _, ok := itemOf(p, PartSystem, "environment_context"); !ok { + t.Fatalf("environment %+v", partOf(p, PartSystem)) + } + if _, ok := itemOf(p, PartSystem, "prompt"); !ok { + t.Fatalf("Codex's own prompt %+v", partOf(p, PartSystem)) + } + if p.Turns != 1 { + t.Fatalf("turns %d", p.Turns) + } +} + +// Codex sends an MCP server's tools as a namespace named as its tools are, +// mcp____: that one is the server's, its own (clock…) aren't MCP. +func TestPromptOfCodexMCP(t *testing.T) { + body := `{"model":"gpt-5.5","input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"hi"}]}],"tools":[ + {"type":"namespace","name":"mcp__linear__","tools":[{"type":"function","name":"list_issues","description":"` + strings.Repeat("issues ", 200) + `"},{"type":"function","name":"get_issue","description":"one issue"}]}, + {"type":"namespace","name":"clock","tools":[{"type":"function","name":"sleep","description":"sleeps"}]}]}` + p := promptOf(provider.Responses, []byte(body)) + if it, ok := itemOf(p, PartTools, "linear"); !ok || it.Tag != "mcp" || it.N != 2 { + t.Fatalf("linear %+v", partOf(p, PartTools)) + } + if it, ok := itemOf(p, PartTools, "clock"); !ok || it.Tag != "namespace" { + t.Fatalf("clock %+v", partOf(p, PartTools)) + } +} + +// Chat Completions: a tool's answer goes by the name of the call it +// answers, a file it read by the file; a user's message begins a turn. +func TestPromptOfChat(t *testing.T) { + body := `{"model":"m","messages":[ + {"role":"system","content":"You are OpenCode.\nInstructions from: /p/AGENTS.md\nbe brief, always"}, + {"role":"user","content":"look at a.go"}, + {"role":"assistant","content":null,"tool_calls":[{"id":"c1","type":"function","function":{"name":"read","arguments":"{\"filePath\":\"/p/a.go\"}"}}, + {"id":"c2","type":"function","function":{"name":"bash","arguments":"{\"command\":\"go test ./...\"}"}}]}, + {"role":"tool","tool_call_id":"c1","content":"package a\nfunc A() {}"}, + {"role":"tool","tool_call_id":"c2","content":"ok a 0.1s"}, + {"role":"user","content":[{"type":"text","text":"and this"},{"type":"image_url","image_url":{"url":"data:image/png;base64,AAAA"}}]}], + "tools":[{"type":"function","function":{"name":"read","parameters":{}}},{"type":"function","function":{"name":"mcp__gh__issue","parameters":{}}}]}` + p := promptOf(provider.Chat, []byte(body)) + if p == nil || p.Turns != 2 { + t.Fatalf("%+v", p) + } + if it, ok := itemOf(p, PartMemory, "/p/AGENTS.md"); !ok || it.Tag != "project" { + t.Fatalf("OpenCode's instructions %+v", partOf(p, PartMemory)) + } + if _, ok := itemOf(p, PartFiles, "/p/a.go"); !ok { + t.Fatalf("files %+v", partOf(p, PartFiles)) + } + if it, ok := itemOf(p, PartFiles, "image"); !ok || it.Tokens != imageTokens { + t.Fatalf("image %+v", it) + } + if _, ok := itemOf(p, PartResults, "bash"); !ok { + t.Fatalf("results %+v", partOf(p, PartResults)) + } + if it, ok := itemOf(p, PartTools, "gh"); !ok || it.Tag != "mcp" { + t.Fatalf("tools %+v", partOf(p, PartTools)) + } +} + +// Gemini matches a function's response to its call by name. +func TestPromptOfGemini(t *testing.T) { + body := `{"systemInstruction":{"parts":[{"text":"You are Gemini CLI."}]}, + "contents":[{"role":"user","parts":[{"text":"read go.mod"}]}, + {"role":"model","parts":[{"functionCall":{"name":"read_file","args":{"path":"go.mod"}}}]}, + {"role":"user","parts":[{"functionResponse":{"name":"read_file","response":{"output":"module x"}}}]}], + "tools":[{"functionDeclarations":[{"name":"read_file","parameters":{}}]}]}` + p := promptOf(provider.Gemini, []byte(body)) + if p == nil || p.Turns != 1 { + t.Fatalf("%+v", p) + } + if _, ok := itemOf(p, PartFiles, "go.mod"); !ok { + t.Fatalf("files %+v", p.Parts) + } +} + +// A Responses request that names a previous response holds its earlier +// turns at the vendor's. +func TestPromptHeld(t *testing.T) { + p := promptOf(provider.Responses, []byte(`{"previous_response_id":"resp_1","input":[{"role":"user","content":"go on"}]}`)) + if p == nil || !p.Held || p.Turns != 1 { + t.Fatalf("%+v", p) + } + if promptOf(provider.Anthropic, []byte(`not json`)) != nil { + t.Fatal("a body that isn't one") + } +} + +// Calibrated, the parts add up to what the vendor counted, and the one the +// trace holds is left as it was. +func TestPromptCalibrated(t *testing.T) { + p := fixturePrompt(t, "claude-code.json", provider.Anthropic) + before, _ := json.Marshal(p) + c := p.calibrated(31337, 200000) + sum := 0 + for _, x := range c.Parts { + sum += x.Tokens + } + if !c.Counted || c.Tokens != 31337 || sum != 31337 || c.Window != 200000 { + t.Fatalf("%+v (sum %d)", c, sum) + } + if after, _ := json.Marshal(p); string(after) != string(before) { + t.Fatal("calibrating changed the estimate") + } + if again := c.calibrated(5, 0); again.Tokens != 31337 || again.Window != 200000 { + t.Fatalf("counted twice %+v", again) + } +} + +func TestFilesOfCommand(t *testing.T) { + for cmd, want := range map[string][]string{ + "cat main.go reconcile.go": {"main.go", "reconcile.go"}, + "sed -n 1,80p internal/x.go": {"internal/x.go"}, + "head -n 40 README.md": {"README.md"}, + `bash -lc "nl -ba a.go"`: {"a.go"}, + "cd /p && cat go.mod": {"go.mod"}, + "cat a.go | grep x": nil, + "go test ./...": nil, + "ls": nil, + } { + if got := filesOfCommand(cmd); !slices.Equal(got, want) { + t.Errorf("%q: %q, want %q", cmd, got, want) + } + } +} + +// Through the gateway: the route says what its prompt held, scaled to +// what the vendor counted, and the window of the model that answered. +func TestRouteTellsItsPrompt(t *testing.T) { + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + t.Setenv("XDG_CACHE_HOME", t.TempDir()) + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.Copy(io.Discard, r.Body) + w.Header().Set("Content-Type", "application/json") + io.WriteString(w, `{"id":"msg_1","type":"message","role":"assistant","model":"m1","content":[{"type":"text","text":"ok"}], + "stop_reason":"end_turn","usage":{"input_tokens":1200,"cache_read_input_tokens":40000,"cache_creation_input_tokens":800,"output_tokens":9}}`) + })) + defer srv.Close() + if err := provider.Save(provider.Provider{ID: "cw", Name: "CW", Anthropic: srv.URL, Models: []string{"m1"}, Key: "k", + Contexts: map[string]int{"m1": 200000}}); err != nil { + t.Fatal(err) + } + b, _ := os.ReadFile("testdata/context/claude-code.json") + var q map[string]any + json.Unmarshal(b, &q) + q["model"], q["stream"] = "cw/m1", false + b, _ = json.Marshal(q) + s := New() + s.Handler().ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("POST", "/v1/messages", strings.NewReader(string(b)))) + rs := s.Trace(context.Background(), 0, 0).Routes + if len(rs) != 1 || rs[0].Status != 200 { + t.Fatalf("%+v", rs) + } + p := rs[0].Prompt + if p == nil || !p.Counted || p.Tokens != 42000 || p.Window != 200000 { + t.Fatalf("prompt %+v", p) + } + if _, ok := itemOf(p, PartMemory, "/home/dev/proj/CLAUDE.md"); !ok { + t.Fatalf("memory %+v", p.Parts) + } + if rs[0].Conv == "" || !strings.HasPrefix(rs[0].Conv, "magpie-") { + t.Fatalf("conversation %q", rs[0].Conv) + } +} diff --git a/internal/gateway/testdata/context/claude-code.json b/internal/gateway/testdata/context/claude-code.json new file mode 100644 index 00000000..00917a5f --- /dev/null +++ b/internal/gateway/testdata/context/claude-code.json @@ -0,0 +1,1131 @@ +{ + "model": "claude-fable-5-1", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur \n\nContents of /home/dev/.claude/CLAUDE.md (user's private global instructions for all projects):\n\nlorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur \n\nlorem ipsum dolor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur a\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing el\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\n\nlorem ipsum dolor sit am\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\nlorem ipsum dolor sit amet consectetur adipiscing \n\nContents of /home/dev/proj/CLAUDE.md (project instructions, checked into the codebase):\n\n# ledger\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\n" + }, + { + "type": "text", + "text": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \n# userEmail\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet con\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s\n\n" + }, + { + "type": "text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu" + } + ] + }, + { + "role": "system", + "content": "# Environment\nlorem ipsum dolor sit amet consectetur adipiscing el\nlorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet co\nlorem ipsum dolor s\nlorem ipsum d\nlorem ipsum dolor sit amet c\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\n\nlorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\n\n# MCP Server Instructions\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\n\nlorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\n\nlorem ips\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do e\n\nlorem ipsum \nlorem ipsum dolor\nlorem ipsum \nlorem ipsum do\nlorem ipsum dolor sit \nlorem ipsum do\nlorem ipsum \nlorem ipsum dolor s\nlorem ipsum dolor sit \nlorem ipsum dolor\nlorem ipsum dolor sit\nlorem ipsum dol\nlorem ipsum \nlorem ipsum dolor sit amet\nlorem ipsum dolo\nlorem ipsum dolor sit amet \nlorem i\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet conse\nlorem ips\nlorem ipsum do\nlorem ipsum dolor\nlorem ipsum dolor\nlorem ipsum dolor\nlorem ipsum \nlorem ips\nlorem ipsum dolor sit amet con\nlorem ipsum d\nlorem ipsum dolor sit am\nlorem ipsum dolor si\nlorem ipsum\nlorem ipsum dolor si\nlorem ipsum do\nlorem ipsu\nlorem i\nlorem i\nlorem ipsum dol\nlorem ipsum d\nlorem ipsum dolor sit amet consectet\nlorem ipsum dol\nlorem ipsu\nlorem ipsum dolor\nlorem ipsum d\nlorem ipsum\nlorem ipsum d\nlorem ipsum \nlorem ipsum dolor\nlorem ipsum dolo\nlorem ipsum dolor si\nlorem ipsum dolo\nlorem \nlorem ips\nlorem ipsu\nlorem ipsum dolor sit amet\nlorem ipsum dolor sit ame\nlorem ipsum dolor sit am\nlorem ipsu\nlorem ipsum d\nlorem ip\nlorem ip\nlorem i\nlore\nlorem ipsum d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectet\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \nlorem \nlorem ipsum dolor\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet cons\nlorem ipsum dolor sit amet conse\nlorem ipsum dolor sit a\nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet conse\nlorem ipsum dolor sit amet\nlorem ipsum dolor sit \nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet conse\nlorem ipsum dolor sit a\n\nlorem ipsum dolor sit amet ", + "output_config": { + "effort": "high" + } + }, + { + "role": "assistant", + "content": [ + { + "type": "text", + "text": "I'll read both files and list the directory in parallel." + }, + { + "type": "tool_use", + "id": "toolu_01JNepVefG3fPanHE5anGavy", + "name": "Read", + "input": { + "file_path": "/home/dev/proj/main.go" + } + }, + { + "type": "tool_use", + "id": "toolu_01FoXbuXtdXQHTyVs6kCB1Fg", + "name": "Read", + "input": { + "file_path": "/home/dev/proj/reconcile.go" + } + }, + { + "type": "tool_use", + "id": "toolu_012f19D2H3vze3HDPudJNKFa", + "name": "Bash", + "input": { + "command": "ls /home/dev/proj", + "description": "List files in project directory" + }, + "cache_control": { + "type": "ephemeral", + "ttl": "1h" + } + } + ] + }, + { + "role": "user", + "content": [ + { + "tool_use_id": "toolu_01JNepVefG3fPanHE5anGavy", + "type": "tool_result", + "content": "lorem ipsum do\nlo\nlorem ipsum do\nlo\nlorem ipsum dolor sit amet consectetur adipiscing elit s\nlo" + }, + { + "tool_use_id": "toolu_01FoXbuXtdXQHTyVs6kCB1Fg", + "type": "tool_result", + "content": "lorem ipsum do\nlo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\nlorem ipsum dolor sit amet conse\nlorem ips\nlorem ipsum dolor sit ame\nlorem ipsu\nlore\nlorem ipsum\nlore\nlor" + }, + { + "tool_use_id": "toolu_012f19D2H3vze3HDPudJNKFa", + "type": "tool_result", + "content": "CLAUDE.md\nmain.go\nreconcile.go", + "is_error": false, + "cache_control": { + "type": "ephemeral", + "ttl": "1h" + } + } + ] + }, + { + "role": "system", + "content": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing" + } + ], + "system": [ + { + "type": "text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp" + }, + { + "type": "text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do ", + "cache_control": { + "type": "ephemeral", + "ttl": "1h" + } + }, + { + "type": "text", + "text": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp\n\n# Harness\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipis\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod\n\n# Session-specific guidance\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed\n\n# Memory\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor\n\nlorem ipsum\nlor\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ips\nlorem ipsum dolor sit amet consectetur adipis\nlor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\nlor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ip\n\n# Environment\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\n\n# Context management\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\n\n# Delivering work\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do e\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do \n\n# Writing for the user\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\n\nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ", + "cache_control": { + "type": "ephemeral", + "ttl": "1h" + } + } + ], + "tools": [ + { + "name": "Agent", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\n\nlorem ipsum do\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit a\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do e\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "description": { + "description": "A short (3-5 word) description of the task", + "type": "string" + }, + "prompt": { + "description": "The task for the agent to perform", + "type": "string" + }, + "subagent_type": { + "description": "The type of specialized agent to use for this task", + "type": "string" + }, + "model": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing ", + "type": "string", + "enum": [ + "sonnet", + "opus", + "haiku", + "fable" + ] + }, + "effort": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adip", + "type": "string", + "enum": [ + "low", + "medium", + "high", + "xhigh", + "max" + ] + }, + "run_in_background": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit ", + "type": "boolean" + }, + "isolation": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm", + "type": "string", + "enum": [ + "worktree", + "remote" + ] + } + }, + "required": [ + "description", + "prompt" + ], + "additionalProperties": false + } + }, + { + "name": "Bash", + "description": "lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do e\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\n\n# Git\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit ", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "command": { + "description": "The command to execute", + "type": "string" + }, + "timeout": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod ", + "type": "number" + }, + "description": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur a\nlorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipisc\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i", + "type": "string" + }, + "run_in_background": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet ", + "type": "boolean" + }, + "dangerouslyDisableSandbox": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d", + "type": "boolean" + } + }, + "required": [ + "command" + ], + "additionalProperties": false + } + }, + { + "name": "Edit", + "description": "lorem ipsum dolor sit amet consectetur adipi\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit s", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "file_path": { + "description": "The absolute path to the file to modify", + "type": "string" + }, + "old_string": { + "description": "The text to replace", + "type": "string" + }, + "new_string": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do e", + "type": "string" + }, + "replace_all": { + "description": "Replace all occurrences of old_string (default false)", + "default": false, + "type": "boolean" + } + }, + "required": [ + "file_path", + "old_string", + "new_string" + ], + "additionalProperties": false + } + }, + { + "name": "Grep", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing el\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit a\nlorem ipsum dolor sit amet consectetur adipiscing", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "pattern": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do", + "type": "string" + }, + "path": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor", + "type": "string" + }, + "glob": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor", + "type": "string" + }, + "output_mode": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol", + "type": "string", + "enum": [ + "content", + "files_with_matches", + "count" + ] + }, + "-B": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit ame", + "type": "number" + }, + "-A": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit am", + "type": "number" + }, + "-C": { + "description": "Alias for context.", + "type": "number" + }, + "context": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte", + "type": "number" + }, + "-n": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co", + "type": "boolean" + }, + "-i": { + "description": "Case insensitive search (rg -i)", + "type": "boolean" + }, + "-o": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consec", + "type": "boolean" + }, + "type": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing e", + "type": "string" + }, + "head_limit": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te", + "type": "number" + }, + "offset": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do e", + "type": "number" + }, + "multiline": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad", + "type": "boolean" + } + }, + "required": [ + "pattern" + ], + "additionalProperties": false + } + }, + { + "name": "Read", + "description": "lorem ipsum dolor sit amet consectetur \n\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectet\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur a\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ei\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "file_path": { + "description": "The absolute path to the file to read", + "type": "string" + }, + "offset": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol", + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "limit": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ", + "type": "integer", + "exclusiveMinimum": 0, + "maximum": 9007199254740991 + }, + "pages": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectet", + "type": "string" + } + }, + "required": [ + "file_path" + ], + "additionalProperties": false + } + }, + { + "name": "mcp__claude_ai_Claude_Docs__create", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor ", + "input_schema": { + "type": "object", + "properties": { + "object": { + "type": "string", + "enum": [ + "file", + "node", + "utterance", + "enum", + "blob" + ] + }, + "engine": { + "type": "string" + }, + "payload": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "container": { + "type": "object", + "properties": { + "kind": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "kind", + "id" + ] + }, + "verbose": { + "type": "boolean" + }, + "opId": { + "type": "string" + }, + "artifact": { + "type": "string" + } + }, + "required": [ + "object", + "payload" + ] + } + }, + { + "name": "mcp__claude_ai_Claude_Docs__read", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm", + "input_schema": { + "type": "object", + "properties": { + "ref": { + "type": "object", + "properties": { + "object": { + "type": "string", + "enum": [ + "project", + "file", + "node", + "utterance", + "enum", + "blob" + ] + }, + "id": { + "type": "string" + } + }, + "required": [ + "object", + "id" + ] + }, + "engine": { + "type": "string" + }, + "container": { + "type": "object", + "properties": { + "kind": { + "type": "string" + }, + "id": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "kind", + "id" + ] + }, + "payload": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "ref" + ] + } + }, + { + "name": "mcp__linear__get_issue", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c" + }, + "fields": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d", + "type": "array", + "items": { + "type": "string", + "enum": [ + "id", + "uuid", + "title", + "description", + "projectMilestone", + "priority", + "estimate", + "url", + "gitBranchName", + "createdAt", + "updatedAt", + "archivedAt", + "completedAt", + "startedAt", + "canceledAt", + "startedTriageAt", + "triagedAt", + "dueDate", + "slaStartedAt", + "slaMediumRiskAt", + "slaHighRiskAt", + "slaBreachesAt", + "slaType", + "status", + "statusType", + "labels", + "triageIntel", + "createdBy", + "createdById", + "assignee", + "assigneeId", + "delegate", + "delegateId", + "project", + "projectId", + "parentId", + "team", + "teamId", + "cycleId", + "attachments", + "documents", + "stateHistory", + "relations", + "customerNeeds", + "releases" + ] + } + }, + "includeRelations": { + "default": false, + "description": "Include blocking/related/duplicate relations", + "type": "boolean" + }, + "includeCustomerNeeds": { + "default": false, + "description": "Include associated customer needs", + "type": "boolean" + }, + "includeReleases": { + "default": false, + "description": "Include associated releases", + "type": "boolean" + } + }, + "required": [ + "id" + ], + "additionalProperties": false + } + }, + { + "name": "mcp__linear__list_issues", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "limit": { + "default": 50, + "description": "Max results (default 50, max 250)", + "type": "number", + "maximum": 250 + }, + "cursor": { + "description": "Next page cursor", + "type": "string" + }, + "orderBy": { + "default": "updatedAt", + "description": "Sort: createdAt | updatedAt", + "type": "string", + "enum": [ + "createdAt", + "updatedAt" + ] + }, + "query": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod", + "type": "string" + }, + "customView": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad", + "type": "string", + "minLength": 1 + }, + "team": { + "description": "Team name or ID", + "type": "string" + }, + "includeSubTeams": { + "default": false, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ", + "type": "boolean" + }, + "state": { + "description": "State type, name, or ID", + "type": "string" + }, + "cycle": { + "description": "Cycle name, number, or ID", + "type": "string" + }, + "label": { + "description": "Label name or ID", + "type": "string" + }, + "assignee": { + "description": "User ID, name, email, or \"me\"", + "type": [ + "string", + "null" + ] + }, + "creator": { + "description": "User ID, name, email, or \"me\"", + "type": "string" + }, + "delegate": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s", + "type": "string" + }, + "project": { + "description": "Project name, ID, identifier (e.g., P-ENG-123), or slug", + "type": "string" + }, + "release": { + "description": "Release ID or slug", + "type": "string" + }, + "priority": { + "description": "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low", + "type": "number" + }, + "parentId": { + "description": "Parent issue ID or identifier (e.g., LIN-123)", + "type": "string" + }, + "fields": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d", + "type": "array", + "items": { + "type": "string", + "enum": [ + "id", + "uuid", + "title", + "description", + "projectMilestone", + "priority", + "estimate", + "url", + "gitBranchName", + "createdAt", + "updatedAt", + "archivedAt", + "completedAt", + "startedAt", + "canceledAt", + "startedTriageAt", + "triagedAt", + "dueDate", + "slaStartedAt", + "slaMediumRiskAt", + "slaHighRiskAt", + "slaBreachesAt", + "slaType", + "status", + "statusType", + "labels", + "triageIntel", + "createdBy", + "createdById", + "assignee", + "assigneeId", + "delegate", + "delegateId", + "project", + "projectId", + "parentId", + "team", + "teamId", + "cycleId" + ] + } + }, + "createdAt": { + "description": "Created after: ISO-8601 date/duration (e.g., -P1D)", + "type": "string" + }, + "updatedAt": { + "description": "Updated after: ISO-8601 date/duration (e.g., -P1D)", + "type": "string" + }, + "triagedAt": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing ", + "type": "string" + }, + "includeArchived": { + "default": false, + "description": "Include archived items", + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + { + "name": "mcp__linear__save_issue", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod ", + "input_schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "id": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ", + "type": "string" + }, + "title": { + "description": "Issue title (required when creating, unless template is set)", + "type": "string" + }, + "description": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d", + "type": "string" + }, + "patch": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s", + "minItems": 1, + "maxItems": 50, + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "replace" + }, + "old_string": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius" + }, + "new_string": { + "type": "string", + "description": "Replacement text. Empty string deletes the match" + }, + "replace_all": { + "description": "Replace every occurrence instead of requiring a unique match", + "type": "boolean" + } + }, + "required": [ + "op", + "old_string", + "new_string" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "insert_before" + }, + "anchor": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te" + }, + "text": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo" + } + }, + "required": [ + "op", + "anchor", + "text" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "insert_after" + }, + "anchor": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t" + }, + "text": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp" + } + }, + "required": [ + "op", + "anchor", + "text" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "prepend" + }, + "text": { + "type": "string", + "minLength": 1, + "description": "Text to insert at the very start of the content" + } + }, + "required": [ + "op", + "text" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "append" + }, + "text": { + "type": "string", + "minLength": 1, + "description": "Text to insert at the very end of the content" + } + }, + "required": [ + "op", + "text" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "replace_range" + }, + "from": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod " + }, + "to": { + "type": "string", + "minLength": 1, + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si" + }, + "new_string": { + "type": "string", + "description": "Text replacing the range. Empty string deletes it" + } + }, + "required": [ + "op", + "from", + "to", + "new_string" + ] + } + ] + } + }, + "team": { + "description": "Team name or ID (required when creating)", + "type": "string" + }, + "template": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipis", + "type": "string" + }, + "cycle": { + "description": "Cycle name, number, or ID. Null to remove", + "type": [ + "string", + "null" + ] + }, + "milestone": { + "description": "Milestone name or ID", + "type": "string" + }, + "priority": { + "description": "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low", + "type": "number" + }, + "project": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t", + "type": [ + "string", + "null" + ] + }, + "state": { + "description": "State type, name, or ID", + "type": "string" + }, + "assignee": { + "description": "User ID, name, email, or \"me\". Null to remove", + "type": [ + "string", + "null" + ] + }, + "delegate": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te", + "type": [ + "string", + "null" + ] + }, + "labels": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c", + "type": "array", + "items": { + "type": "string" + } + }, + "addLabels": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu", + "type": "array", + "items": { + "type": "string" + } + }, + "removeLabels": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ips", + "type": "array", + "items": { + "type": "string" + } + }, + "dueDate": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius", + "type": [ + "string", + "null" + ] + }, + "slaBreachesAt": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ", + "anyOf": [ + { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + }, + { + "type": "null" + } + ] + }, + "slaType": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si", + "anyOf": [ + { + "type": "string", + "enum": [ + "all", + "onlyBusinessDays" + ] + }, + { + "type": "null" + } + ] + }, + "parentId": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do", + "type": [ + "string", + "null" + ] + }, + "estimate": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing", + "type": [ + "number", + "null" + ] + }, + "links": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ip", + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "title": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "url", + "title" + ] + } + }, + "setReleases": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s", + "type": "array", + "items": { + "type": "string" + } + }, + "addReleases": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor ", + "type": "array", + "items": { + "type": "string" + } + }, + "removeReleases": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp", + "type": "array", + "items": { + "type": "string" + } + }, + "blocks": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i", + "type": "array", + "items": { + "type": "string" + } + }, + "blockedBy": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ips", + "type": "array", + "items": { + "type": "string" + } + }, + "relatedTo": { + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor", + "type": "array", + "items": { + "type": "string" + } + }, + "duplicateOf": { + "description": "Duplicate of issue ID/identifier. Null to remove", + "type": [ + "string", + "null" + ] + }, + "removeBlocks": { + "description": "Issue IDs/identifiers to stop blocking", + "type": "array", + "items": { + "type": "string" + } + }, + "removeBlockedBy": { + "description": "Issue IDs/identifiers to remove as blockers of this issue", + "type": "array", + "items": { + "type": "string" + } + }, + "removeRelatedTo": { + "description": "Related issue IDs/identifiers to remove", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + } + ], + "max_tokens": 64000, + "thinking": { + "type": "adaptive", + "display": "omitted" + }, + "context_management": { + "edits": [ + { + "type": "clear_thinking_20251015", + "keep": "all" + } + ] + }, + "output_config": { + "effort": "high" + }, + "stream": true +} \ No newline at end of file diff --git a/internal/gateway/testdata/context/codex.json b/internal/gateway/testdata/context/codex.json new file mode 100644 index 00000000..fa8eb342 --- /dev/null +++ b/internal/gateway/testdata/context/codex.json @@ -0,0 +1,527 @@ +{ + "model": "gpt-6.1-sol", + "input": [ + { + "type": "additional_tools", + "id": "at_fd3d86d3-93ce-5c3a-bcc9-30719648dfdf", + "role": "developer", + "tools": [ + { + "type": "namespace", + "name": "functions", + "description": "", + "tools": [ + { + "type": "custom", + "name": "exec", + "description": "lorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectet\n\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet con\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed d\n\nlorem ipsum dolor\nlorem\nlorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor si\nlorem ipsum dolor si\nlorem ipsum dolor si\nlorem ipsum dolor sit am\nlo\nlorem ipsum d\nlorem ipsum do\nlorem ipsum dolor si\nlorem ipsum dolor s\nlorem ipsum dolor sit amet \nlo\nlorem ipsum dolor sit amet co\nlorem ipsum do\nlorem ipsum dolor si\nlorem ipsum dolor sit\nlorem ipsum dol\nlo\nlorem ipsum dolor sit amet co\nlorem ipsum do\nlorem ipsum dolor si\nlorem ipsum dolor sit\nlorem ipsum dol\nlo\nlorem ipsum dolor si\nlorem ipsum dol\nlorem ipsum dol\nlorem ipsum dolor sit amet c\nlorem ipsum dolor sit\nlo\nlorem ipsum dolor sit\nlorem ipsum dolo\nlorem ipsum dol\nlorem ipsum dolor s\nlorem ipsum dolor sit amet c\nlorem ipsum dolor sit\nlo\nlorem ipsum dolor sit\nlorem ipsum dolo\nlorem ipsum dol\nlorem ipsum dolor s\nlorem ipsum dolor sit amet c\nlorem ipsum dolor sit\nlo\nlorem ipsum dolor sit\nlorem ipsum dolor\nlorem ipsum dol\nlorem ipsum dolor\nlorem ipsum do\nlorem ipsum dolor sit a\nlorem ipsum dolor si\nlorem ipsum dolor sit amet c\nlorem ipsum dolo\nlorem ipsum dolor sit\nlorem ipsum dolor sit am\nlo\nlorem ipsum dolor sit ame\nlorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor sit amet c\nlorem ipsum dolor sit\nlo\nlorem ipsum dolor s\nlorem ipsum dol\nlorem ipsum dolo\nlorem ipsum dolo\nlorem ipsum dolo\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consect\nlorem ipsum dolor sit ame\nlo\nlor\n\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet cons\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlor\n\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit am\nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adip\nlorem ipsum dolor sit amet con\nlorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\nlorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ip\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\nlorem ipsum dolor sit amet con\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum\nlorem ipsum dolor sit ame\nlorem ipsum d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit\nlorem ipsum dolor sit amet conse\nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet c\nlorem \nlor\n\nlorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipis\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do e\nlor\n\nlorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolo\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \nlorem ipsum dolor \nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp\nlorem ipsum dolor \nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum do\nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolor sit amet c\n# Suggest a recommended plugin installation\n\nlorem ipsum dolor sit amet consectetur adipiscing elit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing e\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet cons\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do \n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum do\nlorem ipsum dolor sit ame\nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolor\nlorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet con\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm\nlorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit am\nlor\n\nlorem ipsum dolo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \nlorem ipsum dolor sit amet cons\nlorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dol\nlorem ipsum d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit amet con\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor si\nlorem \nlor\n\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing el\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor sit ame\nlorem ipsum d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit\nlorem ipsum dolor sit amet conse\nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet c\nlorem \nlor\n\nlorem ip\nlorem ipsum dolor sit amet consectetur\n\nlorem ipsum dolor sit \nlorem ipsum dolor sit amet cons\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit a\nlorem \nlor\n\nlorem ipsum \nlorem ipsum dolor sit amet consec\n\nlorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\n\nlorem ipsum\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \n\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur adipiscing \nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit am\nlor\n\nlorem \nlorem ipsum dolor sit amet \n\nlorem ipsum do\nlorem ipsum dolor sit amet conse\n\n\nlor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit s\n\nlorem ipsum dolor sit amet consectetur adipiscing elit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipi\n\nlor\n\nlorem ipsum do\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adip\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\n\nlor\n\nlorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm\n\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\n\n\nlor\n\nlorem ipsum \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ips\n\nlorem ipsum dolor sit amet consectetur adipiscing elit s\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ips\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit ame\n\nlorem ipsum dolor sit am\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectet\n\nlor\n\nlorem ipsum dolo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor\n\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\n\n\nlor\n\nlorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s\nlorem ipsum dolor sit amet cons\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\n\n\nlorem ipsum dolor sit \nlorem\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor\nlorem ipsum dolor sit amet con\nlorem ipsum d\nlorem ipsum dolor sit amet consectetur adipisci\nlorem ipsum dolor\nlor\nlorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor \nlorem ipsum dolor sit amet con\nlorem ipsum dolor\nlorem ipsum dolor sit amet \nlorem ipsum dolor sit amet consectetur adipisci\nlor\nlorem ipsum dolor sit amet consec\nlorem ipsum dolo\nlorem ipsum dolor sit amet\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor\nlor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do e\nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet\nlorem ipsum dolor \nlorem ipsum \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do \nlorem ipsum dolor s\nlor\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolo\nlorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor \nlorem ipsum dolor sit amet consec\nlorem ipsum dolor\nlor\nlorem ipsum dolor sit amet consectetur adipiscing e\nlorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit \nlorem ipsum dolor sit amet consect\nlorem ipsum dolor\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor\nlor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet\nlorem ipsum dolor \nlorem ipsum \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do \nlorem ipsum dolor s\nlor\nlorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor \nlorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor s\nlorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet cons\nlorem ipsum dolor sit a\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu\nlorem ipsum dolor sit amet \nlorem ipsum dolor \nlorem ipsum dolor sit amet cons\nlorem ipsum dolor sit\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolo\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor \nlor\nlorem ipsum dolor sit amet consectetur a\nlorem ipsum dolo\nlorem ipsum dolor sit amet consectetur a\nlorem ipsum dolor sit\nlor\nlorem ipsum dolor sit amet cons\nlorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipisc\nlorem ipsum dolor s\nlorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor\nlor\nlorem ipsum dolor sit am\nlor", + "format": { + "type": "grammar", + "syntax": "lark", + "definition": "\nstart: pragma_source | plain_source\npragma_source: PRAGMA_LINE NEWLINE SOURCE\nplain_source: SOURCE\n\nPRAGMA_LINE: /[ \\t]*\\/\\/ @exec:[^\\r\\n]*/\nNEWLINE: /\\r?\\n/\nSOURCE: /[\\s\\S]+/\n" + } + }, + { + "type": "function", + "name": "wait", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "cell_id": { + "type": "string", + "description": "Identifier of the running exec cell." + }, + "max_tokens": { + "type": "number", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu" + }, + "terminate": { + "type": "boolean", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo" + }, + "yield_time_ms": { + "type": "number", + "description": "Wait before yielding more output. Defaults to 10000 ms." + } + }, + "required": [ + "cell_id" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "request_user_input", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adip", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "questions": { + "type": "array", + "description": "Questions to show the user. Prefer 1 and do not exceed 3", + "items": { + "type": "object", + "properties": { + "header": { + "type": "string", + "description": "Short header label shown in the UI (12 or fewer chars)." + }, + "id": { + "type": "string", + "description": "Stable identifier for mapping answers (snake_case)." + }, + "options": { + "type": "array", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod ", + "items": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "One short sentence explaining impact/tradeoff if selected." + }, + "label": { + "type": "string", + "description": "User-facing label (1-5 words)." + } + }, + "required": [ + "label", + "description" + ], + "additionalProperties": false + } + }, + "question": { + "type": "string", + "description": "Single-sentence prompt shown to the user." + } + }, + "required": [ + "id", + "header", + "question", + "options" + ], + "additionalProperties": false + } + } + }, + "required": [ + "questions" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "request_user_input_async", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "questions": { + "type": "array", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo", + "items": { + "type": "object", + "properties": { + "options": { + "type": "array", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolo", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "title": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem " + } + }, + "required": [ + "title" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "questions" + ], + "additionalProperties": false + } + } + ] + }, + { + "type": "namespace", + "name": "clock", + "description": "Tools for reading and waiting on time.", + "tools": [ + { + "type": "function", + "name": "sleep", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "duration_ms": { + "type": "number", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius" + } + }, + "required": [ + "duration_ms" + ], + "additionalProperties": false + } + } + ] + }, + { + "type": "namespace", + "name": "collaboration", + "description": "Tools for spawning and managing sub-agents.", + "tools": [ + { + "type": "function", + "name": "followup_task", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor l", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message text to send to the target agent.", + "encrypted": true + }, + "target": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo" + } + }, + "required": [ + "target", + "message" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "interrupt_agent", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed ", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "target": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do ei" + } + }, + "required": [ + "target" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "list_agents", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "path_prefix": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo" + } + }, + "additionalProperties": false + } + }, + { + "type": "function", + "name": "send_message", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Message text to queue on the target agent.", + "encrypted": true + }, + "target": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do " + } + }, + "required": [ + "target", + "message" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "spawn_agent", + "description": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "fork_turns": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t" + }, + "message": { + "type": "string", + "description": "Initial plain-text task for the new agent.", + "encrypted": true + }, + "model": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor " + }, + "reasoning_effort": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo" + }, + "task_name": { + "type": "string", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor" + } + }, + "required": [ + "task_name", + "message" + ], + "additionalProperties": false + } + }, + { + "type": "function", + "name": "wait_agent", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "timeout_ms": { + "type": "number", + "description": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm" + } + }, + "additionalProperties": false + } + } + ] + } + ] + }, + { + "type": "message", + "id": "msg_65f2d68b-9dd2-5b1a-9e9e-84456c726485", + "role": "developer", + "content": [ + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\n\n# When to ask the user for permission\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing el\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do \n\n# Autonomy and persistence\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ei\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusm\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet cons\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \n\n# Personality\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c\n\nlorem ipsum dolo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet con\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor s\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consec\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\n\nlorem ipsum dolor sit amet\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\n\nlorem ipsum dolor sit amet \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\n\n# Working with the user\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do ei\nlorem ipsum dolor sit amet consectetur adipiscin\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscin\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \n\nlorem ipsum dolor sit amet\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consecte\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed\n\nlorem ipsum dol\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\n\nlorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\n\nlorem ipsum dolor sit amet consectetur adipisci\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adip\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ip\n\nlorem ipsum dolor \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit ame\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet conse\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisci\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do e\n\n# Rules for getting work done\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipisc\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ip\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit am\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ei\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\n\n# Using skills\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet cons\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet conse\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod temp\n\nlorem ipsum dolor sit \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\n\nlorem ipsum dolor si\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiu\n\n# Apps (Connectors)\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit s\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do ei\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem i\n\n# Plugins\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed d\n\nlorem ipsum dolor sit\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eius\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsu\n\n" + } + ], + "internal_chat_message_metadata_passthrough": { + "content_item_kinds": [ + "model.base_instructions" + ] + } + }, + { + "type": "message", + "id": "msg_01a1179d-34a3-7cb1-b23c-fa807225131e", + "role": "developer", + "content": [ + { + "type": "input_text", + "text": "\nlorem ips\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet con\nlorem ipsum dol\nlorem ipsum dolor sit amet consecte\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod te\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lore\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ips\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consect\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod t\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do e\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet cons\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit ame\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed d\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipis\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dol\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectet\n" + }, + { + "type": "input_text", + "text": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\n" + }, + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet conse\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum d\n\nlorem ipsum dolor sit amet consect\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing e\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing e\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit\n" + }, + { + "type": "input_text", + "text": "\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do e\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod \nlorem ipsum dolor sit amet consec\nlorem ipsum dolor sit amet consectetur adipiscing elit \nlorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetur adip\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetur adipiscing elit se\nlorem ipsum dolor sit amet consectetur adipiscing e\nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectetur \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do\nlorem ipsum dolor sit amet consectetur adipiscing elit sed \nlorem ipsum dolor sit amet consectetur adipiscing eli\nlorem ipsum dolor sit amet consectetur adipisci\nlorem ipsum dolor sit amet consectetu\nlorem ipsum dolor sit amet consectetu\n" + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397541.027822, + "content_item_kinds": [ + "host_skills.instructions", + "permissions.instructions", + "collaboration_mode.instructions", + "plugins.recommendations" + ] + } + }, + { + "type": "message", + "id": "msg_01a1179d-34a3-7cb1-b23c-fa9ee963c199", + "role": "developer", + "content": [ + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur\n\nlorem ipsum dolor sit amet consectetur adipiscing el\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing \nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing \nlorem ipsum dolor sit amet consectetur adipiscing\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet c\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do \nlor\nlorem ipsum dolor sit amet consectet\nlorem ipsum dolor sit \nlorem ipsum dolo\nlorem ip\n\nlor\nlorem ipsum dolor sit amet consec\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adi\n\nlorem ipsum dolor sit amet consectetur adipisci\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod\nlorem ipsum dolor sit amet consectetur adipiscing el\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem \n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lo\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet co\n\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing " + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397541.027822, + "content_item_kinds": [ + "multi_agent.role_instructions" + ] + } + }, + { + "type": "message", + "id": "msg_01a1179d-34a3-7cb1-b23c-faaa76c53fb7", + "role": "developer", + "content": [ + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur a" + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397541.027823, + "content_item_kinds": [ + "multi_agent.mode_instructions" + ] + } + }, + { + "type": "message", + "id": "msg_01a1179d-34a3-7cb1-b23c-fabfd8b52251", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "# AGENTS.md instructions for /home/dev/proj\n\n\n# ledger\nlorem ipsum dolor sit amet consectetur adipiscing\n\n" + }, + { + "type": "input_text", + "text": "\nlorem ipsum dolor sit amet \nlorem ipsum dolor si\nlorem ipsum dolor sit amet consectetur ad\nlorem ipsum dolor sit amet consectet\nlorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum \n" + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397541.027823, + "content_item_kinds": [ + "agents_md.instructions", + "environments.environment_context" + ] + } + }, + { + "type": "message", + "id": "msg_01a1179d-34b9-7533-92c0-a5b358d2cca5", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor" + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397541.049139, + "content_item_kinds": [ + "user.text" + ] + } + }, + { + "type": "message", + "id": "msg_00f7990330b08aa5016ac68eb801a081918c22be6b703f6e0c", + "role": "assistant", + "content": [ + { + "type": "output_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tem" + } + ], + "phase": "commentary", + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397560.0169764, + "content_item_kinds": [ + "unknown" + ] + } + }, + { + "type": "custom_tool_call", + "id": "ctc_00f7990330b08aa5016ac68eb8813c81919d5717e37af30804", + "status": "completed", + "call_id": "call_f9b38b8832494d37a213abde58ee8af2", + "name": "exec", + "input": "text(await tools.exec_command({cmd:\"cat main.go reconcile.go\",max_output_tokens:8000}));\n", + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397560.5094378 + } + }, + { + "type": "custom_tool_call_output", + "id": "ctco_01a1179d-8c8f-7521-b8f4-32635917b555", + "call_id": "call_f9b38b8832494d37a213abde58ee8af2", + "output": [ + { + "type": "input_text", + "text": "Script completed\nWall time 0.1 seconds\nOutput:\n" + }, + { + "type": "input_text", + "text": "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempo" + } + ], + "internal_chat_message_metadata_passthrough": { + "turn_id": "01a1179d-1e8a-7302-b05b-64d89e8f60d3", + "create_time": 1791397563.535103 + } + } + ], + "tool_choice": "auto", + "parallel_tool_calls": false, + "reasoning": { + "effort": "low", + "context": "all_turns" + }, + "store": false, + "stream": true, + "include": [ + "reasoning.encrypted_content" + ], + "text": { + "verbosity": "low" + } +} \ No newline at end of file diff --git a/internal/gateway/trace.go b/internal/gateway/trace.go index 7f559aed..8ebaf381 100644 --- a/internal/gateway/trace.go +++ b/internal/gateway/trace.go @@ -75,6 +75,12 @@ type Route struct { Routed bool `json:"routed,omitempty"` // Upstream: the provider an aggregator said answered behind it Upstream string `json:"upstream,omitempty"` + // Prompt: what the prompt held, part by part, and the window it went + // into (prompt.go) + Prompt *Prompt `json:"prompt,omitempty"` + // Conv: the conversation a request without a session id is part of, + // as a digest of its first user turn (conversationID) + Conv string `json:"conv,omitempty"` } // RouteUsage is one billable attempt's pricing inputs, kept in routing history. diff --git a/internal/gui/assets/app.js b/internal/gui/assets/app.js index 1ef7121d..930c32a6 100644 --- a/internal/gui/assets/app.js +++ b/internal/gui/assets/app.js @@ -12356,6 +12356,7 @@ async function loadUsage(asked) { if (asked) loadQuotas(true); if (usageTab === "sessions") return loadSessions(); if (usageTab === "requests") return loadLedger(); + if (usageTab === "context") return window.loadContext(); renderUsageLoading(); if (!asked) loadQuotas(); const p = period, read = ++usageRead; @@ -15751,7 +15752,7 @@ function renderLedger() { // The agents' own sessions, read from their session files: what each cost, // and the command that picks it up again. A segment of the Usage page. -const USAGE_TABS = [["usage", "Overview"], ["requests", "Requests"], ["sessions", "Sessions"]]; +const USAGE_TABS = [["usage", "Overview"], ["requests", "Requests"], ["sessions", "Sessions"], ["context", "Context"]]; let usageTab = "usage"; let quotaFocus = ""; // pending provider/account card requested by the menu bar let quotaFocusUntil = 0; // expire before a late quota response can move the reader @@ -15821,11 +15822,13 @@ function renderUsageTab() { } slide(seg, "usageTab"); const on = usageTab === "sessions"; - $("#period").hidden = on; + // the Context tab has its own range, in its pane + $("#period").hidden = on || usageTab === "context"; $("#sessRange").hidden = !on; $("#usagePane").hidden = usageTab !== "usage"; $("#ledgerPane").hidden = usageTab !== "requests"; $("#sessionsPane").hidden = !on; + $("#contextPane").hidden = usageTab !== "context"; } const sessDays = () => SESS_RANGES.find(([id]) => id === sessRange)[2]; @@ -20090,6 +20093,8 @@ function refreshUsage(now = false) { } else if (usageTab === "requests") { // the newest page takes the requests as they come; an older one stays put if (ledger && (want || !ledOffset)) await loadLedger(true); + } else if (usageTab === "context") { + await window.loadContext(); } else { // the reader asking reads the allowances afresh, a Claude account's by // running Claude Code's own /usage (the backend runs it at most once in 30s) diff --git a/internal/gui/assets/context.css b/internal/gui/assets/context.css new file mode 100644 index 00000000..285c046a --- /dev/null +++ b/internal/gui/assets/context.css @@ -0,0 +1,217 @@ +/* Context windows: a request's prompt as a card (Routing, the Usage page's + Context tab) and each agent's score and tags. */ +:root { + --k-system: var(--c6); --k-tools: var(--c2); --k-memory: var(--c4); + --k-files: var(--c3); --k-results: var(--c5); --k-chat: var(--c1); + --k-free: color-mix(in srgb, var(--fg) 7%, transparent); +} +.k-system { --k: var(--k-system); } +.k-tools { --k: var(--k-tools); } +.k-memory { --k: var(--k-memory); } +.k-files { --k: var(--k-files); } +.k-results { --k: var(--k-results); } +.k-chat { --k: var(--k-chat); } +i.dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 2.5px; background: var(--k); } +i.dot.free { background: var(--k-free); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg) 10%, transparent); } + +.ctx-card { position: relative; container-type: inline-size; background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 14px; min-width: 0; font-variant-numeric: tabular-nums; } +.ctx-head { display: flex; align-items: center; gap: 8px; min-width: 0; } +.ctx-head .grow, .ctx-foot .grow, .ctx-contents-head .grow, .ctx-agent-head .grow, .ctx-agent-foot .grow, .ctx-tools .grow, .ctx-sess-head .grow { flex: 1; } +.ctx-title { font-size: 13px; font-weight: 600; color: var(--fg); white-space: nowrap; } +.ctx-model { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--code-font, var(--code)); font-size: 11px; color: var(--muted); } +.ctx-state { display: inline-flex; align-items: center; gap: 5px; flex: none; height: 20px; padding: 0 8px; border-radius: 10px; font-size: 11px; font-weight: 500; background: var(--pill); color: var(--fg-2); } +.ctx-state i { width: 6px; height: 6px; border-radius: 50%; background: var(--faint); } +.ctx-state.counted i { background: var(--green); } +.ctx-state.live { background: var(--green-soft); color: var(--green); } +.ctx-state.live i { background: var(--green); animation: ctx-pulse 1.4s ease-in-out infinite; } +@keyframes ctx-pulse { 50% { opacity: .35; transform: scale(.8); } } + +.ctx-k { display: flex; align-items: center; gap: 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); white-space: nowrap; } +:root[lang="zh"] .ctx-k, :root[lang="ja"] .ctx-k { letter-spacing: .02em; } +.ctx-top { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 12px 28px; } +.ctx-top > :only-child { grid-column: 1 / -1; } +.ctx-stat { display: flex; flex-direction: column; gap: 4px; min-width: 0; } +.ctx-big { display: flex; align-items: baseline; gap: 0; white-space: nowrap; color: var(--muted); font-size: 13px; } +.ctx-big b { font-size: 28px; line-height: 1.1; font-weight: 600; letter-spacing: -.02em; color: var(--fg); } +.ctx-sub { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +:root[lang="zh"] .ctx-sub, :root[lang="ja"] .ctx-sub { letter-spacing: .02em; } +.ctx-health { height: 17px; display: inline-flex; align-items: center; padding: 0 7px; border-radius: 9px; font-size: 10px; letter-spacing: .03em; } +.ctx-health.ok { background: var(--green-soft); color: var(--green); } +.ctx-health.warn { background: var(--amber-soft); color: var(--amber); } +.ctx-health.bad { background: var(--red-soft); color: var(--red); } +.ctx-bar { position: relative; display: block; height: 6px; border-radius: 3px; background: var(--k-free); overflow: hidden; } +.ctx-bar i { position: absolute; inset: 0 auto 0 0; border-radius: 3px; background: var(--green); transform-origin: left; animation: ctx-grow .7s var(--ease, ease) both; } +.ctx-cache .ctx-bar { margin: 3px 0 2px; } +@keyframes ctx-grow { from { transform: scaleX(0); } } + +/* the window, a cell for each 1/400 of it */ +.ctx-waffle { display: grid; grid-template-columns: repeat(50, minmax(0, 1fr)); gap: 2px; } +@container (max-width: 520px) { .ctx-waffle { grid-template-columns: repeat(25, minmax(0, 1fr)); } } +.ctx-waffle > i { aspect-ratio: 1; border-radius: 2px; background: var(--k, var(--k-free)); transition: opacity .16s, transform .16s; animation: ctx-cell .32s var(--ease, ease) both; animation-delay: var(--d, 0ms); } +.ctx-waffle > i.free { --k: var(--k-free); } +@keyframes ctx-cell { from { opacity: 0; transform: scale(.4); } } +.ctx-waffle[data-f] > i { opacity: .16; } +.ctx-waffle[data-f="system"] > i.k-system, .ctx-waffle[data-f="tools"] > i.k-tools, +.ctx-waffle[data-f="memory"] > i.k-memory, .ctx-waffle[data-f="files"] > i.k-files, +.ctx-waffle[data-f="results"] > i.k-results, .ctx-waffle[data-f="chat"] > i.k-chat, +.ctx-waffle[data-f="free"] > i.free, .ctx-waffle[data-f="item"] > i.on { opacity: 1; } +.ctx-waffle[data-f="item"] > i.on { transform: scale(1.12); } +.ctx-tip { position: absolute; z-index: 5; min-width: 190px; max-width: 280px; padding: 8px 10px; border-radius: 9px; background: #17171b; color: #ededf1; box-shadow: 0 10px 30px rgba(0, 0, 0, .28); font-size: 11.5px; pointer-events: none; display: flex; flex-direction: column; gap: 3px; } +.ctx-tip[hidden] { display: none; } +.ctx-tip-head { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; } +.ctx-tip-head .grow { flex: 1; } +.ctx-tip-head span:last-child { color: #a1a1aa; } +.ctx-tip-row { display: flex; gap: 10px; color: #b9b9c1; } +.ctx-tip-row .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.ctx-tip-row.on { color: #fff; font-weight: 500; } +.ctx-tip-more { color: #85858d; font-size: 10.5px; } + +.ctx-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: -4px; } +.ctx-leg { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--fg-2); cursor: default; padding: 2px 0; } +.ctx-leg .v { color: var(--muted); } +.ctx-leg:hover .n { color: var(--fg); } + +.ctx-contents { display: flex; flex-direction: column; gap: 6px; padding-top: 12px; border-top: 1px solid var(--line); } +.ctx-contents-head { display: flex; align-items: center; gap: 10px; min-width: 0; } +.ctx-contents-head .segs { max-width: 100%; overflow-x: auto; scrollbar-width: none; flex: none; } +.ctx-contents-head .segs .opt { height: 20px; padding: 0 9px; font-size: 11px; white-space: nowrap; flex: none; } +@container (max-width: 520px) { .ctx-contents-head { flex-wrap: wrap; } .ctx-contents-head .segs { flex: 1 1 100%; } } +.ctx-rows { display: flex; flex-direction: column; } +.ctx-row { display: flex; align-items: center; gap: 8px; min-height: 26px; padding: 0 6px; margin: 0 -6px; border-radius: 6px; font-size: 12px; } +.ctx-row:hover { background: var(--pill); } +.ctx-name { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 6px; overflow: hidden; white-space: nowrap; } +.ctx-name b { font-weight: 500; color: var(--fg); overflow: hidden; text-overflow: ellipsis; flex: none; max-width: 100%; } +.ctx-name small { color: var(--faint); font-size: 11px; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; min-width: 0; } +.ctx-x { font-size: 11px; color: var(--muted); } +.ctx-tag { flex: none; font-family: var(--code-font, var(--code)); font-size: 10px; padding: 1px 5px; border-radius: 4px; background: var(--pill); color: var(--muted); } +.ctx-mini { flex: none; width: 72px; height: 4px; border-radius: 2px; background: var(--k-free); overflow: hidden; } +.ctx-mini i { display: block; height: 100%; border-radius: 2px; background: var(--k); } +.ctx-v { flex: none; width: 48px; text-align: right; color: var(--fg-2); font-size: 11.5px; } +@container (max-width: 420px) { .ctx-mini, .ctx-tag { display: none; } } +.ctx-empty { font-size: 12px; color: var(--muted); padding: 4px 0; } +.ctx-more { align-self: flex-start; margin-top: 2px; font-size: 11.5px; } + +.ctx-foot { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 11px; color: var(--muted); } +.ctx-crumbs { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--code-font, var(--code)); font-size: 10.5px; color: var(--muted); } +.ctx-note { white-space: nowrap; flex: none; } +.ctx-session { display: flex; align-items: center; gap: 12px; margin-top: -4px; } +.ctx-session .ctx-spark { flex: 1; height: 34px; } +.ctx-spark { position: relative; display: block; width: 100%; } +.ctx-spark svg { display: block; width: 100%; height: 100%; overflow: visible; } +.ctx-spark .at { position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%; background: var(--card); border: 1.6px solid var(--k-chat); box-sizing: border-box; pointer-events: none; } +.ctx-spark .win { stroke: var(--line); stroke-dasharray: 3 3; stroke-width: 1; vector-effect: non-scaling-stroke; } +.ctx-spark .area { fill: color-mix(in srgb, var(--k-chat) 14%, transparent); } +.ctx-spark .line { fill: none; stroke: var(--k-chat); stroke-width: 1.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; } +.ctx-spark .hit { fill: transparent; cursor: pointer; } +.ctx-spark .hit:hover { fill: color-mix(in srgb, var(--fg) 7%, transparent); } + +/* Routing: the card under the story of the request */ +.rt-log .ctx-card { margin-top: 12px; } + +/* the Usage page's Context tab */ +.ctx-agents { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 12px; margin: 4px 0 18px; } +.ctx-agent { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 12px; min-width: 0; font-variant-numeric: tabular-nums; } +.ctx-agent-head { display: flex; align-items: center; gap: 10px; min-width: 0; } +.ctx-who-box { min-width: 0; display: flex; flex-direction: column; gap: 3px; } +.ctx-who { display: flex; align-items: center; gap: 8px; min-width: 0; } +.ctx-who .ic { width: 20px; height: 20px; flex: none; } +.ctx-who b { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.ctx-who-sub { font-size: 11px; color: var(--muted); } +.ctx-grade { display: flex; flex-direction: column; align-items: center; gap: 2px; flex: none; } +.ctx-grade-word { font-size: 10.5px; font-weight: 600; } +.ctx-ring { position: relative; width: 52px; height: 52px; --tone: var(--accent); } +.ctx-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); } +.ctx-ring circle { fill: none; stroke-width: 5; stroke-linecap: round; } +.ctx-ring .track { stroke: var(--k-free); } +.ctx-ring .arc { stroke: var(--tone); stroke-dashoffset: var(--to); animation: ctx-arc .9s var(--ease, ease) both; } +.ctx-pane.still .ctx-waffle > i, .ctx-pane.still .ctx-bar i, .ctx-pane.still .ctx-ring .arc { animation: none; } +@keyframes ctx-arc { from { stroke-dashoffset: 163.36; } } +.ctx-ring b { position: absolute; inset: 0; display: grid; place-items: center; font-size: 16px; font-weight: 650; letter-spacing: -.02em; } +.ctx-ring.great, .ctx-grade-word.great { --tone: var(--green); color: var(--green); } +.ctx-ring.good, .ctx-grade-word.good { --tone: var(--c2); color: var(--c2); } +.ctx-ring.fair, .ctx-grade-word.fair { --tone: var(--amber); color: var(--amber); } +.ctx-ring.poor, .ctx-grade-word.poor { --tone: var(--red); color: var(--red); } +.ctx-ring b { color: var(--fg); } +.ctx-scores { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px; } +.ctx-score { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px; font-size: 11.5px; color: var(--fg-2); cursor: default; } +.ctx-score .ctx-bar { height: 4px; } +.ctx-score .ctx-bar i { background: var(--green); } +.ctx-score.warn .ctx-bar i { background: var(--amber); } +.ctx-score.bad .ctx-bar i { background: var(--red); } +.ctx-score .v { color: var(--muted); font-size: 10.5px; } +.ctx-tags { display: flex; flex-wrap: wrap; gap: 6px; } +.ctx-tags:empty { display: none; } +.ctx-chip { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 9px; border-radius: 11px; font-size: 11.5px; font-weight: 500; background: var(--pill); color: var(--fg-2); cursor: default; } +.ctx-chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--c7); } +.ctx-chip.good { background: var(--green-soft); color: var(--green); } +.ctx-chip.good i { background: var(--green); } +.ctx-chip.warn { background: var(--amber-soft); color: var(--amber); } +.ctx-chip.warn i { background: var(--amber); } +.ctx-chip.info i { background: var(--accent); } +.ctx-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 12px; padding: 10px 0 2px; border-top: 1px solid var(--line); } +.ctx-fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; cursor: default; } +.ctx-fact b { font-size: 15px; font-weight: 600; letter-spacing: -.01em; } +.ctx-fact .ctx-k { font-size: 9.5px; overflow: hidden; text-overflow: ellipsis; display: block; } +.ctx-mix { display: flex; flex-direction: column; gap: 6px; } +.ctx-share { display: flex; height: 8px; border-radius: 4px; overflow: hidden; gap: 2px; background: var(--k-free); } +.ctx-share i { display: block; min-width: 3px; background: var(--k); } +.ctx-mix-keys { display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: 11px; color: var(--muted); } +.ctx-mix-keys span { display: inline-flex; align-items: center; gap: 5px; } +.ctx-agent-foot { display: flex; align-items: center; gap: 8px; min-width: 0; margin-top: auto; } +.ctx-models { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; } +.ctx-models code { font-family: var(--code-font, var(--code)); font-size: 10.5px; padding: 2px 6px; border-radius: 5px; background: var(--pill); color: var(--fg-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; } +.ctx-agent-foot .text { flex: none; font-size: 11.5px; } + +.ctx-sess-head { margin-top: 6px; } +.ctx-sess-head .segs .opt { height: 20px; padding: 0 9px; font-size: 11px; } +.ctx-sess-list { display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; } +.ctx-sess + .ctx-sess { border-top: 1px solid var(--line-2, var(--line)); } +.ctx-sess-row { all: unset; box-sizing: border-box; width: 100%; display: grid; grid-template-columns: 20px minmax(0, 1.3fr) minmax(80px, 1fr) 44px minmax(0, auto) 92px; align-items: center; gap: 12px; padding: 8px 14px; cursor: pointer; font-size: 12px; font-variant-numeric: tabular-nums; } +.ctx-sess-row:hover { background: var(--pill); } +.ctx-sess-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; } +.ctx-sess-row .ic { width: 18px; height: 18px; } +.ctx-sess-name { display: flex; flex-direction: column; min-width: 0; gap: 1px; } +.ctx-sess-name b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.ctx-sess-name b.raw { font-family: var(--code-font, var(--code)); font-weight: 500; letter-spacing: .02em; } +.ctx-sess-name code { font-family: var(--code-font, var(--code)); font-size: 10.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.ctx-sess-row .ctx-spark { height: 24px; } +.ctx-sess-peak { justify-self: end; font-weight: 600; } +.ctx-sess-peak.ok { color: var(--green); } +.ctx-sess-peak.warn { color: var(--amber); } +.ctx-sess-peak.bad { color: var(--red); } +.ctx-sess-meta, .ctx-sess-when { color: var(--muted); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.ctx-sess-when { text-align: right; } +.ctx-sess.open { background: var(--card-2); } +.ctx-sess.open > .ctx-card { margin: 0 12px 12px; } +@media (max-width: 640px) { + .ctx-sess-row { grid-template-columns: 20px minmax(0, 1fr) 64px 40px; } + .ctx-sess-meta, .ctx-sess-when { display: none; } + .ctx-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .ctx-scores { grid-template-columns: 1fr; } + .ctx-top { grid-template-columns: 1fr; } +} +.ctx-none { display: flex; flex-direction: column; gap: 4px; align-items: center; padding: 48px 16px; color: var(--muted); font-size: 12.5px; text-align: center; background: var(--card); border: 1px dashed var(--line); border-radius: 14px; } +.ctx-none b { color: var(--fg); font-size: 13.5px; font-weight: 600; } + +@media (prefers-reduced-motion: reduce) { + .ctx-waffle > i, .ctx-bar i, .ctx-ring .arc, .ctx-state.live i { animation: none; } + .ctx-waffle > i { transition: none; } +} + +/* Safari 15: no container queries, so the card's narrow layout goes by the + window's width; no color-mix, so the free cells and the line's area are + tinted by opacity */ +@supports not (container-type: inline-size) { + @media (max-width: 560px) { + .ctx-waffle { grid-template-columns: repeat(25, minmax(0, 1fr)); } + .ctx-contents-head { flex-wrap: wrap; } + .ctx-contents-head .segs { flex: 1 1 100%; } + } + @media (max-width: 460px) { .ctx-mini, .ctx-tag { display: none; } } +} +@supports not (color: color-mix(in srgb, red 50%, blue)) { + :root { --k-free: rgba(128, 128, 128, .12); } + i.dot.free { box-shadow: inset 0 0 0 1px var(--line); } + .ctx-spark .area { fill: var(--k-chat); fill-opacity: .14; } + .ctx-spark .hit:hover { fill: var(--line); } +} diff --git a/internal/gui/assets/context.js b/internal/gui/assets/context.js new file mode 100644 index 00000000..5c5f9dc7 --- /dev/null +++ b/internal/gui/assets/context.js @@ -0,0 +1,619 @@ +"use strict"; +// Context windows: what a request's prompt holds, as the gateway read it +// (gateway.Route.Prompt), drawn as a card — how full the window is, how +// much the vendor read from its cache, a grid of the window with a cell +// for each 1/400 of it coloured by what fills it, and the contents part by +// part. Routing shows the card for the request it tells of; the Usage +// page's Context tab scores each agent's use of its window, tags it, and +// lists its sessions' fill request by request. +(() => { + const PARTS = ["system", "tools", "memory", "files", "results", "chat"]; + const PART_NAMES = { + system: "System prompt", tools: "Tools", memory: "Memory", + files: "Files", results: "Tool results", chat: "Conversation", + }; + const PART_NOTES = { + system: "The agent's own instructions", + tools: "The definitions of the tools it can call", + memory: "Instruction files, memory and reminders", + files: "Files it read, and images", + results: "What the other tools it called returned", + chat: "What you and the model said, turn by turn", + }; + const CELLS = 400; + const partName = (k) => t(PART_NAMES[k] || k); + + const fmtK = (n) => { + n = Math.max(0, Math.round(n || 0)); + const short = (x, d) => x.toFixed(d).replace(/\.0+$/, ""); + if (n >= 1e6) return short(n / 1e6, n >= 1e7 ? 1 : 2) + "M"; + if (n >= 1e3) return short(n / 1e3, n >= 1e5 ? 0 : 1) + "K"; + return String(n); + }; + const pct = (x) => Math.round(x * 100) + "%"; + const median = (xs) => { + if (!xs.length) return 0; + const s = [...xs].sort((a, b) => a - b); + return s[s.length >> 1]; + }; + const agentMeta = (id) => (state.clients || state.agents || []).find((a) => a.id === id); + const agentLabel = (id) => agentMeta(id)?.name || id || t("your agent"); + const agentIcon = (id) => icon(agentMeta(id)?.icon || "generic"); + + // what an item of the prompt is called: a file's path or a tool's name + // as it is; magpie's own names for the rest in the reader's language + const ITEM_NAMES = { + prompt: "Agent prompt", harness: "Harness messages", billing: "Billing header", + environment: "Environment notes", context: "Context", skills: "Skills", + reminders: "System reminders", compacted: "Compacted summary", image: "Image", document: "Document", + }; + function itemName(it) { + if (it.tag === "turn") return t("Turn {n}", { n: it.name }); + if (it.tag === "turns") return t("{n} earlier turns", { n: it.n }); + if (it.tag === "more") return t("{n} more", { n: it.n }); + return ITEM_NAMES[it.name] ? t(ITEM_NAMES[it.name]) : it.name; + } + // a path's file name first, where it is after it + function itemLabel(it, kind) { + const name = itemName(it); + const e = el("span", "ctx-name"); + if ((kind === "files" || kind === "memory") && name.includes("/")) { + const at = name.lastIndexOf("/"); + e.append(el("b", "", name.slice(at + 1)), el("small", "", name.slice(0, at + 1))); + } else e.append(el("b", "", name)); + e.title = name; + return e; + } + const TAG_NAMES = { + mcp: "MCP", namespace: "namespace", read: "read", shell: "shell", result: "result", + user: "user", project: "project", local: "local", memory: "memory", skills: "skills", + reminder: "reminder", image: "image", turn: "", turns: "", more: "", compacted: "", + }; + const tagOf = (it) => it.tag in TAG_NAMES ? TAG_NAMES[it.tag] : it.tag || ""; + + const health = (fill) => fill < 0.75 ? ["ok", "Healthy"] : fill < 0.9 ? ["warn", "Filling up"] : ["bad", "Near full"]; + + // the cache a route's vendor read: its last answer's usage + function cacheOf(r) { + const u = r.usage?.[r.usage.length - 1]; + if (!u) return null; + const total = (u.in || 0) + (u.cache_read || 0) + (u.cache_write || 0); + if (!total) return null; + return { read: u.cache_read || 0, total }; + } + + // the cells of the grid, each the part and item it shows; a window + // smaller than the prompt (not known, or overrun) is the prompt + function cellsOf(p, window) { + const scale = Math.max(window, p.tokens, 1); + const used = Math.min(CELLS, Math.round((p.tokens / scale) * CELLS)); + const parts = PARTS.map((k) => p.parts.find((x) => x.kind === k)).filter((x) => x && x.tokens > 0); + const sum = parts.reduce((s, x) => s + x.tokens, 0) || 1; + // largest remainder, so the cells add up to used and a part of any + // size has at least one + const want = parts.map((x) => (x.tokens / sum) * used); + const got = want.map((w) => Math.max(1, Math.floor(w))); + let left = used - got.reduce((s, n) => s + n, 0); + const order = want.map((w, i) => [w - Math.floor(w), i]).sort((a, b) => b[0] - a[0]); + for (let j = 0; left > 0 && order.length; j = (j + 1) % order.length, left--) got[order[j][1]]++; + for (let j = got.length - 1; left < 0 && j >= 0; j--) while (left < 0 && got[j] > 1) { got[j]--; left++; } + const cells = []; + parts.forEach((x, pi) => { + const items = [...(x.items || [])].sort((a, b) => b.tokens - a.tokens); + const isum = items.reduce((s, it) => s + it.tokens, 0) || 1; + let at = 0, acc = 0; + for (let c = 0; c < got[pi]; c++) { + // the item whose share the cell's middle falls in + const mid = ((c + 0.5) / got[pi]) * isum; + while (at < items.length - 1 && acc + items[at].tokens < mid) acc += items[at++].tokens; + cells.push({ kind: x.kind, item: items.length ? at : -1 }); + } + }); + while (cells.length < CELLS) cells.push(null); + return cells.slice(0, CELLS); + } + + // the headroom: how many more requests fit, at the pace the session's + // prompts grew + function headroom(series, free) { + const steps = []; + for (let i = 1; i < series.length; i++) { + const d = series[i].tokens - series[i - 1].tokens; + if (d > 0 && series[i].tokens >= series[i - 1].tokens * 0.6) steps.push(d); + } + const g = median(steps); + return g > 0 ? Math.floor(free / g) : null; + } + + // count words a number with the phrase for one, or for many + const count = (n, one, many) => n === 1 ? t(one) : t(many, { n }); + + // spark draws a session's prompts, request by request, against its + // window; the one the card tells of is marked, and a point clicked opens + // its request + function spark(series, at, window, onPoint) { + const W = 240, H = 34, pad = 3; + // scaled to the session's peak, so a session that never came near its + // window still shows how it grew; the window's line shows once it is near + const peak = Math.max(...series.map((p) => p.tokens), 1); + const top = window && peak > window * 0.6 ? Math.max(window, peak) : peak * 1.2; + const x = (i) => series.length < 2 ? W / 2 : pad + (i / (series.length - 1)) * (W - pad * 2); + const y = (n) => H - pad - (n / top) * (H - pad * 2); + const box = el("span", "ctx-spark"); + const s = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + s.setAttribute("viewBox", `0 0 ${W} ${H}`); + s.setAttribute("preserveAspectRatio", "none"); + box.append(s); + const ns = (tag, attrs) => { + const e = document.createElementNS("http://www.w3.org/2000/svg", tag); + for (const [k, v] of Object.entries(attrs)) e.setAttribute(k, v); + s.append(e); + return e; + }; + if (window && window <= top) ns("line", { x1: 0, x2: W, y1: y(window), y2: y(window), class: "win" }); + const pts = series.map((p, i) => `${x(i).toFixed(1)},${y(p.tokens).toFixed(1)}`); + if (series.length > 1) { + ns("path", { d: `M${pts[0]} L${pts.slice(1).join(" L")} L${x(series.length - 1).toFixed(1)},${H} L${x(0).toFixed(1)},${H} Z`, class: "area" }); + ns("polyline", { points: pts.join(" "), class: "line" }); + } + series.forEach((p, i) => { + const on = p.id === at; + // the marker is a dot over the stretched svg, so it stays round + if (on) { + const dot = el("span", "at"); + dot.style.left = (x(i) / W * 100).toFixed(2) + "%"; + dot.style.top = (y(p.tokens) / H * 100).toFixed(2) + "%"; + box.append(dot); + } + if (!onPoint) return; + const hit = ns("rect", { x: x(i) - Math.max(2, W / series.length / 2), y: 0, width: Math.max(4, W / series.length), height: H, class: "hit" + (on ? " on" : "") }); + const tip = document.createElementNS("http://www.w3.org/2000/svg", "title"); + tip.textContent = t("Request {n}: {tokens} tokens", { n: i + 1, tokens: fmtK(p.tokens) }); + hit.append(tip); + hit.addEventListener("click", (e) => { e.stopPropagation(); onPoint(p); }); + }); + return box; + } + + // ctxCard draws a route's prompt. opts: series (the session's prompts, + // [{id, tokens, time}]), onPoint (a point of it clicked), cache ({read, + // total}, when the route carries no usage), crumbs (the footer's path) + function ctxCard(r, opts = {}) { + const p = r.prompt; + const card = el("div", "ctx-card"); + if (!p) return card; + const window = p.window || 0; + const fill = window ? p.tokens / window : 0; + const live = !r.done; + + // the head: what it is and how it was counted + const head = el("div", "ctx-head"); + const title = el("span", "ctx-title", t("Context window")); + const st = el("span", "ctx-state " + (live ? "live" : p.counted ? "counted" : "est")); + st.append(el("i"), t(live ? "Live" : p.counted ? "Counted" : "Estimated")); + st.title = t(live ? "The request is on its way: the prompt is estimated from what the agent sent" + : p.counted ? "As many tokens as the vendor counted; the parts are measured from the request and scaled to it" + : "Estimated from what the agent sent: the vendor didn't say how many tokens it read"); + head.append(title, el("span", "grow")); + if (r.model) head.append(el("code", "ctx-model", r.model)); + head.append(st); + + // how full, and the cache + const top = el("div", "ctx-top"); + const used = el("div", "ctx-stat"); + const k = el("div", "ctx-k"); + k.append(el("span", "", t("Context used"))); + if (window) { + const [tone, word] = health(fill); + const h = el("span", "ctx-health " + tone, t(word)); + k.append(h); + } + const big = el("div", "ctx-big"); + big.append(el("b", "", fmtK(p.tokens))); + big.append(el("span", "", window ? " / " + fmtK(window) + " " + t("tokens") : " " + t("tokens"))); + const sub = el("div", "ctx-sub"); + if (window) { + const bits = [t("{pct} full", { pct: pct(fill) })]; + const turns = opts.series ? headroom(opts.series, Math.max(0, window - p.tokens)) : null; + if (turns !== null) bits.push(turns >= 999 ? t("plenty of headroom") : t("~{n} requests of headroom", { n: turns })); + else bits.push(t("{tokens} free", { tokens: fmtK(Math.max(0, window - p.tokens)) })); + sub.textContent = bits.join(" · "); + } else sub.textContent = t("the model's window isn't known"); + used.append(k, big, sub); + top.append(used); + + const cache = cacheOf(r) || opts.cache; + if (cache && p.counted !== false) { + const c = el("div", "ctx-stat ctx-cache"); + const hit = cache.read / cache.total; + c.append(el("div", "ctx-k", t("Prompt cache"))); + const cb = el("div", "ctx-big"); + cb.append(el("b", "", pct(hit)), el("span", "", " " + t("hit"))); + const bar = el("div", "ctx-bar"); + const fillBar = el("i"); + fillBar.style.width = (hit * 100).toFixed(1) + "%"; + bar.append(fillBar); + c.append(cb, bar, el("div", "ctx-sub", t("{cached} cached · {fresh} new", { cached: fmtK(cache.read), fresh: fmtK(cache.total - cache.read) }))); + top.append(c); + } + + // the grid + const grid = el("div", "ctx-waffle"); + grid.setAttribute("role", "img"); + grid.setAttribute("aria-label", t("{used} of {window} tokens used", { used: fmtK(p.tokens), window: fmtK(window || p.tokens) })); + const cells = cellsOf(p, window); + const partOf = new Map(p.parts.map((x) => [x.kind, x])); + cells.forEach((c, i) => { + const e = el("i", c ? "k-" + c.kind : "free"); + if (c) e.dataset.it = c.item; + if (!opts.still) e.style.setProperty("--d", Math.round(i * 1.4) + "ms"); + grid.append(e); + }); + const tip = el("div", "ctx-tip"); + tip.hidden = true; + const showTip = (target) => { + const idx = [...grid.children].indexOf(target); + const c = cells[idx]; + tip.replaceChildren(); + const th = el("div", "ctx-tip-head"); + if (c) { + const part = partOf.get(c.kind); + th.append(el("i", "dot k-" + c.kind), el("b", "", partName(c.kind)), el("span", "grow"), + el("span", "", fmtK(part.tokens) + " · " + pct(part.tokens / Math.max(1, p.tokens)))); + tip.append(th); + const items = [...(part.items || [])].sort((a, b) => b.tokens - a.tokens); + const shown = items.slice(0, 4); + const here = items[c.item]; + if (here && !shown.includes(here)) shown[3] = here; + for (const it of shown) { + const row = el("div", "ctx-tip-row" + (it === here ? " on" : "")); + row.append(el("span", "n", itemName(it)), el("span", "v", fmtK(it.tokens))); + tip.append(row); + } + if (items.length > shown.length) tip.append(el("div", "ctx-tip-more", t("{n} more", { n: items.length - shown.length }))); + grid.dataset.f = c.kind; + } else { + th.append(el("i", "dot free"), el("b", "", t("Free space")), el("span", "grow"), + el("span", "", fmtK(Math.max(0, window - p.tokens)))); + tip.append(th); + grid.dataset.f = "free"; + } + tip.hidden = false; + const b = target.getBoundingClientRect(), cr = card.getBoundingClientRect(); + const w = tip.offsetWidth, h = tip.offsetHeight; + let left = b.left - cr.left + b.width / 2 - w / 2; + left = Math.max(8, Math.min(cr.width - w - 8, left)); + let topY = b.top - cr.top - h - 8; + if (topY < 4) topY = b.bottom - cr.top + 8; + tip.style.left = left + "px"; + tip.style.top = topY + "px"; + }; + grid.addEventListener("pointerover", (e) => { if (e.target.parentElement === grid) showTip(e.target); }); + grid.addEventListener("pointerleave", () => { tip.hidden = true; delete grid.dataset.f; }); + + // the legend: a part hovered lights its cells + const legend = el("div", "ctx-legend"); + for (const kind of PARTS) { + const part = partOf.get(kind); + if (!part || part.tokens <= 0) continue; + const li = el("span", "ctx-leg"); + li.title = t(PART_NOTES[kind]); + li.append(el("i", "dot k-" + kind), el("span", "n", partName(kind)), el("span", "v", fmtK(part.tokens))); + li.onpointerenter = () => { grid.dataset.f = kind; }; + li.onpointerleave = () => { delete grid.dataset.f; }; + legend.append(li); + } + if (window && window > p.tokens) { + const li = el("span", "ctx-leg"); + li.append(el("i", "dot free"), el("span", "n", t("Free space")), el("span", "v", fmtK(window - p.tokens))); + li.onpointerenter = () => { grid.dataset.f = "free"; }; + li.onpointerleave = () => { delete grid.dataset.f; }; + legend.append(li); + } + + // the contents, part by part + const contents = el("div", "ctx-contents"); + const ch = el("div", "ctx-contents-head"); + const list = el("div", "ctx-rows"); + const tabs = [["all", t("All")], ...PARTS.filter((k) => partOf.get(k)?.tokens > 0).map((k) => [k, partName(k)])]; + let tab = opts.tab && tabs.some(([id]) => id === opts.tab) ? opts.tab : "all"; + let more = false; + const drawRows = () => { + let rows; + if (tab === "all") { + rows = p.parts.flatMap((x) => (x.items || []).map((it, i) => ({ it, i, kind: x.kind }))); + } else { + const x = partOf.get(tab); + rows = (x?.items || []).map((it, i) => ({ it, i, kind: tab })); + } + rows.sort((a, b) => b.it.tokens - a.it.tokens); + const most = Math.max(1, ...rows.map((x) => x.it.tokens)); + const n = more ? rows.length : Math.min(rows.length, 8); + const out = rows.slice(0, n).map(({ it, i, kind }) => { + const row = el("div", "ctx-row"); + const tg = tagOf(it); + const bar = el("span", "ctx-mini"); + const b = el("i", "k-" + kind); + b.style.width = Math.max(2, (it.tokens / most) * 100).toFixed(1) + "%"; + bar.append(b); + row.append(el("i", "dot k-" + kind), itemLabel(it, kind)); + if (it.n > 1 && it.tag !== "turns" && it.tag !== "more") row.append(el("span", "ctx-x", "×" + it.n)); + if (tg) row.append(el("code", "ctx-tag", tg)); + row.append(bar, el("span", "ctx-v", fmtK(it.tokens))); + // its cells light up + row.onpointerenter = () => { + grid.dataset.f = "item"; + for (const [j, c] of cells.entries()) grid.children[j].classList.toggle("on", !!c && c.kind === kind && c.item === i); + }; + row.onpointerleave = () => { + delete grid.dataset.f; + for (const e of grid.querySelectorAll("i.on")) e.classList.remove("on"); + }; + return row; + }); + if (!rows.length) out.push(el("div", "ctx-empty", t("Nothing in it"))); + if (rows.length > 8) { + const b = el("button", "text ctx-more", more ? t("Show fewer") : t("Show all {n}", { n: rows.length })); + b.type = "button"; + b.onclick = () => { more = !more; drawRows(); }; + out.push(b); + } + list.replaceChildren(...out); + }; + ch.append(el("span", "ctx-k", t("Contents")), el("span", "grow"), + segs(tabs, tab, (id) => { tab = id; more = false; opts.onTab?.(id); drawRows(); })); + contents.append(ch, list); + drawRows(); + + // the foot: where it is, and the session's line + const foot = el("div", "ctx-foot"); + const crumbs = el("code", "ctx-crumbs"); + crumbs.textContent = (opts.crumbs || [agentLabel(r.agent)]).filter(Boolean).join(" › "); + const notes = []; + if (p.held) notes.push(t("Earlier turns are held by the vendor")); + if (p.turns) notes.push(count(p.turns, "1 turn", "{n} turns")); + foot.append(crumbs, el("span", "grow")); + if (notes.length) foot.append(el("span", "ctx-note", notes.join(" · "))); + card.append(head, top, grid, legend, contents, foot); + if (opts.series && opts.series.length > 1) { + const sp = el("div", "ctx-session"); + sp.append(el("span", "ctx-k", t("This session")), spark(opts.series, r.id, window, opts.onPoint), + el("span", "ctx-sub", count(opts.series.length, "1 request", "{n} requests"))); + card.append(sp); + } + card.append(tip); + return card; + } + window.ctxCard = ctxCard; + window.ctxFmt = fmtK; + + // ---------- the Usage page's Context tab ---------- + + const CTX_RANGES = [["1", "Today"], ["7", "7 days"], ["30", "30 days"]]; + let ctxDays = "7"; + try { const d = localStorage.getItem("magpie.ctxDays"); if (CTX_RANGES.some(([id]) => id === d)) ctxDays = d; } catch {} + let ctxData = null, ctxJSON = "", ctxRead = 0, ctxOpen = "", ctxAgent = "all"; + + const SCORE_NAMES = { cache: "Cache", lean: "Lean start", pace: "Pace", reliable: "Reliability" }; + const SCORE_NOTES = { + cache: "How much of its prompts the vendor read from its cache: full marks at 90%", + lean: "What every request starts with — system prompt, tools, memory — against the window: full marks at 5% or less", + pace: "How much a request adds to the one before it: full marks at 1% of the window or less", + reliable: "Its requests that didn't fail: none at 20% failing", + }; + const TAGS = { + "cache-friendly": ["Cache-friendly", (v) => t("{pct} of its prompts were read from the vendor's cache", { pct: pct(v) })], + "cache-misses": ["Cache misses", (v) => t("Only {pct} of its prompts were read from the cache: each request pays for most of its prompt again", { pct: pct(v) })], + lean: ["Lean start", (v) => t("Every request starts with {tokens} of system prompt, tools and memory", { tokens: fmtK(v) })], + "heavy-start": ["Heavy start", (v) => t("Every request starts with {tokens} of system prompt, tools and memory, before a word of yours", { tokens: fmtK(v) })], + "mcp-heavy": ["MCP-heavy", (v) => t("MCP servers' tool definitions take {tokens} of every request", { tokens: fmtK(v) })], + "tool-heavy": ["Tool-heavy", (v) => t("Tool results are {pct} of its prompts", { pct: pct(v) })], + "file-reader": ["Reads files", (v) => t("Files it read are {pct} of its prompts", { pct: pct(v) })], + "memory-heavy": ["Memory-heavy", (v) => t("Instruction files and memory are {pct} of its prompts", { pct: pct(v) })], + "fills-fast": ["Fills fast", (v) => t("A request adds {tokens} to the one before it, the median", { tokens: fmtK(v) })], + "near-full": ["Runs near full", (v) => t("A session reached {pct} of its window", { pct: pct(v) })], + compacts: ["Compacts", (v) => t("Its context was compacted {n} times", { n: v })], + steady: ["Steady", () => t("Fewer than 1% of its requests failed")], + flaky: ["Flaky", (v) => t("{pct} of its requests failed", { pct: pct(v) })], + }; + const grade = (s) => s >= 85 ? ["great", "Excellent"] : s >= 70 ? ["good", "Good"] : s >= 50 ? ["fair", "Fair"] : ["poor", "Needs care"]; + + function ring(score) { + const r = 26, c = 2 * Math.PI * r; + const [tone] = grade(score); + const box = el("div", "ctx-ring " + tone); + const s = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + s.setAttribute("viewBox", "0 0 64 64"); + s.innerHTML = ``; + box.append(s, el("b", "", String(score))); + return box; + } + + function shareBar(shares) { + const bar = el("div", "ctx-share"); + for (const k of PARTS) { + const v = shares?.[k] || 0; + if (v <= 0.002) continue; + const i = el("i", "k-" + k); + i.style.flexGrow = v; + i.title = partName(k) + " · " + pct(v); + bar.append(i); + } + return bar; + } + + function agentCard(a) { + const card = el("div", "ctx-agent"); + const head = el("div", "ctx-agent-head"); + const who = el("div", "ctx-who"); + who.append(agentIcon(a.agent), el("b", "", agentLabel(a.agent))); + const meta = el("div", "ctx-who-sub", [count(a.requests, "1 request", "{n} requests"), count(a.sessions, "1 session", "{n} sessions")].join(" · ")); + const name = el("div", "ctx-who-box"); + name.append(who, meta); + const [tone, word] = grade(a.score); + const g = el("div", "ctx-grade"); + g.append(ring(a.score), el("span", "ctx-grade-word " + tone, t(word))); + head.append(name, el("span", "grow"), g); + + const scores = el("div", "ctx-scores"); + for (const s of a.scores || []) { + const r = s.most ? s.points / s.most : 0; + const row = el("div", "ctx-score " + (r >= 0.8 ? "ok" : r >= 0.5 ? "warn" : "bad")); + row.title = t(SCORE_NOTES[s.key] || ""); + const bar = el("span", "ctx-bar"); + const f = el("i"); + f.style.width = ((s.points / s.most) * 100).toFixed(1) + "%"; + bar.append(f); + row.append(el("span", "n", t(SCORE_NAMES[s.key] || s.key)), bar, el("span", "v", `${s.points}/${s.most}`)); + scores.append(row); + } + + const tags = el("div", "ctx-tags"); + for (const tg of a.tags || []) { + const def = TAGS[tg.key]; + const chip = el("span", "ctx-chip " + tg.tone); + chip.append(el("i"), def ? t(def[0]) : tg.key); + chip.dataset.tt = def ? def[1](tg.value || 0) : tg.key; + tags.append(chip); + } + + const facts = el("div", "ctx-facts"); + const fact = (label, value, note) => { + const f = el("div", "ctx-fact"); + f.append(el("span", "ctx-k", t(label)), el("b", "", value)); + if (note) f.dataset.tt = t(note); + facts.append(f); + }; + fact("Typical prompt", fmtK(a.median), "The median request's prompt"); + fact("Largest", fmtK(a.p90), "90% of its requests' prompts are this size or smaller"); + fact("Starts with", fmtK(a.baseline), "System prompt, tools and memory: what every request carries before the conversation"); + fact("Grows by", a.growth ? "+" + fmtK(a.growth) : "—", "How much a request's prompt adds to the one before it, the median"); + fact("Cache hit", a.scores?.find((s) => s.key === "cache") && a.cache ? pct(a.cache) : "—", "Of its prompts, what the vendor read from its cache"); + fact("Window size", a.window ? fmtK(a.window) : "—", "The largest context window of the models it used"); + + const mix = el("div", "ctx-mix"); + mix.append(el("span", "ctx-k", t("What its prompts hold")), shareBar(a.shares)); + const keys = el("div", "ctx-mix-keys"); + for (const k of PARTS) { + const v = a.shares?.[k] || 0; + if (v < 0.01) continue; + const s = el("span", ""); + s.append(el("i", "dot k-" + k), partName(k) + " " + pct(v)); + keys.append(s); + } + mix.append(keys); + + const foot = el("div", "ctx-agent-foot"); + const models = el("span", "ctx-models"); + // by the model's own name: "live/claude/claude-sonnet-4-5" cut short + // read the same for each of its models; the whole id in its tooltip + for (const m of a.models || []) { + const c = el("code", "", m.split("/").pop()); + c.title = m; + models.append(c); + } + foot.append(models, el("span", "grow")); + if (a.latestId) { + const go = el("button", "text", t("Latest request")); + go.type = "button"; + go.onclick = () => window.openRoute(a.latestId, a.latestTime).catch((e) => status(e.message, "err")); + foot.append(go); + } + card.append(head, scores, tags, facts, mix, foot); + return card; + } + + function sessionRow(s) { + const open = ctxOpen === s.agent + "\x00" + s.key; + const box = el("div", "ctx-sess" + (open ? " open" : "")); + const row = el("button", "ctx-sess-row"); + row.type = "button"; + row.setAttribute("aria-expanded", String(open)); + const name = el("span", "ctx-sess-name"); + // an untitled session goes by the head of its id, the way the footer names it + name.append(s.title ? el("b", "", s.title) : el("b", "raw", s.key.slice(0, 8))); + name.append(el("code", "", s.model)); + const fill = s.window ? s.peak / s.window : 0; + const [tone] = health(fill); + const peak = el("span", "ctx-sess-peak " + tone, s.window ? pct(fill) : fmtK(s.peak)); + peak.dataset.tt = t("Its largest prompt: {tokens} of {window}", { tokens: fmtK(s.peak), window: fmtK(s.window) }); + const meta = el("span", "ctx-sess-meta", count(s.requests, "1 request", "{n} requests") + (s.compacts ? " · " + count(s.compacts, "1 compaction", "{n} compactions") : "")); + row.append(agentIcon(s.agent), name, spark(s.points, s.latestId, s.window), peak, meta, el("span", "ctx-sess-when", ago(s.last))); + row.onclick = () => { + ctxOpen = open ? "" : s.agent + "\x00" + s.key; + renderContext(); + }; + box.append(row); + if (open && s.latest) { + const last = s.points[s.points.length - 1]; + const r = { id: s.latestId, time: s.last, done: true, agent: s.agent, model: s.model, prompt: s.latest }; + const cache = last && s.latest.counted && last.tokens ? { read: last.cache || 0, total: last.tokens } : null; + box.append(ctxCard(r, { + still: true, cache, + series: s.points, + crumbs: [agentLabel(s.agent), s.title || s.key.slice(0, 12), t("latest request")], + onPoint: (pt) => window.openRoute(pt.id, pt.time).catch((e) => status(e.message, "err")), + })); + } + return box; + } + + function renderContext() { + const pane = $("#contextPane"); + if (!pane) return; + const tools = el("div", "sess-tools ctx-tools"); + tools.append(segs(CTX_RANGES.map(([id, n]) => [id, t(n)]), ctxDays, (id) => { + ctxDays = id; + try { localStorage.setItem("magpie.ctxDays", id); } catch {} + loadContext(); + })); + tools.append(el("span", "grow")); + pane.replaceChildren(tools); + if (!ctxData) { + pane.append(el("p", "usage-note", t("Reading the routing history…"))); + return; + } + pane.append(el("p", "usage-note", t("What each agent's prompts hold, as magpie's gateway read them: the score and tags are worked out from the requests of the range."))); + if (!ctxData.agents.length) { + const empty = el("div", "ctx-none"); + empty.append(el("b", "", t("No prompts read yet")), el("span", "", t("Requests your agents send through magpie show here."))); + pane.append(empty); + return; + } + const grid = el("div", "ctx-agents"); + for (const a of ctxData.agents) grid.append(agentCard(a)); + pane.append(grid); + + const agents = [...new Set(ctxData.sessions.map((s) => s.agent))]; + const head = el("div", "row-head ctx-sess-head"); + head.append(el("span", "label", t("Sessions")), el("span", "grow")); + if (agents.length > 1) { + if (ctxAgent !== "all" && !agents.includes(ctxAgent)) ctxAgent = "all"; + head.append(segs([["all", t("All")], ...agents.map((id) => [id, agentLabel(id)])], ctxAgent, (id) => { ctxAgent = id; renderContext(); })); + } + pane.append(head); + const list = el("div", "ctx-sess-list"); + const shown = ctxData.sessions.filter((s) => ctxAgent === "all" || s.agent === ctxAgent); + for (const s of shown) list.append(sessionRow(s)); + if (!shown.length) list.append(el("p", "usage-note", t("No sessions in this range"))); + pane.append(list); + } + + async function loadContext() { + const read = ++ctxRead, days = ctxDays; + if (!ctxData || ctxData.days !== +days) { ctxData = null; renderContext(); } + const data = await api("context?days=" + days); + if (read !== ctxRead) return; + // the auto refresh redraws only what changed: the same answer keeps the + // pane (and what the pointer is on), and a new one comes in without its + // entrance animations + const json = JSON.stringify(data); + if (ctxData && json === ctxJSON) return; + const pane = $("#contextPane"); + if (pane) pane.classList.toggle("still", !!ctxData); + ctxData = data, ctxJSON = json; + renderContext(); + } + window.loadContext = loadContext; + window.renderContext = renderContext; +})(); diff --git a/internal/gui/assets/i18n.js b/internal/gui/assets/i18n.js index 9f6d5262..e5b5eda1 100644 --- a/internal/gui/assets/i18n.js +++ b/internal/gui/assets/i18n.js @@ -4,6 +4,115 @@ // works. {name} slots are filled by t(str, vars). const I18N = { zh: { + // the context window (context.js) + "1 request": "1 个请求", + "1 session": "1 个会话", + "1 compaction": "压缩 1 次", + "1 turn": "1 轮", + "System prompt": "系统提示词", + "Tools": "工具", + "Files": "文件", + "Tool results": "工具结果", + "The agent's own instructions": "agent 自带的指令", + "The definitions of the tools it can call": "它可调用的工具的定义", + "Instruction files, memory and reminders": "指令文件、记忆和提醒", + "Files it read, and images": "它读取的文件和图片", + "What the other tools it called returned": "它调用的其他工具返回的内容", + "What you and the model said, turn by turn": "你和模型的对话,逐轮", + "Agent prompt": "agent 提示词", + "Harness messages": "harness 消息", + "Billing header": "计费头", + "Environment notes": "环境信息", + "System reminders": "系统提醒", + "Compacted summary": "压缩后的摘要", + "Document": "文档", + "Turn {n}": "第 {n} 轮", + "{n} earlier turns": "更早的 {n} 轮", + "{n} more": "另外 {n} 项", + "Healthy": "健康", + "Filling up": "渐满", + "Near full": "将满", + "Request {n}: {tokens} tokens": "第 {n} 个请求:{tokens} token", + "Counted": "已计数", + "Estimated": "估算", + "The request is on its way: the prompt is estimated from what the agent sent": "请求进行中:提示词按 agent 发送的内容估算", + "As many tokens as the vendor counted; the parts are measured from the request and scaled to it": "总数是服务商计的 token 数;各部分按请求内容测量,再按比例对齐到总数", + "Estimated from what the agent sent: the vendor didn't say how many tokens it read": "按 agent 发送的内容估算:服务商没有告知它读了多少 token", + "Context used": "已用上下文", + "{pct} full": "已用 {pct}", + "plenty of headroom": "余量充足", + "~{n} requests of headroom": "约还能容纳 {n} 个请求", + "{tokens} free": "剩余 {tokens}", + "the model's window isn't known": "模型的窗口大小未知", + "Prompt cache": "提示词缓存", + "hit": "命中", + "{cached} cached · {fresh} new": "{cached} 来自缓存 · {fresh} 新增", + "{used} of {window} tokens used": "已用 {used} / {window} token", + "Free space": "剩余空间", + "Nothing in it": "这里没有内容", + "Show all {n}": "显示全部 {n} 项", + "Contents": "内容", + "Earlier turns are held by the vendor": "更早的轮次保存在服务商那里", + "{n} turns": "{n} 轮", + "This session": "本会话", + "Lean start": "起步轻", + "Pace": "增速", + "Reliability": "可靠性", + "How much of its prompts the vendor read from its cache: full marks at 90%": "服务商从缓存读取的提示词占比:90% 即满分", + "What every request starts with — system prompt, tools, memory — against the window: full marks at 5% or less": "每个请求一开始就带着的内容(系统提示词、工具、记忆)占窗口的比例:不超过 5% 即满分", + "How much a request adds to the one before it: full marks at 1% of the window or less": "每个请求比上一个多出的量:不超过窗口的 1% 即满分", + "Its requests that didn't fail: none at 20% failing": "未失败的请求:失败率达 20% 时为 0 分", + "Cache-friendly": "缓存友好", + "{pct} of its prompts were read from the vendor's cache": "它的提示词有 {pct} 是服务商从缓存读取的", + "Cache misses": "缓存常未命中", + "Only {pct} of its prompts were read from the cache: each request pays for most of its prompt again": "只有 {pct} 的提示词来自缓存:每个请求都要为大部分提示词重新付费", + "Every request starts with {tokens} of system prompt, tools and memory": "每个请求一开始就带着 {tokens} 的系统提示词、工具和记忆", + "Heavy start": "起步重", + "Every request starts with {tokens} of system prompt, tools and memory, before a word of yours": "你还没说一个字,每个请求就已带着 {tokens} 的系统提示词、工具和记忆", + "MCP-heavy": "MCP 偏重", + "MCP servers' tool definitions take {tokens} of every request": "MCP 服务器的工具定义在每个请求里占 {tokens}", + "Tool-heavy": "工具调用多", + "Tool results are {pct} of its prompts": "工具结果占它提示词的 {pct}", + "Reads files": "读文件多", + "Files it read are {pct} of its prompts": "它读取的文件占提示词的 {pct}", + "Memory-heavy": "记忆偏重", + "Instruction files and memory are {pct} of its prompts": "指令文件和记忆占它提示词的 {pct}", + "Fills fast": "涨得快", + "A request adds {tokens} to the one before it, the median": "每个请求比上一个多 {tokens}(中位数)", + "Runs near full": "常接近满", + "A session reached {pct} of its window": "有会话用到了窗口的 {pct}", + "Compacts": "会压缩", + "Its context was compacted {n} times": "它的上下文被压缩了 {n} 次", + "Steady": "稳定", + "Fewer than 1% of its requests failed": "失败的请求不到 1%", + "Flaky": "不稳定", + "{pct} of its requests failed": "{pct} 的请求失败了", + "Excellent": "优秀", + "Good": "良好", + "Fair": "一般", + "Needs care": "待改进", + "Typical prompt": "典型提示词", + "The median request's prompt": "请求提示词的中位数", + "Largest": "最大", + "90% of its requests' prompts are this size or smaller": "90% 的请求提示词不超过这个大小", + "Starts with": "起步", + "System prompt, tools and memory: what every request carries before the conversation": "系统提示词、工具和记忆:每个请求在对话之前就带着的内容", + "Grows by": "每次增长", + "How much a request's prompt adds to the one before it, the median": "请求提示词比上一个多出的量(中位数)", + "Cache hit": "缓存命中", + "Of its prompts, what the vendor read from its cache": "它的提示词中服务商从缓存读取的比例", + "Window size": "窗口大小", + "The largest context window of the models it used": "它所用模型中最大的上下文窗口", + "What its prompts hold": "提示词构成", + "Latest request": "最新请求", + "latest request": "最新请求", + "Its largest prompt: {tokens} of {window}": "最大的提示词:{tokens} / {window}", + "{n} compactions": "压缩 {n} 次", + "Reading the routing history…": "正在读取路由历史…", + "What each agent's prompts hold, as magpie's gateway read them: the score and tags are worked out from the requests of the range.": "每个 agent 的提示词里装了什么,由 magpie 网关读取;评分和标签根据所选时间范围内的请求算出。", + "No prompts read yet": "还没有读到提示词", + "Requests your agents send through magpie show here.": "你的 agent 经 magpie 发出的请求会显示在这里。", + "No sessions in this range": "这个时间范围内没有会话", "No installed fonts found": "未找到已安装字体", "Interface font": "界面字体", "Code font": "代码字体", @@ -3617,6 +3726,115 @@ const I18N = { "credits": "积分", }, "zh-TW": { + // the context window (context.js) + "1 request": "1 個請求", + "1 session": "1 個會話", + "1 compaction": "壓縮 1 次", + "1 turn": "1 輪", + "System prompt": "系統提示詞", + "Tools": "工具", + "Files": "檔案", + "Tool results": "工具結果", + "The agent's own instructions": "agent 自帶的指令", + "The definitions of the tools it can call": "它可呼叫的工具的定義", + "Instruction files, memory and reminders": "指令檔案、記憶和提醒", + "Files it read, and images": "它讀取的檔案和圖片", + "What the other tools it called returned": "它呼叫的其他工具傳回的內容", + "What you and the model said, turn by turn": "你和模型的對話,逐輪", + "Agent prompt": "agent 提示詞", + "Harness messages": "harness 訊息", + "Billing header": "計費標頭", + "Environment notes": "環境資訊", + "System reminders": "系統提醒", + "Compacted summary": "壓縮後的摘要", + "Document": "文件", + "Turn {n}": "第 {n} 輪", + "{n} earlier turns": "更早的 {n} 輪", + "{n} more": "另外 {n} 項", + "Healthy": "健康", + "Filling up": "漸滿", + "Near full": "將滿", + "Request {n}: {tokens} tokens": "第 {n} 個請求:{tokens} token", + "Counted": "已計數", + "Estimated": "預估", + "The request is on its way: the prompt is estimated from what the agent sent": "請求進行中:提示詞依 agent 送出的內容預估", + "As many tokens as the vendor counted; the parts are measured from the request and scaled to it": "總數是服務商計的 token 數;各部分依請求內容測量,再按比例對齊到總數", + "Estimated from what the agent sent: the vendor didn't say how many tokens it read": "依 agent 送出的內容預估:服務商沒有告知它讀了多少 token", + "Context used": "已用上下文", + "{pct} full": "已用 {pct}", + "plenty of headroom": "餘裕充足", + "~{n} requests of headroom": "約還能容納 {n} 個請求", + "{tokens} free": "剩餘 {tokens}", + "the model's window isn't known": "模型的視窗大小未知", + "Prompt cache": "提示詞快取", + "hit": "命中", + "{cached} cached · {fresh} new": "{cached} 來自快取 · {fresh} 新增", + "{used} of {window} tokens used": "已用 {used} / {window} token", + "Free space": "剩餘空間", + "Nothing in it": "這裡沒有內容", + "Show all {n}": "顯示全部 {n} 項", + "Contents": "內容", + "Earlier turns are held by the vendor": "更早的輪次保存在服務商那裡", + "{n} turns": "{n} 輪", + "This session": "本會話", + "Lean start": "起步輕", + "Pace": "增速", + "Reliability": "可靠性", + "How much of its prompts the vendor read from its cache: full marks at 90%": "服務商從快取讀取的提示詞占比:90% 即滿分", + "What every request starts with — system prompt, tools, memory — against the window: full marks at 5% or less": "每個請求一開始就帶著的內容(系統提示詞、工具、記憶)占視窗的比例:不超過 5% 即滿分", + "How much a request adds to the one before it: full marks at 1% of the window or less": "每個請求比上一個多出的量:不超過視窗的 1% 即滿分", + "Its requests that didn't fail: none at 20% failing": "未失敗的請求:失敗率達 20% 時為 0 分", + "Cache-friendly": "快取友善", + "{pct} of its prompts were read from the vendor's cache": "它的提示詞有 {pct} 是服務商從快取讀取的", + "Cache misses": "快取常未命中", + "Only {pct} of its prompts were read from the cache: each request pays for most of its prompt again": "只有 {pct} 的提示詞來自快取:每個請求都要為大部分提示詞重新付費", + "Every request starts with {tokens} of system prompt, tools and memory": "每個請求一開始就帶著 {tokens} 的系統提示詞、工具和記憶", + "Heavy start": "起步重", + "Every request starts with {tokens} of system prompt, tools and memory, before a word of yours": "你還沒說一個字,每個請求就已帶著 {tokens} 的系統提示詞、工具和記憶", + "MCP-heavy": "MCP 偏重", + "MCP servers' tool definitions take {tokens} of every request": "MCP 伺服器的工具定義在每個請求裡占 {tokens}", + "Tool-heavy": "工具呼叫多", + "Tool results are {pct} of its prompts": "工具結果占它提示詞的 {pct}", + "Reads files": "讀檔案多", + "Files it read are {pct} of its prompts": "它讀取的檔案占提示詞的 {pct}", + "Memory-heavy": "記憶偏重", + "Instruction files and memory are {pct} of its prompts": "指令檔案和記憶占它提示詞的 {pct}", + "Fills fast": "漲得快", + "A request adds {tokens} to the one before it, the median": "每個請求比上一個多 {tokens}(中位數)", + "Runs near full": "常接近滿", + "A session reached {pct} of its window": "有會話用到了視窗的 {pct}", + "Compacts": "會壓縮", + "Its context was compacted {n} times": "它的上下文被壓縮了 {n} 次", + "Steady": "穩定", + "Fewer than 1% of its requests failed": "失敗的請求不到 1%", + "Flaky": "不穩定", + "{pct} of its requests failed": "{pct} 的請求失敗了", + "Excellent": "優秀", + "Good": "良好", + "Fair": "普通", + "Needs care": "待改進", + "Typical prompt": "典型提示詞", + "The median request's prompt": "請求提示詞的中位數", + "Largest": "最大", + "90% of its requests' prompts are this size or smaller": "90% 的請求提示詞不超過這個大小", + "Starts with": "起步", + "System prompt, tools and memory: what every request carries before the conversation": "系統提示詞、工具和記憶:每個請求在對話之前就帶著的內容", + "Grows by": "每次增長", + "How much a request's prompt adds to the one before it, the median": "請求提示詞比上一個多出的量(中位數)", + "Cache hit": "快取命中", + "Of its prompts, what the vendor read from its cache": "它的提示詞中服務商從快取讀取的比例", + "Window size": "視窗大小", + "The largest context window of the models it used": "它所用模型中最大的上下文視窗", + "What its prompts hold": "提示詞構成", + "Latest request": "最新請求", + "latest request": "最新請求", + "Its largest prompt: {tokens} of {window}": "最大的提示詞:{tokens} / {window}", + "{n} compactions": "壓縮 {n} 次", + "Reading the routing history…": "正在讀取路由紀錄…", + "What each agent's prompts hold, as magpie's gateway read them: the score and tags are worked out from the requests of the range.": "每個 agent 的提示詞裡裝了什麼,由 magpie 閘道讀取;評分和標籤根據所選時間範圍內的請求算出。", + "No prompts read yet": "還沒有讀到提示詞", + "Requests your agents send through magpie show here.": "你的 agent 經 magpie 送出的請求會顯示在這裡。", + "No sessions in this range": "這個時間範圍內沒有會話", "Route by what it asks for": "按意圖分流", "It can pick the model too: add a rule with an intent": "它也能挑模型:新增一條帶意圖的規則", "already in the library: {names}": "資源庫裡已有:{names}", @@ -7213,6 +7431,115 @@ const I18N = { "credits": "積分", }, ja: { + // the context window (context.js) + "1 request": "1 件のリクエスト", + "1 session": "1 件のセッション", + "1 compaction": "圧縮 1 回", + "1 turn": "1 ターン", + "System prompt": "システムプロンプト", + "Tools": "ツール", + "Files": "ファイル", + "Tool results": "ツールの結果", + "The agent's own instructions": "エージェント自身の指示", + "The definitions of the tools it can call": "呼び出せるツールの定義", + "Instruction files, memory and reminders": "指示ファイル、メモリ、リマインダー", + "Files it read, and images": "読み込んだファイルと画像", + "What the other tools it called returned": "呼び出したその他のツールが返した内容", + "What you and the model said, turn by turn": "あなたとモデルのやり取り(ターンごと)", + "Agent prompt": "エージェントのプロンプト", + "Harness messages": "ハーネスのメッセージ", + "Billing header": "課金ヘッダー", + "Environment notes": "環境情報", + "System reminders": "システムリマインダー", + "Compacted summary": "圧縮された要約", + "Document": "ドキュメント", + "Turn {n}": "ターン {n}", + "{n} earlier turns": "それ以前の {n} ターン", + "{n} more": "ほか {n} 件", + "Healthy": "良好", + "Filling up": "埋まりつつある", + "Near full": "ほぼ満杯", + "Request {n}: {tokens} tokens": "リクエスト {n}:{tokens} トークン", + "Counted": "カウント済み", + "Estimated": "推定", + "The request is on its way: the prompt is estimated from what the agent sent": "リクエスト送信中:プロンプトはエージェントが送った内容から推定しています", + "As many tokens as the vendor counted; the parts are measured from the request and scaled to it": "トークン数はベンダーが数えたものです。各部分はリクエストから測り、その数に合わせて按分しています", + "Estimated from what the agent sent: the vendor didn't say how many tokens it read": "エージェントが送った内容から推定:ベンダーは読み込んだトークン数を返しませんでした", + "Context used": "使用中のコンテキスト", + "{pct} full": "{pct} 使用", + "plenty of headroom": "余裕あり", + "~{n} requests of headroom": "あと約 {n} リクエスト分の余裕", + "{tokens} free": "残り {tokens}", + "the model's window isn't known": "モデルのウィンドウサイズは不明", + "Prompt cache": "プロンプトキャッシュ", + "hit": "ヒット", + "{cached} cached · {fresh} new": "{cached} キャッシュ · {fresh} 新規", + "{used} of {window} tokens used": "{window} トークン中 {used} 使用", + "Free space": "空き", + "Nothing in it": "中身はありません", + "Show all {n}": "{n} 件すべて表示", + "Contents": "内訳", + "Earlier turns are held by the vendor": "以前のターンはベンダー側に保持されています", + "{n} turns": "{n} ターン", + "This session": "このセッション", + "Lean start": "軽いスタート", + "Pace": "増え方", + "Reliability": "信頼性", + "How much of its prompts the vendor read from its cache: full marks at 90%": "ベンダーがキャッシュから読んだプロンプトの割合:90% で満点", + "What every request starts with — system prompt, tools, memory — against the window: full marks at 5% or less": "すべてのリクエストが最初から持つもの(システムプロンプト、ツール、メモリ)がウィンドウに占める割合:5% 以下で満点", + "How much a request adds to the one before it: full marks at 1% of the window or less": "1 つのリクエストが前回より増える量:ウィンドウの 1% 以下で満点", + "Its requests that didn't fail: none at 20% failing": "失敗しなかったリクエスト:失敗率 20% で 0 点", + "Cache-friendly": "キャッシュ効率が良い", + "{pct} of its prompts were read from the vendor's cache": "プロンプトの {pct} がベンダーのキャッシュから読まれました", + "Cache misses": "キャッシュミスが多い", + "Only {pct} of its prompts were read from the cache: each request pays for most of its prompt again": "キャッシュから読まれたのはプロンプトの {pct} だけ:毎回プロンプトの大半を払い直しています", + "Every request starts with {tokens} of system prompt, tools and memory": "すべてのリクエストがシステムプロンプト、ツール、メモリの {tokens} から始まります", + "Heavy start": "重いスタート", + "Every request starts with {tokens} of system prompt, tools and memory, before a word of yours": "あなたが何か言う前から、すべてのリクエストがシステムプロンプト、ツール、メモリの {tokens} を抱えています", + "MCP-heavy": "MCP が重い", + "MCP servers' tool definitions take {tokens} of every request": "MCP サーバーのツール定義が毎回 {tokens} を占めています", + "Tool-heavy": "ツール多用", + "Tool results are {pct} of its prompts": "ツールの結果がプロンプトの {pct} を占めています", + "Reads files": "ファイルをよく読む", + "Files it read are {pct} of its prompts": "読み込んだファイルがプロンプトの {pct} を占めています", + "Memory-heavy": "メモリが重い", + "Instruction files and memory are {pct} of its prompts": "指示ファイルとメモリがプロンプトの {pct} を占めています", + "Fills fast": "すぐ埋まる", + "A request adds {tokens} to the one before it, the median": "1 リクエストごとに前回より {tokens} 増えます(中央値)", + "Runs near full": "満杯近くまで使う", + "A session reached {pct} of its window": "ウィンドウの {pct} に達したセッションがあります", + "Compacts": "圧縮あり", + "Its context was compacted {n} times": "コンテキストが {n} 回圧縮されました", + "Steady": "安定", + "Fewer than 1% of its requests failed": "失敗したリクエストは 1% 未満です", + "Flaky": "不安定", + "{pct} of its requests failed": "リクエストの {pct} が失敗しました", + "Excellent": "優秀", + "Good": "良い", + "Fair": "まずまず", + "Needs care": "要改善", + "Typical prompt": "典型的なプロンプト", + "The median request's prompt": "リクエストのプロンプトの中央値", + "Largest": "最大", + "90% of its requests' prompts are this size or smaller": "リクエストの 90% のプロンプトがこのサイズ以下です", + "Starts with": "スタート時", + "System prompt, tools and memory: what every request carries before the conversation": "システムプロンプト、ツール、メモリ:会話の前からすべてのリクエストが抱えるもの", + "Grows by": "増加量", + "How much a request's prompt adds to the one before it, the median": "リクエストのプロンプトが前回より増える量(中央値)", + "Cache hit": "キャッシュヒット", + "Of its prompts, what the vendor read from its cache": "プロンプトのうちベンダーがキャッシュから読んだ割合", + "Window size": "ウィンドウサイズ", + "The largest context window of the models it used": "使ったモデルの最大コンテキストウィンドウ", + "What its prompts hold": "プロンプトの中身", + "Latest request": "最新のリクエスト", + "latest request": "最新のリクエスト", + "Its largest prompt: {tokens} of {window}": "最大のプロンプト:{window} 中 {tokens}", + "{n} compactions": "圧縮 {n} 回", + "Reading the routing history…": "ルーティング履歴を読み込み中…", + "What each agent's prompts hold, as magpie's gateway read them: the score and tags are worked out from the requests of the range.": "各エージェントのプロンプトの中身を magpie のゲートウェイが読み取ったものです。スコアとタグは期間内のリクエストから算出しています。", + "No prompts read yet": "まだプロンプトを読み取っていません", + "Requests your agents send through magpie show here.": "エージェントが magpie 経由で送ったリクエストがここに表示されます。", + "No sessions in this range": "この期間にセッションはありません", "No installed fonts found": "インストール済みフォントが見つかりません", "Interface font": "インターフェースのフォント", "Code font": "コードのフォント", @@ -10811,6 +11138,115 @@ const I18N = { "Main navigation": "メインナビゲーション", }, de: { + // the context window (context.js) + "1 request": "1 Anfrage", + "1 session": "1 Sitzung", + "1 compaction": "1 Komprimierung", + "1 turn": "1 Runde", + "System prompt": "Systemprompt", + "Tools": "Tools", + "Files": "Dateien", + "Tool results": "Tool-Ergebnisse", + "The agent's own instructions": "Die eigenen Anweisungen des Agents", + "The definitions of the tools it can call": "Die Definitionen der Tools, die er aufrufen kann", + "Instruction files, memory and reminders": "Anweisungsdateien, Memory und Erinnerungen", + "Files it read, and images": "Gelesene Dateien und Bilder", + "What the other tools it called returned": "Was die übrigen aufgerufenen Tools zurückgaben", + "What you and the model said, turn by turn": "Was du und das Modell gesagt habt, Runde für Runde", + "Agent prompt": "Agent-Prompt", + "Harness messages": "Harness-Nachrichten", + "Billing header": "Abrechnungs-Header", + "Environment notes": "Umgebungsangaben", + "System reminders": "Systemerinnerungen", + "Compacted summary": "Komprimierte Zusammenfassung", + "Document": "Dokument", + "Turn {n}": "Runde {n}", + "{n} earlier turns": "{n} frühere Runden", + "{n} more": "{n} weitere", + "Healthy": "Gesund", + "Filling up": "Füllt sich", + "Near full": "Fast voll", + "Request {n}: {tokens} tokens": "Anfrage {n}: {tokens} Token", + "Counted": "Gezählt", + "Estimated": "Geschätzt", + "The request is on its way: the prompt is estimated from what the agent sent": "Die Anfrage läuft noch: Der Prompt ist aus dem geschätzt, was der Agent gesendet hat", + "As many tokens as the vendor counted; the parts are measured from the request and scaled to it": "So viele Token, wie der Anbieter gezählt hat; die Teile sind aus der Anfrage gemessen und darauf skaliert", + "Estimated from what the agent sent: the vendor didn't say how many tokens it read": "Aus dem geschätzt, was der Agent gesendet hat: Der Anbieter hat nicht gesagt, wie viele Token er gelesen hat", + "Context used": "Belegter Kontext", + "{pct} full": "{pct} belegt", + "plenty of headroom": "viel Spielraum", + "~{n} requests of headroom": "Platz für ~{n} Anfragen", + "{tokens} free": "{tokens} frei", + "the model's window isn't known": "Das Fenster des Modells ist unbekannt", + "Prompt cache": "Prompt-Cache", + "hit": "Treffer", + "{cached} cached · {fresh} new": "{cached} aus dem Cache · {fresh} neu", + "{used} of {window} tokens used": "{used} von {window} Token belegt", + "Free space": "Frei", + "Nothing in it": "Nichts darin", + "Show all {n}": "Alle {n} anzeigen", + "Contents": "Inhalt", + "Earlier turns are held by the vendor": "Frühere Runden hält der Anbieter", + "{n} turns": "{n} Runden", + "This session": "Diese Sitzung", + "Lean start": "Schlanker Start", + "Pace": "Tempo", + "Reliability": "Zuverlässigkeit", + "How much of its prompts the vendor read from its cache: full marks at 90%": "Wie viel seiner Prompts der Anbieter aus dem Cache las: volle Punktzahl ab 90 %", + "What every request starts with — system prompt, tools, memory — against the window: full marks at 5% or less": "Womit jede Anfrage beginnt – Systemprompt, Tools, Memory – im Verhältnis zum Fenster: volle Punktzahl bis 5 %", + "How much a request adds to the one before it: full marks at 1% of the window or less": "Wie viel eine Anfrage zur vorigen hinzufügt: volle Punktzahl bis 1 % des Fensters", + "Its requests that didn't fail: none at 20% failing": "Seine Anfragen ohne Fehler: null Punkte bei 20 % Fehlern", + "Cache-friendly": "Cache-freundlich", + "{pct} of its prompts were read from the vendor's cache": "{pct} seiner Prompts las der Anbieter aus dem Cache", + "Cache misses": "Cache-Fehlschläge", + "Only {pct} of its prompts were read from the cache: each request pays for most of its prompt again": "Nur {pct} seiner Prompts kamen aus dem Cache: Jede Anfrage bezahlt den Großteil ihres Prompts erneut", + "Every request starts with {tokens} of system prompt, tools and memory": "Jede Anfrage beginnt mit {tokens} an Systemprompt, Tools und Memory", + "Heavy start": "Schwerer Start", + "Every request starts with {tokens} of system prompt, tools and memory, before a word of yours": "Noch vor deinem ersten Wort beginnt jede Anfrage mit {tokens} an Systemprompt, Tools und Memory", + "MCP-heavy": "MCP-lastig", + "MCP servers' tool definitions take {tokens} of every request": "Die Tool-Definitionen der MCP-Server belegen {tokens} jeder Anfrage", + "Tool-heavy": "Tool-lastig", + "Tool results are {pct} of its prompts": "Tool-Ergebnisse machen {pct} seiner Prompts aus", + "Reads files": "Liest Dateien", + "Files it read are {pct} of its prompts": "Gelesene Dateien machen {pct} seiner Prompts aus", + "Memory-heavy": "Memory-lastig", + "Instruction files and memory are {pct} of its prompts": "Anweisungsdateien und Memory machen {pct} seiner Prompts aus", + "Fills fast": "Füllt sich schnell", + "A request adds {tokens} to the one before it, the median": "Eine Anfrage fügt der vorigen {tokens} hinzu (Median)", + "Runs near full": "Läuft fast voll", + "A session reached {pct} of its window": "Eine Sitzung erreichte {pct} ihres Fensters", + "Compacts": "Komprimiert", + "Its context was compacted {n} times": "Sein Kontext wurde {n}-mal komprimiert", + "Steady": "Stabil", + "Fewer than 1% of its requests failed": "Weniger als 1 % seiner Anfragen schlugen fehl", + "Flaky": "Wackelig", + "{pct} of its requests failed": "{pct} seiner Anfragen schlugen fehl", + "Excellent": "Ausgezeichnet", + "Good": "Gut", + "Fair": "Mittel", + "Needs care": "Ausbaufähig", + "Typical prompt": "Typischer Prompt", + "The median request's prompt": "Der Prompt der mittleren Anfrage (Median)", + "Largest": "Größte", + "90% of its requests' prompts are this size or smaller": "90 % seiner Prompts sind so groß oder kleiner", + "Starts with": "Startet mit", + "System prompt, tools and memory: what every request carries before the conversation": "Systemprompt, Tools und Memory: was jede Anfrage vor der Unterhaltung mitbringt", + "Grows by": "Wächst um", + "How much a request's prompt adds to the one before it, the median": "Wie viel der Prompt einer Anfrage zur vorigen hinzufügt (Median)", + "Cache hit": "Cache-Treffer", + "Of its prompts, what the vendor read from its cache": "Der Anteil seiner Prompts, den der Anbieter aus dem Cache las", + "Window size": "Fenstergröße", + "The largest context window of the models it used": "Das größte Kontextfenster der Modelle, die er nutzte", + "What its prompts hold": "Was seine Prompts enthalten", + "Latest request": "Neueste Anfrage", + "latest request": "neueste Anfrage", + "Its largest prompt: {tokens} of {window}": "Sein größter Prompt: {tokens} von {window}", + "{n} compactions": "{n} Komprimierungen", + "Reading the routing history…": "Routing-Verlauf wird gelesen …", + "What each agent's prompts hold, as magpie's gateway read them: the score and tags are worked out from the requests of the range.": "Was die Prompts jedes Agents enthalten, wie magpies Gateway sie las: Bewertung und Tags ergeben sich aus den Anfragen des Zeitraums.", + "No prompts read yet": "Noch keine Prompts gelesen", + "Requests your agents send through magpie show here.": "Anfragen, die deine Agents über magpie senden, erscheinen hier.", + "No sessions in this range": "Keine Sitzungen in diesem Zeitraum", "No installed fonts found": "Keine installierten Schriften gefunden", "Interface font": "Oberflächenschrift", "Code font": "Codeschrift", diff --git a/internal/gui/assets/index.html b/internal/gui/assets/index.html index 481c3d9c..7dd2dc59 100644 --- a/internal/gui/assets/index.html +++ b/internal/gui/assets/index.html @@ -13,6 +13,7 @@ + @@ -192,6 +193,7 @@

+