fix(ledger): prevent status card from getting stuck at running - #4
Closed
danvitv wants to merge 30 commits into
Closed
fix(ledger): prevent status card from getting stuck at running#4danvitv wants to merge 30 commits into
danvitv wants to merge 30 commits into
Conversation
feat(ledger): add selective gap-filler projection
fix(chat): preserve line breaks around unmatched emphasis
All four chat transports (OpenAI, Anthropic, Gemini, OpenAI Responses) trimmed the entire SSE line before extracting the data: payload, then trimmed the payload again. This stripped leading/trailing whitespace that is part of the JSON content — most notably newlines in streaming text deltas — causing paragraph breaks to be lost during reception. Replace the double-trim with a shared _sseData helper that: - strips only a trailing \r (CRLF line ending) - accepts both data: and data: (single optional space is framing) - does NOT trim the extracted JSON payload Add a regression test that splits an SSE body across multiple network chunks and verifies newlines in content survive intact.
fix(transport): preserve whitespace in SSE data field parsing
utf8.decode(chunk, allowMalformed: true) decodes each network chunk independently, which corrupts multi-byte UTF-8 sequences (e.g. Cyrillic, emoji) when they are split across chunk boundaries. Replace with utf8.decoder.bind(responseStream) so the decoder maintains state across chunks and only emits complete characters. Added a regression test with Russian text 'Привет\n\nмир' split inside the first 'П' byte to verify both UTF-8 integrity and newline preservation.
fix: preserve SSE UTF-8 and action styling
…istory
The global \s{2,} → ' ' replacement in _stripThinkDirective was
intended to clean up residual whitespace after removing <think> directive
patterns, but it ran on EVERY message — including chat history — and
collapsed all \n\n paragraph breaks into single spaces.
This caused the model to see history as one unbroken line, which it then
mirrored in its output. The effect was intermittent because the stripper
only runs when isFinalResponse && (!requestReasoning || omitReasoning).
The directive patterns already include their own \s* boundaries, so the
global whitespace collapse is unnecessary. Removing it preserves paragraph
structure while still stripping think directives and rewriting literal tags.
Regression tests verify newlines survive stripping for roleplay content,
lumiaooc blocks, and multi-paragraph text.
fix(reasoning-stripper): stop collapsing paragraph newlines in chat history
…ll#250) - FilterTagsSection takes an optional fetchSuggestions autocomplete and an allowCustomTags flag, so a source with free-text tags can resolve a query to a name-based FilterTag that is not in the curated list - _FilterTags debounces the query into that callback, guards against out-of-order responses, and lists suggested custom tags plus the raw query - _FilterTags._selectedList includes selected names with no entry in tags, so a picked custom tag is visible and removable - CatalogFilterSheet wires fetchJanitorTagSuggestions and allowCustomTags for the JanitorAI provider only; other providers keep the previous behaviour - New catalog_add_custom_tag string (en/ru)
…rides (hydall#251) - Render each slot as one MenuGroup of dropdown rows: API connection and model override as MenuSelectorItem, plus a "Parameter overrides" row linking into the slot settings sheet - Always offer "Automatic" in the model picker so a slot on a stale model id can be reset back to the connection's own model - Give every parameter in the slot settings sheet an "Override selected preset value" switch; off, a read-only row shows what the selected connection contributes - Back the switches with <field>Override flags on StudioAgentSettings and CleanerSettings; an unset flag makes AgentConfigResolver pass null so the API preset's value survives. Flags default to true, preserving upgrade behaviour - Honour the negative-temperature sentinel for the post-processing slot - Resolve model lists with pickChatTransportFor(config) instead of a hardcoded OpenAI transport, so Gemini/Anthropic/OpenRouter slots are listed over their own protocol and auth, matching the LLM tab - Mirror the LLM tab's endpoint/key precondition, and stop falling back to the active preset when a slot points at a deleted config - Add an optional description to MenuSelectorItem; rewrite the tab hint and fix grammar in the slot hints (en + ru)
The Agents tab read and wrote the API slot bindings on the preset row with id `default`, while a turn resolves them from the preset activeStudioPresetProvider names. With any non-default Studio preset selected the two diverged: the tab edited `default`, the turn read the active preset's empty slot and fell back to the chat's own connection. The model override lives in global PipelineSettings and was still applied, so a model picked from one provider's list was sent to another provider's endpoint and came back "model not found" — only "Automatic" worked, since it takes the model from whichever connection the turn ended up on. - Resolve studioPresetProvider through activeStudioPresetProvider, falling back to the seeded `default` row, mirroring StudioTurnConfigResolver - Move it next to that provider; db_provider cannot import it back without a cycle - Write slot changes to the same active preset, seeding `default` only when the stored active id no longer resolves - Cover all three resolutions with a regression test
…ion-scroll fix(memory): regenerate drafts and stabilize chat scroll
…and-modes fix(memory): restore prompt preset tools and clarify retrieval modes
…-timeouts fix(prompt): isolate lorebook timeout failures
ownsRunningStatus() used identical() object identity to decide whether
the current run still owns the postGenStatusProvider state. Riverpod
internal state replacements and the auto-dismiss timer in
PostGenStatusCard can replace the state object between startStatus and
finishOwnedStatus, causing identical() to fail and leaving the status
card permanently stuck at 'Ledger running...'.
Replace the identical() check with a logical check: same session id,
same task, and phase == running. This still prevents older runs from
overwriting newer ones (different task or non-running phase fails the
check) while tolerating state-object replacement.
Also add a success toast ('Studio Ledger ok (ops=N)') when the ledger
run completes with ops > 0, mirroring the existing failure toast.
Owner
Author
|
Wrong base repo. Opening PR to upstream hydall/Glaze:nightly instead. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@z:\GlazeProject\glaze_flutter_tmp_pr_body.md