Let Compact continue on another model or vendor

This commit is contained in:
Ian Gulliver
2026-10-18 00:43:00 -07:00
parent 0a1f58cafa
commit 17f09ecb7c
11 changed files with 314 additions and 236 deletions
-3
View File
@@ -9,9 +9,6 @@
# M3 — Second vendor and review
- Continue on another model or vendor with Compact
Compact takes an optional `model`; the handoff is written by the old session as now, and the continuation session starts on the chosen model on either vendor, reusing `handoffPrompt` and `handoffPreamble`. Superset's "Continue with another agent" and Factory's `/handoff` do the same. It can't rescue a vendor that is rate-limited, since the old session writes the handoff.
# M4 — Merging and history
# M5 — Workflows
+14 -1
View File
@@ -817,7 +817,13 @@ paths:
operationId: compactSession
description: >
Asks the idle session's agent for a handoff (goal, decisions, state, dead ends, open questions, files). When that turn ends,
the session is completed and a new session on the same task and model starts with the handoff as its first message.
the session is completed and a new session on the same task starts with the handoff as its first message, on the requested model
or else the old session's.
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/CompactCreate" }
responses:
"202":
description: The handoff turn was started.
@@ -1501,6 +1507,13 @@ components:
type: string
description: Model for this turn and later ones. When it differs from the session's model, the session switches before the message is sent.
CompactCreate:
type: object
properties:
model:
type: string
description: Model for the new session, on either vendor. The old session still writes the handoff. Defaults to the old session's model.
Blob:
type: object
required: [id, content_type, created_by, created_at]
+1 -1
View File
@@ -93,7 +93,7 @@ Closing the window leaves the app running with its store and streams (`applicati
## Views
- **Transcript and Lead.** `TranscriptBuilder` is a pure function from events to a list of rows: user and agent messages, consecutive tool calls folded into one group with its summary ("Read file ×3"), subagents nested with their status, pending tool calls and running subagents (background ones included after the turn ends) outlined in the accent colour with a 0.6s fade, thinking, the byre prompt collapsed, held turns, `NO_REPLY` turns folded away, handoffs, snapshot rows with changes, fork and review, and notes for the other event kinds. It is incremental: a new batch extends the existing rows. The view is a `ScrollView` with a plain `VStack`, stuck to the bottom unless the user has scrolled more than 80 points up. The stack isn't lazy because a `LazyVStack` estimates the height of rows it hasn't shown yet and corrects it when they scroll into view, without moving the scroll offset, so scrolling up through rows not yet shown jumped by each correction; SwiftUI can't move the offset mid-scroll without stopping its momentum. While the user is scrolling (`onScrollPhaseChange`), content height changes only update whether it is stuck and never pull it back to the bottom. The lead pages back when the view comes within one screen of the top: the fetched page is held while the scroll phase is scrolling and inserted once it is idle (`ChatModel.older`, `prependOlder`), and the next geometry change moves the offset down by the height added, so the rows on screen stay put; a page that adds no rows (all folded `NO_REPLY` turns) fetches the next one at once. Each Markdown text run's `NSTextView` measures its height with one TextKit stack kept in its coordinator, and a repeat measurement at the same width and text returns the stored size. Pending sends show at the end until the server echoes them. A turn summary counts as read when its row is on screen and the app is active (`markSummaryRead`). The head carries Compact (with its context-usage fill), Sync from main, Merge and Discard.
- **Transcript and Lead.** `TranscriptBuilder` is a pure function from events to a list of rows: user and agent messages, consecutive tool calls folded into one group with its summary ("Read file ×3"), subagents nested with their status, pending tool calls and running subagents (background ones included after the turn ends) outlined in the accent colour with a 0.6s fade, thinking, the byre prompt collapsed, held turns, `NO_REPLY` turns folded away, handoffs, snapshot rows with changes, fork and review, and notes for the other event kinds. It is incremental: a new batch extends the existing rows. The view is a `ScrollView` with a plain `VStack`, stuck to the bottom unless the user has scrolled more than 80 points up. The stack isn't lazy because a `LazyVStack` estimates the height of rows it hasn't shown yet and corrects it when they scroll into view, without moving the scroll offset, so scrolling up through rows not yet shown jumped by each correction; SwiftUI can't move the offset mid-scroll without stopping its momentum. While the user is scrolling (`onScrollPhaseChange`), content height changes only update whether it is stuck and never pull it back to the bottom. The lead pages back when the view comes within one screen of the top: the fetched page is held while the scroll phase is scrolling and inserted once it is idle (`ChatModel.older`, `prependOlder`), and the next geometry change moves the offset down by the height added, so the rows on screen stay put; a page that adds no rows (all folded `NO_REPLY` turns) fetches the next one at once. Each Markdown text run's `NSTextView` measures its height with one TextKit stack kept in its coordinator, and a repeat measurement at the same width and text returns the stored size. Pending sends show at the end until the server echoes them. A turn summary counts as read when its row is on screen and the app is active (`markSummaryRead`). The head carries Compact (with its context-usage fill; a long press opens a menu of models to continue on), Sync from main, Merge and Discard.
- **Composer.** A `TextEditor`, with paste and drop handled as in "Gaps in SwiftUI". Text, the model menu (filtered to the live session's vendor), Interrupt and Send. Enter sends, Shift-Enter adds a newline, and Enter during IME composition does neither. Pasted or dropped PNG, JPEG, GIF and WebP images become thumbnails with ×, uploaded to `POST /api/blobs` on send; any other image `NSBitmapImageRep` decodes, such as TIFF, is converted to PNG first, its size checked after conversion. A failed send puts the text and images back and shows the error.
- **Inbox.** The selected task's oldest open item, rendered from its Markdown context with each choice's marker replaced by a clickable block (pick-one, sends at once) or checkbox (pick-any, with Submit), the "recommended" tag, image-choice grids, attachments, Let the agent decide, Other… and, for errors, Reply… and Dismiss. Arrow keys move between choices. A 409 shows its error. The Changes summary line sits above it.
- **Changes, Files, Reviews, Workflow, Project, Status, Settings.** Including the pinned-snapshot stepper, open-diff memory, per-task place in Files, finding diffs with Fix and Ignore, nested subtasks, TODO Start and Discuss, rate-limit pace bars and lead notes. The Workflow tab draws its stage graph natively from the `WorkflowRun` (stages as boxes coloured by state, `after` as edges, laid out top to bottom by depth) with the layout and drawing code from "Diagrams", fed from the run's data rather than Mermaid text.
+1 -1
View File
@@ -173,7 +173,7 @@ curl -H 'Tailscale-User-Login: you@example.com' -H 'Tailscale-User-Name: You' ht
Images: `POST /api/blobs` takes a raw image body (type sniffed from the bytes, PNG, JPEG, GIF or WebP only, at most 5 MiB; `ImageTypes` and `MaxBlobBytes` in `internal/store/blob.go`) and returns its id; `GET /api/blobs/{id}` serves it. A message or session prompt may carry `images`, a list of blob ids (unknown ids are a 400); a message may then have empty text. byre reads each blob when the turn is sent and passes it before the text: to Claude as a base64 `image` content block (`claude.Session.Send`), to Codex as an `image` input with a `data:` URL (`codex.Session.Send`). The `user.message` event records the ids as `images`. In the composer, pasting or dropping an image adds a thumbnail with a × to remove it; images upload when the message is sent, and the transcript shows them on the user's message, each linking to the full image.
Compaction is vendor-agnostic: `POST /api/sessions/{id}/compact` (the transcript's **Compact** button, always shown and enabled only while the task has an idle session) sends the agent `handoffPrompt` (`internal/agents/compact.go`) as a `byre` message, asking for a handoff covering the goal, decisions and why, current state, dead ends, open questions and files. That turn files no inbox summary and isn't bounced for questions. When it ends normally, its `turn.ended` carries `handoff: true`, the session is completed, and a new session on the same task and model starts with `handoffPreamble` plus the handoff as its first message (actor `byre`; its `user.message` carries `continuation: true`). The context meter tracks the new session. The request's `user.message` carries `handoff: true`, and from it the transcript puts the request and everything the agent does in that turn into one collapsed note reading "writing a handoff…", without streaming the agent's text; when the turn ends its summary becomes the `turn.ended` note, or "handoff not written" if the turn ended without one. The transcript never draws the new session's first message (`continuation: true`), so that note, which holds the handoff, is the only marker of the switch. If byre restarts during the handoff turn, the continuation is lost and the old session simply goes idle.
Compaction is vendor-agnostic: `POST /api/sessions/{id}/compact` (the transcript's **Compact** button, always shown and enabled only while the task has an idle session) sends the agent `handoffPrompt` (`internal/agents/compact.go`) as a `byre` message, asking for a handoff covering the goal, decisions and why, current state, dead ends, open questions and files. That turn files no inbox summary and isn't bounced for questions. When it ends normally, its `turn.ended` carries `handoff: true`, the session is completed, and a new session on the same task starts with `handoffPreamble` plus the handoff as its first message (actor `byre`; its `user.message` carries `continuation: true`). The request's optional `model` (the button's long-press menu, `compact_task`'s `model`) picks the new session's model, on either vendor; without it the new session keeps the old one's. The old session still writes the handoff, so this can't get past a vendor that is rate-limited. The chosen model is held in memory (`Manager.handoffModel`) until the handoff turn ends. The context meter tracks the new session. The request's `user.message` carries `handoff: true`, and from it the transcript puts the request and everything the agent does in that turn into one collapsed note reading "writing a handoff…", without streaming the agent's text; when the turn ends its summary becomes the `turn.ended` note, or "handoff not written" if the turn ended without one. The transcript never draws the new session's first message (`continuation: true`), so that note, which holds the handoff, is the only marker of the switch. If byre restarts during the handoff turn, the continuation is lost and the old session simply goes idle.
Task agents spawn parallel work as subtasks (see "Subtasks").
+30 -6
View File
@@ -24,15 +24,38 @@ const leadHandoffPrompt = `Write a handoff for a fresh lead agent that will take
`questions you have surfaced or answered and why; what you last pointed the human's attention at; and anything you promised to do or check. ` +
`Be complete: the next agent sees nothing else. Your final message is the handoff, and nothing else.`
func (m *Manager) Compact(ctx context.Context, sessionID string) (api.AgentSession, error) {
func (m *Manager) Compact(ctx context.Context, sessionID, model string) (api.AgentSession, error) {
sess, err := m.store.GetSession(ctx, sessionID)
if err != nil {
return api.AgentSession{}, err
}
if sess.Owner != "" {
return m.Send(ctx, sessionID, "byre", leadHandoffPrompt, "")
task, err := m.taskFor(ctx, sess)
if err != nil {
return api.AgentSession{}, err
}
return m.Send(ctx, sessionID, "byre", handoffPrompt, "")
prompt := handoffPrompt
if sess.Owner != "" {
prompt = leadHandoffPrompt
}
err = transition(ctx, m.store, sess.Id, api.AgentSessionStateIdle, api.AgentSessionStateRunning, "byre")
if err != nil {
return api.AgentSession{}, err
}
m.mu.Lock()
m.handoffModel[sessionID] = model
m.mu.Unlock()
return m.launch(ctx, sess, task, "byre", prompt, nil)
}
func (m *Manager) continuationModel(sess api.AgentSession) string {
m.mu.Lock()
model := m.handoffModel[sess.Id]
delete(m.handoffModel, sess.Id)
m.mu.Unlock()
if model == "" {
return sess.Model
}
return model
}
func isHandoffPrompt(actor, text string) bool {
@@ -60,13 +83,14 @@ func (m *Manager) handoff(ctx context.Context, sessionID, handoff string) error
if err != nil {
return err
}
model := m.continuationModel(sess)
if sess.Owner != "" {
err = m.retire(ctx, sess, "byre")
if err != nil {
return err
}
_, err = m.createLead(ctx, creator, leadHandoffPreamble+handoff, sess.Model, "byre", nil)
_, err = m.createLead(ctx, creator, leadHandoffPreamble+handoff, model, "byre", nil)
return err
}
@@ -88,7 +112,7 @@ func (m *Manager) handoff(ctx context.Context, sessionID, handoff string) error
if err != nil {
return err
}
_, err = m.create(ctx, task, creator, handoffPreamble+handoff, sess.Model, "byre", nil)
_, err = m.create(ctx, task, creator, handoffPreamble+handoff, model, "byre", nil)
if errors.Is(err, ErrConflict) {
m.startDiscard(task.Id)
return nil
+1 -1
View File
@@ -293,7 +293,7 @@ func (m *Manager) leadTurnEnded(ctx context.Context, l *live, res endResult) err
go m.continueFromHandoff(l.id, res.result)
case wantCompact && finished && !compacting:
go func() {
_, err := m.Compact(context.Background(), l.id)
_, err := m.Compact(context.Background(), l.id, "")
if err != nil {
slog.Error("compact lead", "session", l.id, "err", err)
}
+13 -2
View File
@@ -325,13 +325,24 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
return "Interrupted.", nil
}),
tool("compact_task", "Have a task's idle agent write a handoff and continue in a fresh session.", taskOnly,
tool("compact_task", "Have a task's idle agent write a handoff and continue in a fresh session.",
`{"type": "object", "properties": {
"task_id": {"type": "string"},
"model": {"type": "string", "description": "Start the fresh session on this model, on either vendor; the current agent still writes the handoff. Defaults to the current model."}
}, "required": ["task_id"]}`,
func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) {
args := struct {
Model string `json:"model"`
}{}
err := json.Unmarshal(raw, &args)
if err != nil {
return "", err
}
sess, err := m.taskSessionArg(ctx, raw)
if err != nil {
return "", err
}
_, err = m.Compact(ctx, sess.Id)
_, err = m.Compact(ctx, sess.Id, args.Model)
if err != nil {
return "", err
}
+2
View File
@@ -56,6 +56,7 @@ type Manager struct {
startedTodo map[string]time.Time
startRefused map[string]bool
finishing map[string]bool
handoffModel map[string]string
deliverMu sync.Mutex
deliverLocks map[string]*sessionLock
@@ -141,6 +142,7 @@ func New(st *store.Store, worktreeRoot, leadRoot, codexHome string, status func(
startedTodo: map[string]time.Time{},
startRefused: map[string]bool{},
finishing: map[string]bool{},
handoffModel: map[string]string{},
signals: make(chan []api.Event, 1024),
snaps: map[string]*snapState{},
merges: map[string]*projectMerge{},
+218 -208
View File
@@ -714,6 +714,12 @@ type ClientRequest struct {
// ClientRequestOp defines model for ClientRequest.Op.
type ClientRequestOp string
// CompactCreate defines model for CompactCreate.
type CompactCreate struct {
// Model Model for the new session, on either vendor. The old session still writes the handoff. Defaults to the old session's model.
Model *string `json:"model,omitempty"`
}
// ConnectedClient defines model for ConnectedClient.
type ConnectedClient struct {
// Commit The git commit the app was built from
@@ -1527,6 +1533,9 @@ type StartTodoItemJSONRequestBody = TodoStart
// SetFindingStateJSONRequestBody defines body for SetFindingState for application/json ContentType.
type SetFindingStateJSONRequestBody = FindingStateUpdate
// CompactSessionJSONRequestBody defines body for CompactSession for application/json ContentType.
type CompactSessionJSONRequestBody = CompactCreate
// SendMessageJSONRequestBody defines body for SendMessage for application/json ContentType.
type SendMessageJSONRequestBody = MessageCreate
@@ -3735,214 +3744,215 @@ var swaggerSpec = []string{
"fQtTsEYJZYLbCGVqL9p1/zLCewCkTYTa/z49F3dLGYCVExrFAafgh1PrRs5UfR9Rza7z2x72Z1LxVCfV",
"pLZ3hn8mgjepMkBOKkKO4o1fvqxjn5VIXVaitDXiiXUV8s/dJ/jcurQ9m2PgX+ELwv3dcCsChunb1cqP",
"4SvQw54WCREvCQ7ai8aaxYh0YG1BEs4OFLC+J/g3ni042TPZNOWpOmn8vCTERuTCI8qthK6ht4UKJD30",
"SERs5E8/xJ+v6o/TBOpiV+s25Igrgj2QybbrMi2MNI2IYonhWK10KF8xwGPRe5rTeo2X13WrG1owHFVY",
"tw5e/Amg/JxaL5WslYtCfbpqCTJEUg2qMsc0fIkU79Y5Uodwupta+SDsWpmock1dTMdUjlujLq0fgcRr",
"OQMyJldK9Bf8Z+vvsdzCmKjIkzMYa3ytgMF0Dzs1U6g/lolxQVLerqQRK1mrKMZqn8bXZkaHIArdSQeF",
"U41TOwxGeI/s5xepGYO0ilg22NgSwr7Q7iWQ6W1M1QtjsfchiABN6SXpuJDMn4npQgd6jFwOvCGhXL1H",
"vQRSOi9WMsyWQgeBWoRE9YS8treqL5hcW9soaWCagAplgUL/psbEJ9SC699QPIKbrc/EahP+9dsihfOb",
"VaPNTTZeNpMoKQzRRoYOGEJ7IPOg50DbhOAekypm4yNTEGW1KQHrbNi4U5ClpgC5tdUmeGEs3r0VA1Pd",
"6pmqhLezG4UAXut1T/9RawcgoGsOBzxQDxbR5HKzVi+wk/zJd9Rh/ugn6nyIp7iPPGIHaN7GKuHcCKb+",
"oD1cftu4ClDnnzqold9nsEpYnzZ0Ip2Tm/E7HqhSxrvlwnRvb5y1IdeuhiU9G7n9WjOTQdV7xkOF3QpO",
"Fi8UcMOIO+WUcAqURT0WKWHrAPi4sioBKx+/BPBkI+zDmq0B+2lSbFjs+7Z4O0pYbvGco+Rwtcfg9BBh",
"PaqHDlWugzBrTVSARhUtmoY8Ej4pWq9AcT+3s9ZP2zUMz9wHSQVhqTbiWgGLBQyH+AkMAXja4UuhPd1h",
"oKodURltkIU9+7AN2LWz8HMMQl6964FmnAiOa2K2DGnvJgzGijewm+JeRQUiwhvGp8Ghvo1y3UFnGnsq",
"HWg4OMWLHm+ngLKGdEoo6RqtXNxLPGJ4sa/lQh1wvHi+PGBpsUAnny9BeVZAfZZdfVkxdq2NdJvylVSr",
"Ru341Db1VZmoOQX0mHETmohrNbcsy9HLnTrLogGm9bn8Jeta1aR51nONP3G6+IvH5yGuZgiagmlmhJDx",
"aFUGuxwYCWijW9H5PvT3ogP2NlEmfasHzdXPl9+d/P8iqPfhHP+Fk4uUv8zDjEONeZhDTqV6H4p97LhK",
"cGpL29SeTI5hyZxptDPBkg6/PviqZhjlI/P0xsD9AjTuW7BeAz9YXNIIvMqzom7KQ5tam8VFtA0OOcX3",
"cACI4Npci84GUyvm+v2UGd76TNTar7T3qq6Q2jdqHkBvGWH5WrmFEnfSgY0uZ71woCKLs4vv4sl/xx/z",
"n69iH4Pl/byueZF9GCe76C762YPTFpHHp0Xwwi1X2NbePZTZ4HuC6Pbx4u+IAunFMoi1NEr4pb3z5/n2",
"xIYk/tFlRVdnKLuMXO8DwKX0N5fymlv78vGHN3SVw/UP6gO02KE2z7pauam4TJIPTIu+IGEgXekHXWj5",
"fAZX2qiF9pIBNAK/rX3YR2kREAS90ua/Mtf2/augVoX77LEYtpGuhmY+FNYBKJ2bEpknqomTQV01elX2",
"3+ozWH3wxk7PSL36Pognr6W7ARUTaeRQD7G0eob2eHTHkl7854l4Io7xjvhPcYp//lP8c61nNyfWoFT3",
"nyfiL+LXvN1f3v+atwPnAPSbQAQ6rkScUCXulpur6wYkv7oSFifsxRMlZ0ue0JHHnjpMPa7Eqm2CXoNi",
"MriWHHziOMeVcAr0COgoIJ6gpV66G1XHBR5hf8eVkMnk66eiB+wzgf9NRQ7yM/ZtqbKn1H/yeYEXJ/SC",
"Lvnjinv6qymp5/dwvU5529zeE8/SRyNmvJ4/5UEHGk/LW/6sdKwPotPYC1Pp3QZT8hq4OtjemEGx67gg",
"euU9J86/4/ijI0HPaaCD1igdIcjU26TkEyH9HOeBkoA2r+jzb4bAH8Dj4On6EivfnYeDZ5y5TRQQ4yF0",
"slaNvlXu81BX9DUoXIlgVRe69j0GKlr5yEPBCwmSrtd1lCsIbr17cBt3BxCAllejFp8k/Rze4TgnzQq+",
"g/EL1F3wIQjvB560uBr+KCnEGMxVD4X2ytAlbP8CSDmGE5as2tbxNUTqknR/dXfodUQe1KGTwQcQqvpa",
"sGmwrjVNm+94r0y8Z8GLXM5Cs0GzJ/nHpXu9u6L5lkdFXtYoB8r9lhFxuAB/miY02AYmMAt6thQrCWqo",
"3IwSQeyUWOhbZab7tpBeyyYbCfcn54YU8CQRVGU96MOO3PBkpUOF/e09KZc8avLuXzO/iABEnzAU9Yos",
"YnYL97pQ0IE0/k45VXd94G/frpXzqh7hOn9Qsv7Rls7uZ2ST+5zSbvnLYFABRIUoL4LtiQ+S3qLWsmvC",
"zpjcSXmvx+guK0rvscii8yN0P+A9sp5LSPGa9NRjhHPv1fcJ1Atme78jP+KI/hoes8FBe/IfRfWEDMqh",
"e/BU/MIOUeDQp1zmgNt5n2LvVf4wd1BPqsEYEMCa6p37PJjnfpKzXyYdUzL9aIOecwTTG6fmvqT1BcJn",
"1J3QcIBJjkJIzbXRfqlqhJ0H7NbzDUGTtPKG/bPQ6I3mXdAL+22XJBRUCmP3JCMauawojOS10Mf/iK/A",
"agD+bDGuoNhRJ18VuupeqnrXbJxaW1fq4BL1DAgtJAPKkLe2kMK3q5V0G/EEXk9JgsRX/OJMgLx5fIDS",
"sYNFN5Mqgri/whJKvJFGjWioaifn0Zo4WBjIwndL3Sgh6WJDVDFDpQrpVFtD552P8jYA0Q6k6p3jsL8H",
"OO9qU9s7tPjhh8mYzt0IRUERcPi06figNK0DgBpnVHVAKAPPBT3Ta1nSkdfarxu5uRq1zC90uFIrqZvR",
"t/HTUpBB8urAw7eUqHD3KgiJbjK6VibosDknY1qA1gsVhLEiOKkb5aafwZuit8ZszvniioCjKJXPc5GP",
"AhgOQymiCp4PPMJRMVQJrxz6sgSxDGHtz05P/9o+ffrHGVCzIy+W1gd8oM7oOfRED06nn2Yk7LQJDECc",
"/F7J5g0xEl8kjI4p6dW1k2bEIjHCU43ukFMrG8Zere3VYRaOHGzdZ1sTTsPdz1OcQTzG/exY28EL2Jr7",
"yDyCndlmxOvgPhvtJB49iBTkWFiKqmGf6lHbQ1TXRqevYt9K+pEIln3RsEVPpTgu+Au0TSMaZRZh2fNY",
"2j52h8a4cruqH+zK+jhcBwGLJ7d3W3zJn7Hd6XxdMkgPHCrIfxCAQJYVWct1UK6LEFhL59lHFv92amYX",
"RntV8LWrxI3akKs/rb7ozg07bEZ8D9EVnxog41wBu6g8G3oOtt708fnjHn0jgzHNrLQVb9OlMqD4hqWM",
"LrA0iz3dNmnWVuFt2npVcdimNgtYq4jhOxD4sYxBPvvtOqVoiVsM0+zi43rumv5Gr9cjbt0PIe0jgSdz",
"4ATQQX1THGpOJs8r1FjvROLDDadVIaizcxmVde2URzYOLDM8gQxpdfBCGwgX1EZQqMeUW4H9Ln4B8gla",
"ghQaPUEmKSJ6lGo+h+pgRPR8edi2dmErQ+d5wx7yOc601ysdruhJF5px1gkW0ex2HIU3hFBFYCVRQ90q",
"p8OmEjMZ1ALd9oIOjapErYLUTUUuLygma6OK8EvxbKZMynzZq4ABQevKDpUPas0nC9NVoEtsJbyFP+L6",
"hZMm9xzoopcBVpOK0XpSxWEO9CUg+jGIVs4evqDesyffxYGyZxdxzIPzMDwAXXaHtWabUrRObYW7RotU",
"NAD3tEMDIlCivBzN/XtoiNbOrtYP1RGVtH+rdTjAqYbaFWHBwH+oxR8906/8UpZEF3qLvjROKWjFKQw4",
"hkn3PaGPvPjzy2cveqF+Qd4o8/kullta07txV4sjj1o2HzjrTJJcI5ritJg9iUEoKmoPyMXbh7Qu0a67",
"CN0DPMLGZJLtCb+xHu+2gWwYp+krwtNvzpkazykCa+5PgcE6heYQW0PH8OMpfHf6wXy8r2RYTeLejrzU",
"i0XJ8RZUSVfK1GccpsRCqzL1iZ2fwFtGn2kM1QBwyz7vY13nvCP9DScG0oGuDMCdqwiPaVJzPumOKSXa",
"QZ0QzSK36WC0E4Q6gbsC/HEFf1Qw0BVf/6bG6FMHyh4lHTnkWdNtAuEvcALRHRXCf2qfXwg8r0mVYDKp",
"Jmm8STVJA04oGMxNqkmCyYG3RTznl7Qfr9OYgxeXrTMvTV14YW3znOYzePPM3/yZZzf8hic7ePy2m/ue",
"q6FwG5hJj+pk6Jcf7w7x9krMF6Horoz4UCYTPiBlJ1JGccKc3QbfiIWC03e9wYin85STyQsL4o1sGvYu",
"hMwdtyqpqqfiGRlk8uRV6lbbNnbMJx1dhp7EcISUamehKnQDO+7nremGTxaCa6fVnHxvDr+GrqUv+12z",
"FQFnAF5JoEcmJYaiMaeR3uPJYz3HMVte6YrAyFmj+BTSaiNchAxofiY7Fb3D8w2LrbJwVaC3c/DLyyg0",
"T2AlNZt62ZjV5fDhuU7FWzVHjaw1/WGIGID7+GCG0fAqmzu58f01i2ypcQQEeDz1BJJJNYGpHXqIYdQ/",
"Sa/exI/Tk9fYyzhbn/A2xTiwcSguwVs0CFOCEmK5PjlPy6hqrT+3nwwra+xcfAO35TdPnwJb7eQsKOch",
"JZR+19JuaNPb6uIoHVu0Dwba+ODa2Zgpu6z4imzoLq4KRnkWguJ5HBY0ium9iJ70Dkc6XfmRKK681n4m",
"XZ20osPUH/wWL64Z2BJUfdWuQaK2onurwzkpYSKJwaZjkez0WdHyEoMypHhBrXonM1pCkGCQC/6ssXAC",
"N2rU9rIj+VjmLKu9kAR9HJE+w3PZs3rnZIvIKH9VXKk2QOjL4/J3w0uhS8eHg5PPyFq5nIqgGgA4xaWk",
"w0fZZY78wbopxLZXMLsS3R5LZHG5jPh0RchFDTugeJ6lDnCjJcBRmiMd+GNV9gEZkaRZ+KVgTuLBtBcr",
"XSPHNxW6btSZkLOgb1WVGXJ5imw4IqEgnYbuA7xGaBlOzSxgM/B9bgH/JwQ/635GMzh1BT7+vXPRtSNQ",
"pGbABdIZqS25SiCT3YLVvXMW9530MNfgVtM7xb5/IXR6AU5zFpc3wdREi+h/QhOaVJNuoodmPyMkHSY4",
"y57GdGjZo++6WeSPX8cZ5Q9fZLPLnz+nmf683qtmQI3OfexP9EGnE8jIUTqxoxSazkwpvmJRtpIcHkUX",
"mKPnD0amEEqWbELmK/h0RONObDEneyipKl7i5YzNUk4IxFbtRXBydoMoDHjWJfCL+eYOJju9vK8lL1fK",
"5FCYHSj1agz+nVGQZIU5YzDccr0mEYl9Dww5aJAsTrkJqpivgKPhQQa+nzJ/mNahMPn6+gotNgcGcmUJ",
"RQ+PyQSH3qux7IHP8s1TXsxa55QBp0QmFGVBndnbEcRZsxXjqnNqOdjo4QsuKHuMRB2uF6xkpGTZCg0g",
"lS8bO8hF5GAzEAHmCp1YChcePI7Qg1j7hEjR0nI/LIL+3qp5CXu8V1cZ+hcVze6+yqtCvuNy0kn02JRp",
"pQAOdA5dWDxUmLiqn1qZb0FMWNJi5LOn9MplJPvNrq51ie5cRGLCoSVxCiyuiQYT3xFO0/UuB2iOVAo4",
"IWO7bbHu4E35Xzi1vQa6DP7ZWd86x9l5qvp0ub/HHbHrn+ohTvYP0DYh70Bb3u7tE1y8WMiq8lbJQvTF",
"qPLTq3cx6jFz84pKUOtVstYgE7+0d+YgnWYhvrw0aXA/254tKB2uOI/h1oHY4dpBgsTu9DcoK8BaiLsi",
"izQzMIdndJnZpmQXecVGP+YMf34VNSNr2agQFDCQXi8M+e+gigo9sKWADlsH+E8IR5+heplcOa1h30oM",
"VIXDrnwQcmHLh/UxfGseR+bjFC+MZTEl/J3UmCIrpd/IyFoV/0IFUY36mf4I4lpBY6dW9racVeMBGbdN",
"PCjJJqB7gqYcSUZ4D/EVlrJLdM2EjHslvgZUZ6LiRhwQuh3k6GdkxLJPdu0Kt0h5yPGST2DC8GuQJ8ob",
"QbMbU4/g22iEfddKv0wGJlNQtw0TSjkCqLGcF93SuS9CjybyrlXtLiLC4EEXo5g4nP1MTbc/UWubIpyZ",
"4mizSDuKimFyxYYuo7rYdSmmAOZL1dyDMNEakkBVQDZ4lTC5B1Ba2UreqJhVERETP+jSHEc3leDTgtlU",
"H66y0UchvId+dODNqQerADrZXwc/LB9RRcMQPqeLDL6NIhAtFhuuW/zBGjHrY8p8WPA4ksKNDrT9irW4",
"O1ZBO4pQ1ugJwTjBrmzUwQCJIg3jl7xkvqZ0GNeP0QdX++PJ6UKnDWRi39GdqIeiud6L7AC7flW2FFwm",
"W0XkMjJnVngG33rxJHUBRzT98c//dlyJtURfGwYdzR5hpdwK9SvSizc/vb3cKRrtLW8xkgosXii1ZRef",
"dQB5JKC6DLlnthPLFeclpLx0MClSlpOnCE1fPCFT5hSHZTaLEueyCEStj89K7AkRDLo5K6Ear0R3J1eR",
"vHDkBw5g5x3MOhM38uMpTTsRShn4YtZ10/Moiy709ATOmo+vr9aK/Jhi2QMqJUH2XNwiRKjOc4b7SPkv",
"reOLmp1IKh4dMxsQNz3dpSvrTyM9oN+R1gy0Q0WlWhztQJUacK0DfVp6xMq0rglO6U2a4uDF4OHrNOn0",
"6EU++15DVedPcjVcevijfUbrKuf1QVazDJT7QaL1z2Jf3aOtOba+myTOiJi+q4Okk56XxrasshWYci6e",
"Jp8SEi2NOkh0GddHVpNga3ulOVfGnsv18qcXP01XFJbTFz1y68C9CG00gJVHh12Jg8eW3cBzZ39Tudgh",
"nixUgK35JbaNtoiZXW+OB5GCNHlWJIwl5oyjXrnWjLDVsQlxGLpmKond2zn0TCbHwTL8Ujq1GyhXSYO7",
"d9gcUvgVR9zBJIDCjY6Dbgf38PjvZ2NgrXXOoyV5dth/1UnB+QUbRc8scdaOIg+sHt9BCoc8TVFY6J/U",
"MTmekqL5sjhfxtjIyTvypgLNjnSpXkhijU+gh5wQMLOfWKa+DFCRS3niBzt/iu4qgvFG3Imbe+SoyJLB",
"lUK7nSot3Km0mLjnyH3N6SyQpIJ5IRE367SQ/fMf4CCjDM4jLm10+0YcI3e4FvScCojYknkc666NBIKO",
"W+ovSADa8nXnMHTtI49KDCV7UFU9FozZ6an40fKHO50Gxin9YaRWCi8hGqsjtxbJlzY+KImVuYjcsm9+",
"oqKo6YHVnRHf13NwyQ3FXlyrmV0pn/LMQx/sBV2Lv04oygv/xJ/qTNAj/Jwe/XVSdcH82BRA2RkvyTVI",
"XGa5GKKbZsa8W6/4bsoT+IwZ6xCyY8h2SZm8IiOCjDOCGEgY05GIsNUkcvpo3Lu27xOn5yfZRiVqezDv",
"cn2Zj3spr5+noS/l9Xc8OrTrJnApr1/xHC7l9ds0jUt5/Us3k0t5HcPefuUl/7IToRICyfy2zn1imbJX",
"dAjwUVjSCRsEdSoQk2ONnu2h4kRepHbQ5X88e/3D9B6hi2UvmWzs4tYzHC84jGroIdPg/ytt9Kpd5Ql+",
"MubM2bu9rbYCcxo/4S+L07K13Z6Oeq998DuTjg4uHipWmRg/SR5ug8zBmeCerpjDLE+2tpimbZ+Zgyce",
"+x9bcTnl27WtN1zucTsrGnR4RLEtJhATmXSsoxF5/NG8dQg2jBErWrrIqjvCWav3TIWUMEo6xSnkUYuD",
"Wcfj/AoaQO3Hc8nvUJXFiSMFhGlXiQGGfUWHTDR5caKWCB0Oa54eSCMrgnkHgLENw/uxGMQ9a33J9Kma",
"XGXXBTDdScyNS95frfdp9nCVzpYymQalYW5EcwWDEeXYaKzCoYpIHDxYkoymn3K5sHm2YAHbGdLw+NVI",
"S7P92bDkPeItWNhUqhbho/Y754Ypj4tToMYpKsfLGrI9mYcTQzyoAAiPaUjKRZLVAoQ1ich79jusJq2h",
"tQVMQoj3beaFglQE3e68cjtmlfVSCJKQYemJapVH62ftnxxwgazYdhtZkmx+/XTF+cSKW84Jxh4tEcPB",
"+RKqiclyrVytY7KVXXfQdnaWT0m7UJzBGNDG8uI+GDKDiR+cGGKbfypFQUWGDi+QJnmNU8BQJudd820C",
"Q7MpFNl+joIEYUL2ef/ObkQtyYFjlTw3B+EFF1FfHosMJG4Pufgh75it4kOBi17YE3h4Ahrbk5g47AQr",
"WShHZbpI1bi4hxRNwRj3yu3II+zan7dtoXQzSjpjqSOy7dw13QICZFG6uxnGgkdoHXEDi2yxUHbPCiqs",
"byuZN4pRja/S9cArOPKUT/Zgl5sMymn7tvQfh/l18qmDNXRKMtqo3rb0nGMPQ4AHh/n0z1QmPfdAxter",
"5+xp9f1CPKP7+LjFji9YJ0133imehhNWo6+0dTeeTD3Hybntfk5tvciFwkxH8W7EfMZ+AmeYygdIFtgu",
"BZaTudNebVuoWK2fRTrgXCgBZa9J8vBPNnLMshTJXc+5mqcxqbZNR5/dzRpBiDaXX9Ko3bPOUNQ9Y0tR",
"9yBzuu4eJiNK9yi39HRP++7WvPSrMXmqp2GKaqch+KPJ+VCULp9rHCrTRmdTy87AroPMrm0FtmnXdXV/",
"3UXXWWk27GRYmEQY4z6G+cyjXyCLkdEHkK5h+JXesCxRzmzek1Ny/9KHyjil+rtVXNg2LD4igz5HnQnT",
"+Al4WaCw4zxh2dPp0+lTysWqjFzrydnkj9On0z9SnYclgg5r/8l6pc1pZ51cKBRyAcTIF76qJ2eT71W4",
"iAaPXirpPzx9mtUAhp9Ii4mlPP0b5/khQncAGYQRcH1DF1d3q5xYKtlwtonWY0GZj9gY1wGZcHFK62JJ",
"vItgnfJZzWfrROvRgUBGXTapYEEdENWvTt5R+3NyedmsUZ1Rq0BVV7vozk1QlGdu1XosyPvmx+8r8e9v",
"Xn5fie9ffQeU9Bd1/WYqnnGl2n8Rr/WfiGD2Yf1zSnLQhRz/idVCGZxxWqcLPe8DuKtDmoqLbCEbffq3",
"tVo89Nu1efCnd+p6fd9veweEmdwBGn7z2dAQIV9AwsvodFJj1uUpHK5vnz4d6y7N7zSlL/r2mz8e3HqA",
"2Kcf4L9X9cddRzThzM4D+g+GONubCJA88nRkmbUkszuCCA85b+6399gudASTKxWUA47kw0TDeGxMpptw",
"Qns4GWJzla1puIJfIxoMyjhneDCUfX9R1xdcvhCoJkk3Xe1oTMZKBr3XcsaunURgPcpAvWLUpPplAtll",
"0qTZCMrS7LOUQVJkddN7H6On1Sb6+qG5UNdoPpRmkxd+GVYpReHcZ8NC9KbBND95NFIkxdjzEj7n0sf0",
"KXDmmGuiRHM5OImmPjxC3zz9ZhvMF5TTt45hiB3QY7TAvQlEd+R31+Md3fpUWyuvhQxXHuXNGWwsbnZF",
"pbYXv6EHmAjSoY4EdklD2CnALGo/sJaZuKAEmF3OVb6ihg7K8BVswGa6Be3vFUP6khd1P64CJvtZCAFX",
"LH6kw97t2P0OfDVZt4dvbqrNPNhdFF/n1t1/g5/NZmod2N+x+qSNftOWNnqMo/kMe7yPS/h2G65vOVPl",
"A7AgHteuymLxWBL3eoLeXNR0KjAcE/9AkxXAFODo1btzUcsgIwOKFRlhC//94qcfp/Rn1DT+IH04wScn",
"r15AXXT8gt69azGJfETSYyGdInq46QKw0RM1zugXyt6DMkoVq9zJEH1BFI/slPBIgpHaN0rW/w0xOn4R",
"O4ymJUing/noulqfaRkp2vTOKCcWlvuwXSHPEq2mZJcvY6XI0kGke6M7ij1ITaoSVo1HUnGfCNGuyyRW",
"f3pXWVa2Uaow8ikAtfRdl7X6172kFe5oQuETik/sn7u9lPRlFib8CYeIXEvGztCrLtX8QMkmvtMN7L4w",
"0jn2uOSaIQ6RSWbpZ5Iv5ZEX4DpSwi+okBx9TErINdiCno/hvTfwE/Y+KnQOk2ryklcHIMVu8enwAlIj",
"HhNbSPQaak/SpaRWPul7tUseUX4qXkR9b7AUoc4p94dYdNpbXFkf8Iw51zz5GI2tKecQ5s9Ehc5UxMYO",
"+dxexkFoGhlctAxpvCAxzB+YZdSRsg41JeJHMtqaWOOkhIVcyetVcrg65Na8n6Dbqxh20PX5e2MJ8EBc",
"iSTt/b2F8Kff3qv1vz2Ulp1+gCnuEdm75T+iYi2DcRmmMNFOEO5O3OMwxgSWh0nBK7ULmq/VY4IRfQdG",
"IAhsDpAvZFoYEG1hkmRGf60e6UhnlvpHONAPBU48sgych0rFK3U6j3VIxjCACpU84jppgMJCU8xajgpH",
"PqsqQhVk+9ixJYtYV/vMV4xKB0WlSddXV723Yq8EJ4K83hbBLnKYfH6Ey8Dx5XBtdA8yFS1iyiNfDz3U",
"BFZ8nyR4uY0e8BmLTH3GtgLGVVIY693SNhRY68/YE5zEvBhv6//5m6OwzOOyslJT/BOiuZ5YF//MQsWz",
"pLv8UnsOPzqeijcS3clmNxB5uZY+heviNJMQC93LWOJqjK+G+mw7JbcBj0u9fSYxi7OBdF2t5HvyYf6X",
"p0+r3R7Nvz4iOiNA3qATxzZK/4ypjLlEFP77JHoV/stTCM9tsL4Rp27wQTdNlwGmtKPTEt5G/e4O+xmq",
"hpOpLKo9S9jMBRJTnKmkx4OQ19wzWPySlEzYNEtPNyyWBvH4yFj7mPI7eGFAzYzIX8A7Trv7A4nKj0EE",
"+9XvDiKGf/hsg2OEKecAGqOJPfjnAL3jJOrWJdhi4p9PuaMRoYwNapwOjt2VHfpwzCgG5l+Dy/eSRPsN",
"evYNVQBpjTdKrT2l+c3Y2ZVaXSsXvXUWKmBmaT8dJVE/WspM9PjiTxztUOkH4TodhfjpB/iPZQ70i1Xb",
"bNILfJ5GPkRJSp/UjyQQ0JwfKhDQ8hm773/39uq+bCmXnlFUJJmY4CfAgTM2mJponOewCCpeV8aoizi9",
"L4FUfZJwGGJFAAxxK3cRpuuhLd4OwbOhcVgYMlWB7IN/ZzHIksy07fv8OMS85GP9X1CSAiHiJIlTO6WR",
"u8yBlqQSsABZBwktt0s6kldk9s2GXKKzGo90+2e3/gYVYlmXOlRZkQHKmCKNgFgngbmHmk0ceSY9R2d6",
"vCOsbQSt47qETBcqdAUtHweDuv4/wSZFeXQ/aYs5avzEKVnvdu3qctd9MoEay055SN6HbTe3QdCLdeRp",
"kCdp2yIswDk4xBvmiWl1ws4Jp5Z6sST79zts16N4eSrPIriAoL+Jjb4EMefBDqHjz5omagWSmsH6wiKI",
"U409P9Ip6BVF/MI+XAloI1yUuusKbD/4iEVQn37gX3t0vTm8H+nu2LPu/po/NxuXoPAwTq4EztOUkHn0",
"MF5iiy9xEmGkQ9mpzuSIKxgWQPya4F+NSPx0cnsJIbK8Hyl1RvK7GivywQwBiGOcnoK55pQbC+MMetki",
"qthGduloZEivaVAdiq5cOG3cq8chbFm2ji9M1QgBx0ka5c/7QirP8nHlUP5RCYxkAjvPo/SRf7Q2BZiP",
"I5I20QWKY6W2aCzmEnhEAov977Ci+XNB8f9CezGXjVddOYJCtgJjIyD+nmiyrW1HmH83uhRTdaBPR57t",
"q+I6FFFPDc+ipjBlEKty+T1Ron6uhZilpZfwpqtZ1E872kscLH3nigo9lf2YpAspE8Qj0aqUt+Afj1Q9",
"1HjPuW1OP9APwPhYG/X0A9aV/XgY3sfv74X21UjJGBgfjH6DAoQ0xpGPTWIFwqcYOLY9J5z/IRPqmT72",
"GCtlKJbn7SrtYqomzBRN88VCbZ7TV+pBGU/MV/wes1NuhF4Y66hV2baZFw5+JBNnNsTvY1vnqtUjx4lA",
"+sXu/cLx8MGuH/FIjN4EL8kk1U+DnRKdssbfZTZ1egFkner/drS8NY3yvUZdZuMC4gW7fhuT830N2/74",
"VDHqh08/8K89wm5UPz8ifA6xfPFkH4m7SqB4GHdVgukp2xsOO08PnMDYgXpGMe+qV6UoJQIkTmspTW3n",
"c/FkYWVTiVrNNFtO0CEVnshaUGwJqvaT12NFtbqPQfEbsx7HZOFcZoGHhMMXjS1k7cWAn2F1fsr6jIFN",
"EHiJaRCZo0t8XJxuKXdhORIIwT+Kvl/WcBtnj2DKctf+rsf+VJugnGvXvw+Svox5Org6Exn+tzbyVZzk",
"V7KVCWi4j7WC4Av3e+9kz+/jS2/kRVTxoECAGJ5SjSYHhVQJvKMMQJyi8YiFwI5UbVUlGPiPUH0J5gwk",
"lo7N/Lm59mL0KInFqFFBJTs77wjKgY9MV+T5H9LTBMG/3CJUX5uMlxVi38PHJEXiYymUdgjKmZD82YMT",
"ceUPY1v6wDuddYmni2q/l122rX7V/KRCfpJytlUp53Jr6BdlezBYQBGew3rVDP3KpgsdUD5UxxTkCJ1V",
"/TTW98hiPa52jNppzGtNJInSK4vLLJHdEQVRaipChY4PIth2hmnAMLouJpAmooRL1yw/Z7mlOXnx/oVQ",
"0DpAbjQTd5z5rjzctCAf1Bpn49oiX8RHoUvRO8CxYRA6TyzYuAyaSJaZub+gSvh2tqR9RO+GSLOjf+kS",
"TLWYV1o2jb2LYImLSfqOYZQU7NnkXhqXZzmEzBn7FUSs6fL/atPfO+Ek+zzIWDP+tp/nsDhB/nqyUwlT",
"FdPqx2/P+kAu7jYlrkp/0f4cpWI4/cr2UNF+dMJBrT815vATrS+MhAWy+Ua5EzQR+CDD1xYe9KUJsz2R",
"bVhaN06bL6PaLlVQjrhLcbsxp0NioHoEvMsbLp6gc09WISh+gjRoKWvMvINuYRT11nHAHIROzmAAhWM0",
"9KCNh+mEdkMd/LOY5nSTzxaoMiejwFpuNPmFDikrMOSniGBR9Ql87qRuypHG36vw3D5jEH4RXw/pgp7p",
"tTThUENzt8lfP6cAmWp3omJr9FyrGlPaxnIkeJq7Ekd4+eF1l4zPi97VNB27ul7A6IdFHVDu3Hsp7Uv9",
"cOGHT+6HN+ST+7FNHaub7BTXHi9wRzcKt2HMawKigP+xiXat3egR+cmoLPVHvzJTZDOq1EIrHyOJAgaC",
"bDjBx0sT8CX8VSMXje6XjZoHYdtwLhJfXQvFbaFBTBNN2jYsNgyEGEBBjFCj5C3L0910wtLZdrEU0ylF",
"3/vNqtHmpkIhnbTvO/jNF9rt4zUvGumXJ15Bo0AiQiPJFmt7c0Eng5if3jqOh+mqadpxLvJ3PTUvtPsB",
"C7ePJrJJSHHk4479o58izNF5mFrrIeOO6bS+17eqUEMHLrJa1bD/qiYlSbDizumgUuPoqFp1pTe5SCnX",
"IfFDJRiG82nDGrRefFVWde0Yz6tN2V+lF95S1ZFhaV/WxMeEpMwSwgtZcxb3lZIGHR/ORe3smmLPMHAI",
"GbLz6P091O9DAI+6Re0aj0KlK3xRIwCdsHgeaz5wuaxEfLoPswrS4rLrjAx/VQQrfsi5aZxaSW2Gnhx5",
"wclUzVE2Tsl6w5US00jM1vro9sF1O/25AMjm9T4xlW27ZosjLJsoalimdyX6x1lmy+qnP3wx9VPFIYW0",
"zIrXVG9XmZ7+Pqq7QyJuBxmMUMcrwf17GOxDka79INdGsqs4RsBK/r4c6APAvE9062fMIYTV7cvBrd88",
"ffTo1oOEG4TMIWINhbziiuKmZTGvT4+/fkEHZJYdCRqdWrSNdCTalHWiU3EJdgbkkbhuQLumbEZe/6YI",
"OueCcqFhR7ElEG7euEfnzoCf/7zs2R4G7F439KOKMc+5oxHaCTvyj82CYdLW8UOQ8jDrhsX4ojADzHkq",
"hIVfUA5S+liGIGfLFSWwQ0ynMHfbtEEBQo/h2jlfA05529wCrWfER+VuTOGsjde16n04HeR1rjCrM07p",
"4n9+X4kZ3I8oa6n3QRn0PRk/P69WZCo8JM3Y5z8Af6+JgP3t4p/fr5rfPY8woG7MI/ygs/7Hf0zKgILC",
"lxfNMEY5IzJZHeCUzcKauXYrVVN5NFacZEHe6HHEbqooFnE3J9r0q9Npc6u5RF+w6KvHdTew46IHlDCA",
"hk2zqSga2r9rpV+OCEjaBItSZbSzUT3Srsro9hqt2WPmjFrxgVI9pnUuqs2RQJPCvaeO6tTSlVi3uAzN",
"mSb0AoA1h5Scc+vuZHTO7CY2W6rZDUASq/bzLuTiYklOLMiFuPo6uYqYrr535Lp4zJ7E19VQiykxotHy",
"CYGTXEiusGa/8Coc56EEXBil60FjVd6FU94PR41WW4bZQLovJbmgndSg2Hsfyw8sFSYTDLrpVj5rLGZM",
"HIQqbHvHsO4rzTaKu7DulBMWU2aQnbBiL0CWdzESm0DGT7ooMYapqglZ4VRQH4NoMoYuJSKnFklvAjPy",
"N5Rlm+cYxBPaAKHnnGwx5oo5rhJI4/wIEOmc1jFHYz5LbfpD//nlsxcxLkmZOhoi7LzfjLPxFMp4M150",
"m2KOS7qGDmKDbRGYVTnfDh5kCMmpeKkZp3GPOqZ9qNIoqCqiC4G9M7zTedXxSsBxgTEZsTcqnA3TQDuO",
"U48nI++gdzhWslYVaZy0j4QlhQXiQ1pC1Xl8cTd9usIZq5IZm2vm9IrocBxE3zavPWsysrxXlJ9zCP3z",
"TFdGuwCKrnWkrjI3exobsoCgJ98+/bfjzpVchoIveTFBkVt8asBiOeweA9CqUvUt3qTtWxIn09W46/vW",
"x824xy5kDh+mVwU8L2Da3VIjVcHwKux8FrDpGZ5KKgwruajK//cHKDPp5Cwoh+SPuAbS8dMZQc1fsRQt",
"vt+eAHxAzhN8YR6fxQlZE2xO0bcu1Skf1LNIvdIHBUp4jtS0T2CnWT0tmAgJC8ocWmWbcQtW9po+z568",
"4Z4+lpMvfDnPwl1aSAJcpmms8HLCq8urkMrWZhnxvkhEzGfSXxL7iHM/yc9kTN207fVTO3nnhRR0Uu+G",
"hJsITyJ325n6odF5ou7plt5WaT6XZqYaHOYZDPD4ES+78CBeO4AJdwwG8/WrAqN48OXlnRTM0bNEJUZq",
"F9nq6FTmKFll2hIw+oCw1OhZ8OxMvVAGsccsBP9UNWkmuQpq1uWR74WY0GGO7uBjhqy97Ozo5frqd/f+",
"Z5iXwzi+chK15pC/nUaWtXWhgG7q/dr6yDrRH1fQtMrcESSx4Z4Ky4BsKXXjZ7LhukS9cB/4WJgWE/rZ",
"OUrK4Bxqfaio3NGfLy/fXFRDgagTRqyL5quyapsS/PCKv0yCH47zOzSzCM3t6yd9KKZByPS6DVspCQcL",
"kzfKs4kthmhEn8MnFJAWc354cg/mRmgfOs5z2hLeLRSG9Ve9EFD2LG5N/nFHVRLTG0deYj5bZTAMCxrc",
"lv0E462cx37sS/F1mY3zaVfaV6Ltqz6U481x83f2tN/oOYZhhxCm5A2ATSsUGtbKZc74w5q92/Tg7Rck",
"B2/vRQ3+bohBIT/nNpy/+iyZvbttJGfo17MV+wLvTH8hY+E5nG25JhXuUsU0Tr2Q2nJEHAWq5RGYnz8m",
"jnv/fVIyHcL7Zc5Zfx8MXySNBxHW1Hior458nYw2ClYedXjlQYWruvCwO+VUCgC7UYBiQTg196fA5pVm",
"efrBfDyM1TtnH8+76P2V9AUyjLGBFwkOX4IexdEOpUUJ8H8HxD9OFfbrdG7dzaOJw2U2xNw/5c2e3FMx",
"iRF7xJUy45FaqqtL2gWV0YGoUgE8qhbVo8WoxQEE06ZVftgBtZ1ZAwW/ycxIcWk+WJuSqvVDv26Vqa3j",
"KMU4DOzFMdmWMjJ1lFP1WIqwF4FD6ffRGLHLjRLNL3UVU68L2c0pqoqTDYHWFPuXQXS1KsqZ/r6z7uai",
"i577v7ms9hP2LCPwoyqkDsoXVc7am8eXdel7tfLsAOfVO/Brw3IjjCNNVvYvWswSWnF4clR4Qu1gzADs",
"sLlaoV81wWXqMO7W3pnOCI4S47ZWSbqbLGvyY3E22QhfPJX0Q/NDDVAuKLfSRjYH1asmf66uqHLEA+6j",
"ElI0dqGN8EvVNJQoPPcWyxznZ7YB1xy68fWc6vBlqkIkeVz2migbsbh3ETvjoIyZM2VCsxFrB7dEzT4J",
"MLptw7plZhgIu/LgNN7AA/bOZJLmaUyunE2joXhcaMpqC3D1RON1vwh3LOArxSVP8kL/1jmVKAaPeq+j",
"2wqtk43hSHlntlbi26dPnyaTOTQHCIbWp9gAJf1OB7Y4/mE+bLAnO0nJTiflEc9n2OCHd/rr71Tr+7+U",
"Q1driOHeX+9lKFoCJvONgF4NY/aI2ipvjkIxtvPnOPpj1mSIY4zVZeD38baZ/hfb4Zh4eadAGBt1HODc",
"2d9S+BKqOWfIQNdVlkYBKOlU/CCDckLVmu1JpCn2udCIfdfWHAUG8whfyLTplzjnRzZYpnHG3EQBCCat",
"4OuX1uJMT11rdtt8ol/bcJNcazLroWqsWXgR7FnMUaINJTHtI0onJqBDISoCKOwtyKBi/JbbxLoPEhkG",
"tVpTOdiq837kx56FM7qis8QAkU8A2WwEg+Kuvm0fNYdhPsyYirc1Rz7B+itEn7jtu3W7v6RWX0KZEkdj",
"FvoQnQrmKUo4fETx0UyLUrvObpnzvAkCpx/g3QHVt8aJ047qWwLIDV+XRFp1wJJnnCNjZtebB+HHWPKr",
"h5HQjRw65x/kTp9BHrwGzvDoxxm86IiG9OI/nr3+Aa8QabIYEA5oj0ncHumk4H+fQx6OuiQMU1k3cpY5",
"N+dFDggcIPuMAwMjgf/94qcfoy4HUFf75CEHFPobEaz45unTnodchlFRcibM6s1kiGMFkvmm7WPLIdLw",
"QYjy5dIsb9GMnQVmB/f5vQrIfPz4fwYA",
"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",
}
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
+9 -1
View File
@@ -810,7 +810,15 @@ func (s *Server) WithdrawMessage(w http.ResponseWriter, r *http.Request, taskID
}
func (s *Server) CompactSession(w http.ResponseWriter, r *http.Request, sessionID string) {
sess, err := s.agents.Compact(r.Context(), sessionID)
req := api.CompactCreate{}
if !readJSON(w, r, &req) {
return
}
model := ""
if req.Model != nil {
model = *req.Model
}
sess, err := s.agents.Compact(r.Context(), sessionID, model)
if err != nil {
writeAgentError(w, err)
return
+25 -12
View File
@@ -470,17 +470,10 @@ struct CompactButton: View {
let level = pct >= 90 ? Palette.danger : pct >= 70 ? Palette.warn : Palette.accent
let detail = usage.map { u in u.window > 0 ? "\ncontext: \(u.used.formatted()) of \(u.window.formatted()) tokens\(u.model.isEmpty ? "" : " (\(u.model))")" : "" } ?? ""
let disabled = sessionId == nil || state != .idle || sending
Button {
guard let sessionId else {
return
}
sending = true
Task {
do {
_ = try await store.api.client.compactSession(path: .init(sessionId: sessionId)).accepted
} catch {
overlays.showAlert(errorText(error))
sending = false
Menu {
ForEach(models, id: \.self) { m in
Button("Continue on \(m)") {
compact(m)
}
}
} label: {
@@ -504,14 +497,34 @@ struct CompactButton: View {
.overlay(RoundedRectangle(cornerRadius: 6).stroke(pct >= 70 ? level : Palette.border))
.opacity(disabled ? 0.45 : 1)
.contentShape(Rectangle())
} primaryAction: {
compact(nil)
}
.menuStyle(.button)
.menuIndicator(.hidden)
.buttonStyle(.plain)
.fixedSize()
.disabled(disabled)
.help("Ask the agent for a handoff, then continue in a new session with a fresh context\(detail)")
.help("Ask the agent for a handoff, then continue in a new session with a fresh context; hold to continue on another model\(detail)")
.onChange(of: state) {
sending = false
}
}
private func compact(_ model: String?) {
guard let sessionId else {
return
}
sending = true
Task {
do {
_ = try await store.api.client.compactSession(path: .init(sessionId: sessionId), body: .json(.init(model: model))).accepted
} catch {
overlays.showAlert(errorText(error))
sending = false
}
}
}
}
private struct ScrollMetrics: Equatable {