Skip to content

feat(scenario): BisonFi support - #10

Open
bakasura980 wants to merge 5 commits into
feat/scenarios/protocols/kaminofrom
feat/bisonfi-support
Open

feat(scenario): BisonFi support#10
bakasura980 wants to merge 5 commits into
feat/scenarios/protocols/kaminofrom
feat/bisonfi-support

Conversation

@bakasura980

@bakasura980 bakasura980 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Greptile Summary

This PR adds BisonFi support to Studio scenarios.

  • Enables BisonFi templates in the scenario editor.
  • Adds raw-layout field extraction for non-IDL templates.
  • Adds a BisonFi/Whirlpool arbitrage example and BisonFi icon metadata.
  • Adds the BisonFi visual asset.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/studio/src/components/svm/scenario-editor.tsx Enables BisonFi templates and falls back to raw-layout properties when an IDL account definition is unavailable.
apps/studio/src/components/svm/scenarios-bento.types.ts Adds a BisonFi and Whirlpool arbitrage example using the derived lowercase protocol identifiers.
apps/studio/src/lib/protocol-icons.ts Registers BisonFi's display name, lowercase protocol identifier, and icon asset.
apps/studio/public/assets/bisonfi.svg Adds the static BisonFi protocol icon consumed by the protocol metadata entry.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Service[Scenario template service] --> Editor[Scenario editor]
  Editor --> Filter[BisonFi allow-list]
  Filter --> Fields[IDL or raw-layout fields]
  Fields --> Action[Configurable scenario action]
  Example[BisonFi arbitrage example] --> Editor
  Icon[BisonFi protocol icon] --> Action
Loading

Reviews (3): Last reviewed commit: "Merge and fix conflicts" | Re-trigger Greptile

Context used:

92Infinitus92 and others added 4 commits August 12, 2026 16:03
…he simnet clock (#1)

* fix(studio): stop scenario saves from destroying override data

Renaming a scenario or editing its description rebuilt the whole backend
document from a lossy UI projection — values: {}, a dummy pubkey, fabricated
templateIds, tags: [] — and PATCH is a full replace, so real content was
wiped. Layered fixes:

- flattenOverrideValues collects both value shapes: flat backend keys and
  nested UI edits reachable through modifiedFields (nested edits were
  silently dropped before);
- buildUpdatePayload mirrors the editor sync payload: real override id,
  templateId, values, account, fetchBeforeUse and tags are carried through;
- the shared OverridePayload type spreads the untouched backend override
  (ScenarioAction.original) first, so fields the UI does not edit — enabled
  today, anything added later — survive by construction;
- scenario tags load from the list endpoint: GET /v1/scenarios/{id} has never
  existed and the SPA fallback answered it with HTML 200, so tags never
  loaded and every editor sync wiped them server-side.

Also ignores wheel scrolling over the editor's focused number inputs — the
browser's scroll-to-increment default silently changed typed values.

* fix(studio): compute time travel from the surfnet clock

Date-mode time travel used Date.now(), but the simulated clock drifts from
the wall clock (pauses, prior jumps, slot-paced ticking): the first jump
silently absorbed the accumulated drift, and consecutive jumps moved the
clock by seconds while claiming days. The jump target now derives from the
Clock sysvar via the new lib/surfnet-clock.ts helper (SYSVAR_CLOCK_PUBKEY,
jsonParsed), covered by request-pinning tests.

The dialog also previews the landing time live (1s polling while open),
pre-blocks backward jumps with a friendly message and a disabled Jump button,
and surfaces backend rejections and non-OK HTTP responses instead of staying
silent.

* fix(studio): commit inline edits once instead of PATCHing per keystroke

The scenario title and description inputs sent a full-replace PATCH on every
keystroke against live-rerendered state, which made typing nearly impossible
and produced a request storm. The new DraftField keeps a local draft and
commits once on Enter/blur; Escape cancels the edit and stops propagation so
cancelling no longer closes the whole detail pane; empty values are ignored
unless explicitly allowed (description).

* chore(studio): refresh AI chat models

OpenAI: gpt-5.6-luna/terra/sol. reasoning_effort is 'none' because gpt-5.6
rejects function tools with reasoning enabled on /v1/chat/completions;
re-enabling it means migrating this client to /v1/responses. Anthropic:
claude-haiku-4-5 / claude-sonnet-5 / claude-opus-5, with max_tokens raised
4096 -> 16000 since Claude 5 models think by default and the cap covers
thinking plus response. Stored model ids from the removed list fall back
through the existing getModelById guard. The system prompt points models at
search_constant_options for constant values.

* test(studio): move the network API test out of pages/ and exclude .next

A vitest file living under src/pages/api compiled into a real production
endpoint (/api/network/network.test), and vitest picked up compiled .next
artifacts after any production build, failing the suite. The test now lives
in src/__tests__ and .next/** is excluded from the runner.

* refactor(studio): move reasoning effort into the model config

Review feedback: reasoning_effort was hardcoded in streamOpenAIResponse for
every model. It now lives on the model entry (reasoningEffort), so enabling
reasoning for a future model is a config change; unlisted models fall back to
'none' since gpt-5.6 rejects function tools with reasoning enabled on
/v1/chat/completions.

* fix(studio): resolve fetchSurfnetClockSeconds to null on network errors

Review feedback: the signature promises Promise<number | null>, but a downed
surfnet made the promise reject instead. Failures now resolve to null, matching
how both callers already treat an unreadable clock.
…#2)

* feat(studio): download a scenario as JSON

The editor's download button had no handler at all — the icon was decorative. It
now saves the scenario in the shape POST /v1/scenarios accepts, so a scenario can
survive the restart that otherwise wipes it. Values pass through lossless-json to
keep i64 fields exact, and a failure shows a message in the play bar instead of
only a console line.

* fix(studio): surface why an AI generation stopped

The Claude stream exited silently on any stop reason other than tool_use, so a
generation cut short by the output cap looked like nothing had happened. It now
names the reason — output budget, refusal, or tool rounds exhausted — and
max_tokens goes from 16000 to 32000, since these models think by default and the
cap covers thinking plus the answer (it is a ceiling, not a reservation).

* feat(studio): import a scenario from a downloaded file

The + button becomes a menu: new scenario, or import a file saved by the
download button. An import gets a fresh id, and lossless-json keeps i64 exact.

* fix(studio): open the detail pane for a newly created scenario

A page opened without an id marked the deep-link resolver as initialized and
never reset it once an id arrived, so the first create needed a page reload.

* feat(studio): keep Claude's thinking blocks and cache the prompt prefix

Thinking blocks now go back with the tool results as the API requires; dropping
them silently disabled thinking for the rest of the turn. A cache breakpoint on
the system prompt and on the newest block lets later rounds read the prefix
instead of paying for it again.

* fix(studio): keep u64/u128 precision in scenario and snapshot JSON

Scenario override values are Solana u64/u128 fields that native JSON rounds.
Route load, edit, save (PATCH), Play (registerScenario) and localStorage
through lossless-json so large integers stay exact. Snapshot download now
emits the bare account map (result.value) that surfpool restore expects.
Adds tests for the edit/save/register payloads and the snapshot download shape.

* feat(studio): OpenAI Responses API + thinking toggle

Move streamOpenAIResponse to /v1/responses so reasoning and function tools
coexist: flat tools, store:true, reasoning.effort (medium on, none off), and
previous_response_id continuation. An interrupted stream (no response.completed
or no response id) is now an error, not a silent success.

Add a Thinking toggle (default on) for OpenAI and Claude Sonnet/Opus; it stays
visible but disabled for Fable 5 (always thinks) and non-reasoning providers.
Drop Claude Haiku 4.5, add Fable 5, send thinking:{type:disabled} only for
Sonnet/Opus when off, and handle model_context_window_exceeded. Raise the tool
loop cap to 8 so a retriable tool error does not exhaust the drill-down.

Also tidy the bar: cap protocol chips at 5 with a +N count and stop the model
box wrapping.
Comment thread apps/studio/src/components/svm/scenario-editor.tsx Outdated
@failfmi failfmi changed the title Feat/bisonfi support feat(scenario): BisonFi support Aug 24, 2026
@failfmi
failfmi deleted the branch feat/scenarios/protocols/kamino September 3, 2026 06:20
@failfmi failfmi closed this Sep 3, 2026
@failfmi failfmi reopened this Sep 3, 2026
@bakasura980
bakasura980 changed the base branch from develop to feat/scenarios/protocols/kamino September 3, 2026 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants