From 3038c5724b0cab92b56c8dafa78452d436fc3997 Mon Sep 17 00:00:00 2001 From: retoor Date: Mon, 12 Oct 2026 00:53:52 +0200 Subject: [PATCH] Update --- README.md | 2 +- research/INDEX.md | 16 +- ...lm-chat-completions-responses-migration.md | 28 + ...nal-transpiler-feasible-with-loss-table.md | 51 ++ .../system-message-three-channels.md | 50 ++ ...opers-openai-assistants-migration-guide.md | 28 + .../developers-openai-changelog.md | 28 + .../developers-openai-compaction-guide.md | 28 + .../developers-openai-error-codes-guide.md | 28 + ...rs-openai-go-chat-completions-reference.md | 28 + .../developers-openai-gpt-5-4-guide.md | 28 + ...evelopers-openai-image-generation-guide.md | 28 + ...developers-openai-java-responses-create.md | 28 + ...developers-openai-python-chat-reference.md | 28 + ...s-openai-python-realtime-client-secrets.md | 28 + ...velopers-openai-realtime-client-secrets.md | 28 + .../developers-openai-ruby-evals-create.md | 28 + ...evelopers-openai-ruby-evals-runs-create.md | 28 + .../developers-openai-shell-tool-guide.md | 28 + ...developers-openai-text-generation-guide.md | 28 + ...elopers-openai-text-generation-markdown.md | 28 + ...lopers-openai-typescript-chat-reference.md | 28 + ...enai-typescript-realtime-client-secrets.md | 28 + .../developers-openai-web-search-guide.md | 28 + .../github-agenvoy-gpt6-guide.md | 28 + ...github-anahata-asi-migrate-to-responses.md | 28 + ...hub-apple-swift-openapi-generator-issue.md | 28 + ...ithub-benshapyro-devkit-responses-skill.md | 28 + ...github-byterefinery-openai-python-skill.md | 28 + .../github-clavia-labs-tanstack-ai-openai.md | 28 + ...thub-cpiprint-bodhiapp-openai-api-guide.md | 28 + ...cyli00-otterpad-openai-image-generation.md | 28 + ...love-ethang-openrouter-responses-commit.md | 28 + ...ithub-enkrateialucca-responses-api-2026.md | 28 + ...thub-fairmehit-bifrost-harness-coverage.md | 28 + ...hub-fesshompa-promptfoo-openai-provider.md | 28 + .../github-ggboykxz-apex-api-reference.md | 28 + ...github-guedesdiogo-kelpie-llm-providers.md | 28 + ...ub-hassanhashmi-ai-ml-course-openai-sdk.md | 28 + ...ub-ibobbyts-codex-rosetta-openapi-specs.md | 28 + .../github-immutex-mcode-model-layer.md | 28 + ...github-isaachorowitz-ziplyne-images-api.md | 28 + .../github-langdock-custom-model-example.md | 28 + ...hub-lucasurrutia-zeroq-openai-responses.md | 28 + .../github-mandax94-openai-readme.md | 28 + ...-matthewtaormina-agentskills-openai-sdk.md | 28 + .../github-maxzhao-maxa-responses-protocol.md | 28 + ...thub-milad-o-cogent-responses-migration.md | 28 + ...github-minami-bein-ai-web3-school-notes.md | 28 + ...minorcell-aquaregia-responses-migration.md | 28 + ...b-morning-start-prism-openapi-vendoring.md | 28 + ...ub-oaklight-llm-rosetta-spec-compliance.md | 28 + ...b-openai-openapi-error-responses-commit.md | 28 + .../github-perongh-oai2ant-readme.md | 28 + ...hub-piotrmieszczak-llm-utils-openai-api.md | 28 + .../github-rynfar-meridian-responses-issue.md | 28 + ...github-sabyasachi-seal-sync-openai-apis.md | 28 + ...hub-sarthib7-sokosumi-openai-agent-chat.md | 28 + ...thub-startvibecoding-vibecoding-gateway.md | 28 + ...isestemichtome-bifrost-harness-coverage.md | 28 + ...b-workglow-dev-libs-responses-migration.md | 28 + .../llmfly-gpt6-astra-migration-guide.md | 28 + .../medium-praveen-singh-responses-vs-chat.md | 28 + .../openai-chat-completions-api-reference.md | 60 ++ .../openai-migrate-to-responses.md | 61 ++ .../openai-responses-api-reference.md | 59 ++ .../platform-openai-moderations-reference.md | 28 + ...penai-realtime-conversation-item-delete.md | 28 + ...form-openai-realtime-input-audio-commit.md | 28 + ...m-openai-realtime-session-client-events.md | 28 + .../ai-nexus-ratatui-best-practices.md | 48 ++ .../axhub-telegram-mobile-design.md | 51 ++ .../bubbletea-chat-example.md | 50 ++ .../bubbletea-glamour-example.md | 49 ++ .../tui-framework-design/bubbletint-readme.md | 49 ++ .../messaging-layout-chat-scene.md | 64 ++ .../conclusions/palette-role-theming.md | 59 ++ .../telegram-chat-grammar-adoption.md | 65 ++ .../telegram-theme-roles-mapping.md | 62 ++ .../tui-framework-design/lipgloss-pkg-docs.md | 49 ++ .../mini-apps-docs-main-button.md | 50 ++ .../mini-apps-docs-settings-button.md | 50 ++ .../mini-apps-docs-theming.md | 50 ++ .../mini-apps-docs-viewport.md | 52 ++ .../pytermgui-file-loaders.md | 46 ++ .../pytermgui-styling-docs.md | 49 ++ .../ratatui-kit-theming.md | 49 ++ .../ratatui-themes-readme.md | 50 ++ .../send-rs-chat-widget.md | 49 ++ .../send-rs-config-keymap.md | 49 ++ .../send-rs-tui-draw-main.md | 49 ++ .../send-rs-tui-focus-state.md | 48 ++ .../send-rs-tui-status-bar.md | 48 ++ .../tdesktop-day-blue-theme.md | 57 ++ .../tdesktop-lang-strings.md | 54 ++ .../tdesktop-night-theme.md | 56 ++ .../techmesto-telegram-checkmarks.md | 50 ++ .../telecli-tui-chat-layout.md | 51 ++ .../telegram-android-chat-message-cell.md | 53 ++ .../telegram-android-dialog-cell.md | 53 ++ ...telegram-blog-chat-themes-read-receipts.md | 50 ++ .../tui-framework-design/telegram-bot-api.md | 52 ++ .../telegram-bot-features.md | 50 ++ research/tui-framework-design/telegram-faq.md | 51 ++ .../telegram-webapps-docs.md | 52 ++ .../textual-constants-theme-env.md | 46 ++ .../textual-design-guide.md | 48 ++ .../textual-theme-module.md | 50 ++ .../tui-framework-design/za-tui-app-styles.md | 49 ++ .../tui-framework-design/za-tui-chat-view.md | 49 ++ .../tui-framework-design/za-tui-input-bar.md | 49 ++ .../za-tui-main-screen.md | 49 ++ .../tui-framework-design/za-tui-status-bar.md | 47 ++ tai.py | 704 +++++++++++++++++- test_tai.py | 454 +++++++++++ tui.md | 78 +- 116 files changed, 5475 insertions(+), 25 deletions(-) create mode 100644 research/muse-responses-openai-transpiler/benchlm-chat-completions-responses-migration.md create mode 100644 research/muse-responses-openai-transpiler/conclusions/bidirectional-transpiler-feasible-with-loss-table.md create mode 100644 research/muse-responses-openai-transpiler/conclusions/system-message-three-channels.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-assistants-migration-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-changelog.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-compaction-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-error-codes-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-go-chat-completions-reference.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-gpt-5-4-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-image-generation-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-java-responses-create.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-python-chat-reference.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-python-realtime-client-secrets.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-realtime-client-secrets.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-ruby-evals-create.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-ruby-evals-runs-create.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-shell-tool-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-text-generation-guide.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-text-generation-markdown.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-typescript-chat-reference.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-typescript-realtime-client-secrets.md create mode 100644 research/muse-responses-openai-transpiler/developers-openai-web-search-guide.md create mode 100644 research/muse-responses-openai-transpiler/github-agenvoy-gpt6-guide.md create mode 100644 research/muse-responses-openai-transpiler/github-anahata-asi-migrate-to-responses.md create mode 100644 research/muse-responses-openai-transpiler/github-apple-swift-openapi-generator-issue.md create mode 100644 research/muse-responses-openai-transpiler/github-benshapyro-devkit-responses-skill.md create mode 100644 research/muse-responses-openai-transpiler/github-byterefinery-openai-python-skill.md create mode 100644 research/muse-responses-openai-transpiler/github-clavia-labs-tanstack-ai-openai.md create mode 100644 research/muse-responses-openai-transpiler/github-cpiprint-bodhiapp-openai-api-guide.md create mode 100644 research/muse-responses-openai-transpiler/github-cyli00-otterpad-openai-image-generation.md create mode 100644 research/muse-responses-openai-transpiler/github-eglove-ethang-openrouter-responses-commit.md create mode 100644 research/muse-responses-openai-transpiler/github-enkrateialucca-responses-api-2026.md create mode 100644 research/muse-responses-openai-transpiler/github-fairmehit-bifrost-harness-coverage.md create mode 100644 research/muse-responses-openai-transpiler/github-fesshompa-promptfoo-openai-provider.md create mode 100644 research/muse-responses-openai-transpiler/github-ggboykxz-apex-api-reference.md create mode 100644 research/muse-responses-openai-transpiler/github-guedesdiogo-kelpie-llm-providers.md create mode 100644 research/muse-responses-openai-transpiler/github-hassanhashmi-ai-ml-course-openai-sdk.md create mode 100644 research/muse-responses-openai-transpiler/github-ibobbyts-codex-rosetta-openapi-specs.md create mode 100644 research/muse-responses-openai-transpiler/github-immutex-mcode-model-layer.md create mode 100644 research/muse-responses-openai-transpiler/github-isaachorowitz-ziplyne-images-api.md create mode 100644 research/muse-responses-openai-transpiler/github-langdock-custom-model-example.md create mode 100644 research/muse-responses-openai-transpiler/github-lucasurrutia-zeroq-openai-responses.md create mode 100644 research/muse-responses-openai-transpiler/github-mandax94-openai-readme.md create mode 100644 research/muse-responses-openai-transpiler/github-matthewtaormina-agentskills-openai-sdk.md create mode 100644 research/muse-responses-openai-transpiler/github-maxzhao-maxa-responses-protocol.md create mode 100644 research/muse-responses-openai-transpiler/github-milad-o-cogent-responses-migration.md create mode 100644 research/muse-responses-openai-transpiler/github-minami-bein-ai-web3-school-notes.md create mode 100644 research/muse-responses-openai-transpiler/github-minorcell-aquaregia-responses-migration.md create mode 100644 research/muse-responses-openai-transpiler/github-morning-start-prism-openapi-vendoring.md create mode 100644 research/muse-responses-openai-transpiler/github-oaklight-llm-rosetta-spec-compliance.md create mode 100644 research/muse-responses-openai-transpiler/github-openai-openapi-error-responses-commit.md create mode 100644 research/muse-responses-openai-transpiler/github-perongh-oai2ant-readme.md create mode 100644 research/muse-responses-openai-transpiler/github-piotrmieszczak-llm-utils-openai-api.md create mode 100644 research/muse-responses-openai-transpiler/github-rynfar-meridian-responses-issue.md create mode 100644 research/muse-responses-openai-transpiler/github-sabyasachi-seal-sync-openai-apis.md create mode 100644 research/muse-responses-openai-transpiler/github-sarthib7-sokosumi-openai-agent-chat.md create mode 100644 research/muse-responses-openai-transpiler/github-startvibecoding-vibecoding-gateway.md create mode 100644 research/muse-responses-openai-transpiler/github-ulisestemichtome-bifrost-harness-coverage.md create mode 100644 research/muse-responses-openai-transpiler/github-workglow-dev-libs-responses-migration.md create mode 100644 research/muse-responses-openai-transpiler/llmfly-gpt6-astra-migration-guide.md create mode 100644 research/muse-responses-openai-transpiler/medium-praveen-singh-responses-vs-chat.md create mode 100644 research/muse-responses-openai-transpiler/openai-chat-completions-api-reference.md create mode 100644 research/muse-responses-openai-transpiler/openai-migrate-to-responses.md create mode 100644 research/muse-responses-openai-transpiler/openai-responses-api-reference.md create mode 100644 research/muse-responses-openai-transpiler/platform-openai-moderations-reference.md create mode 100644 research/muse-responses-openai-transpiler/platform-openai-realtime-conversation-item-delete.md create mode 100644 research/muse-responses-openai-transpiler/platform-openai-realtime-input-audio-commit.md create mode 100644 research/muse-responses-openai-transpiler/platform-openai-realtime-session-client-events.md create mode 100644 research/tui-framework-design/ai-nexus-ratatui-best-practices.md create mode 100644 research/tui-framework-design/axhub-telegram-mobile-design.md create mode 100644 research/tui-framework-design/bubbletea-chat-example.md create mode 100644 research/tui-framework-design/bubbletea-glamour-example.md create mode 100644 research/tui-framework-design/bubbletint-readme.md create mode 100644 research/tui-framework-design/conclusions/messaging-layout-chat-scene.md create mode 100644 research/tui-framework-design/conclusions/palette-role-theming.md create mode 100644 research/tui-framework-design/conclusions/telegram-chat-grammar-adoption.md create mode 100644 research/tui-framework-design/conclusions/telegram-theme-roles-mapping.md create mode 100644 research/tui-framework-design/lipgloss-pkg-docs.md create mode 100644 research/tui-framework-design/mini-apps-docs-main-button.md create mode 100644 research/tui-framework-design/mini-apps-docs-settings-button.md create mode 100644 research/tui-framework-design/mini-apps-docs-theming.md create mode 100644 research/tui-framework-design/mini-apps-docs-viewport.md create mode 100644 research/tui-framework-design/pytermgui-file-loaders.md create mode 100644 research/tui-framework-design/pytermgui-styling-docs.md create mode 100644 research/tui-framework-design/ratatui-kit-theming.md create mode 100644 research/tui-framework-design/ratatui-themes-readme.md create mode 100644 research/tui-framework-design/send-rs-chat-widget.md create mode 100644 research/tui-framework-design/send-rs-config-keymap.md create mode 100644 research/tui-framework-design/send-rs-tui-draw-main.md create mode 100644 research/tui-framework-design/send-rs-tui-focus-state.md create mode 100644 research/tui-framework-design/send-rs-tui-status-bar.md create mode 100644 research/tui-framework-design/tdesktop-day-blue-theme.md create mode 100644 research/tui-framework-design/tdesktop-lang-strings.md create mode 100644 research/tui-framework-design/tdesktop-night-theme.md create mode 100644 research/tui-framework-design/techmesto-telegram-checkmarks.md create mode 100644 research/tui-framework-design/telecli-tui-chat-layout.md create mode 100644 research/tui-framework-design/telegram-android-chat-message-cell.md create mode 100644 research/tui-framework-design/telegram-android-dialog-cell.md create mode 100644 research/tui-framework-design/telegram-blog-chat-themes-read-receipts.md create mode 100644 research/tui-framework-design/telegram-bot-api.md create mode 100644 research/tui-framework-design/telegram-bot-features.md create mode 100644 research/tui-framework-design/telegram-faq.md create mode 100644 research/tui-framework-design/telegram-webapps-docs.md create mode 100644 research/tui-framework-design/textual-constants-theme-env.md create mode 100644 research/tui-framework-design/textual-design-guide.md create mode 100644 research/tui-framework-design/textual-theme-module.md create mode 100644 research/tui-framework-design/za-tui-app-styles.md create mode 100644 research/tui-framework-design/za-tui-chat-view.md create mode 100644 research/tui-framework-design/za-tui-input-bar.md create mode 100644 research/tui-framework-design/za-tui-main-screen.md create mode 100644 research/tui-framework-design/za-tui-status-bar.md diff --git a/README.md b/README.md index 6a613eb..7ab4706 100644 --- a/README.md +++ b/README.md @@ -322,7 +322,7 @@ File changes render as a unified diff right inside the call box: line numbers, g ## TUI framework -The interactive UI toolkit lives in `tai.py` itself (stdlib-only, no dependencies): a retained, DOM-like panel tree with rows/cols flow, percent/`fr`/`auto` sizing, docking, named z-layers, a cuts/chops occlusion compositor, SGR mouse, bubbling events, Tab/Shift+Tab focus with modal trap, tick animations, and live pty sub-terminals behind a reimplemented VT screen. `/demo` (or `./tai.py --demo`) tours every widget; `./tai.py --demo-shot` prints one composed frame as plain text. Full reference: [tui.md](tui.md); design background: [research/tui-framework-design/conclusions/retained-dom-compositor-tui.md](research/tui-framework-design/conclusions/retained-dom-compositor-tui.md). +The interactive UI toolkit lives in `tai.py` itself (stdlib-only, no dependencies): a retained, DOM-like panel tree with rows/cols flow, percent/`fr`/`auto` sizing, docking, named z-layers, a cuts/chops occlusion compositor, SGR mouse, bubbling events, Tab/Shift+Tab focus with modal trap, tick animations, and live pty sub-terminals behind a reimplemented VT screen. `/demo` (or `./tai.py --demo`) tours every widget; `./tai.py --demo-shot` prints one composed demo frame as plain text. `./tai.py --tui` runs the fullscreen Telegram-style chat UI (bots sidebar, transcript, input, status bar) with REPL parity; `./tai.py --theme NAME` picks a theme (`dark`, `light`, `nord`, `gruvbox`, `ansi`, or `TAI_THEME`). Full reference: [tui.md](tui.md); design background: [research/tui-framework-design/conclusions/retained-dom-compositor-tui.md](research/tui-framework-design/conclusions/retained-dom-compositor-tui.md), [chat layout](research/tui-framework-design/conclusions/messaging-layout-chat-scene.md), [theming](research/tui-framework-design/conclusions/palette-role-theming.md). ## Configuration diff --git a/research/INDEX.md b/research/INDEX.md index bce0a1e..f12d684 100644 --- a/research/INDEX.md +++ b/research/INDEX.md @@ -6,11 +6,11 @@ | Metric | Value | |---|---| -| Subjects | 6 | -| Total source documents | 421 | -| — Tier 1 (Source Dossier, independently analyzed) | 111 | -| — Tier 2 (Source Citation Card, listed only) | 310 | -| Total conclusion documents | 8 | +| Subjects | 7 | +| Total source documents | 526 | +| — Tier 1 (Source Dossier, independently analyzed) | 153 | +| — Tier 2 (Source Citation Card, listed only) | 373 | +| Total conclusion documents | 14 | | Archive opened | 2026-10-09 | | Last updated | 2026-10-11 | @@ -22,8 +22,9 @@ | [`agent-memory-recency-tracking`](agent-memory-recency-tracking/) | 63 (16 / 47) | 1 | 2026-10-09 | 2026-10-09 | Designing an LRU-style last-used/use-count tracker for vault records and chunks | | [`async-pty-process-testing`](async-pty-process-testing/) | 59 (20 / 39) | 1 | 2026-10-09 | 2026-10-09 | Designing tai_test.py (pty vs. pipes, non-blocking stdin, process-group cleanup, test-framework shape) — backfilled after it was initially skipped, see activity log | | [`shell-multiplexer-auto-attach`](shell-multiplexer-auto-attach/) | 138 (48 / 90) | 2 | 2026-10-09 | 2026-10-10 | Designing a tai-managed terminal multiplexer + bashrc auto-attach: tmux-as-substrate recommendation, interactive-vs-automation shell detection; extended 2026-10-10 to cover zsh/fish hook syntax | -| [`tui-framework-design`](tui-framework-design/) | 55 (10 / 45) | 1 | 2026-10-10 | 2026-10-10 | Designing tai's in-house TUI framework (retained DOM, cuts/chops compositor, SGR mouse, bubbling events, VT sub-terminals); extended 2026-10-10 with synchronized-output verification (DEC 2026); implemented in working-tree tai.py and verified the same session; same-day follow-up fixed the 19 failures natively, deleted tai_pkg/, suite 320/320 green, committed; extended again for kitty keyboard protocol (double-Shift prompt dialog) | +| [`tui-framework-design`](tui-framework-design/) | 94 (49 / 45) | 5 | 2026-10-10 | 2026-10-11 | Designing tai's in-house TUI framework (retained DOM, cuts/chops compositor, SGR mouse, bubbling events, VT sub-terminals); extended 2026-10-10 with synchronized-output verification (DEC 2026); implemented in working-tree tai.py and verified the same session; same-day follow-up fixed the 19 failures natively, deleted tai_pkg/, suite 320/320 green, committed; extended again for kitty keyboard protocol (double-Shift prompt dialog); extended 2026-10-11 with messaging-layout comparison (telecli, send-rs, za-tui, bubbletea examples) and palette-role theming survey (Textual, lipgloss, bubbletint, ratatui-themes, ratatui-kit, pytermgui) plus 2 conclusions, nothing built yet; extended again 2026-10-11 with Telegram look-and-feel survey (tdesktop day/night themes, lang strings, Android dialog/message cells, FAQ, blog, Bot API/features, WebApps ThemeParams, mini-apps SDK docs, iOS teardown — 16 Tier 1) plus 2 conclusions, nothing built yet | | [`agentic-tool-loop-design`](agentic-tool-loop-design/) | 74 (7 / 67) | 2 | 2026-10-11 | 2026-10-11 | Fixing stop-after-narration on prompt-JSON CLI backends without intent regexes; decided structural loop control plus exactly-once JSON-contract repair plus prompt contract, implemented in tai.py the same session (suite 357/357 + 16/16 green); approval tiers judged already industry-standard, no change | +| [`muse-responses-openai-transpiler`](muse-responses-openai-transpiler/) | 66 (3 / 63) | 2 | 2026-10-11 | 2026-10-11 | Documenting Meta muse Responses wire format vs classic Chat Completions; decided bidirectional transpile is feasible with a fixed loss table and system guidance has three channels; scratch transpiler tested, nothing merged | ## Recent activity log @@ -42,6 +43,9 @@ | 2026-10-10 | `tui-framework-design` | Follow-up (no new sources): the 19 failures from the previous row were fixed natively — five classes (`Consts`, `Install`, `Sandbox`, `Opencode`, `SysInfo`) defined directly in standalone `tai.py` with module functions delegating, four test patch-targets corrected to the real `tai.*` seams (assertions unchanged) — then `tai_pkg/` deleted outright per retoor's call. Suite now 320/320 green (`test_tai.py`) + 16/16 (`test_seal.py`); `tui.md` focus rules updated (Tab always cycles, auto-focus, focus memory); committed. Conclusion document forward-corrected. | | 2026-10-10 | `tui-framework-design` | Extended with 1 more source (Tier 1: the kitty keyboard protocol specification, direct fetch) to settle double-Shift detection for a prompt dialog: bare modifier presses need flag 8, press is `57441;2u`, filter `:2`/`:3` via flag 2, push `CSI > 10 u` best-effort with no query round-trip, pop on teardown. Subject total now 55 sources (10 Tier 1 / 45 Tier 2), 1 conclusion. | | 2026-10-11 | `agentic-tool-loop-design` | New subject: 74 sources (7 Tier 1 / 67 Tier 2) + 2 conclusions, covering 7 searches plus 7 direct fetches on agentic loop control (Anthropic stop_reason docs, Building Effective Agents, Agent SDK loop, Writing Tools for Agents, ReAct pattern, tool-calling playbook, small-model narration field report). Decisions: keep loop control structural (tool_calls presence is the stop_reason equivalent, never text parsing), repair a missing JSON envelope exactly once per CLI-backend call, harden the prompt contract, leave approval tiers unchanged. Backed a same-session implementation (tai.py `opencode_find_answer`/`cli_json_repair_prompt`/`cli_json_turn`, prompt-contract sentences, 7 new tests) with suite 357/357 + 16/16 green. Counts verified directly against the written files. | +| 2026-10-11 | `tui-framework-design` | Extended with 23 more sources (all Tier 1, no Tier 2 — every consulted source body was opened via web_fetch by the researching agent) + 2 conclusions (`conclusions/messaging-layout-chat-scene.md`, `conclusions/palette-role-theming.md`): 14 dossiers comparing 4 messaging-client implementations (telecli tui.rs; send-rs tui mod/state/config/status/chat-widget; za-tui tcss/main-screen/status/input/chat-view; bubbletea chat + glamour examples; ai-nexus ratatui guidance doc) and 9 dossiers surveying theme systems (Textual theme.py, design guide, constants.py; lipgloss pkg docs; bubbletint, ratatui-themes, ratatui-kit; pytermgui styling + file_loaders). Decisions: 30/70 chat scene with growing input + 1-line status, manual sidebar toggle first with sub-80 auto-hide deferred, modal keys, left-aligned grouped rows, markdown width-minus-chrome, pin-to-bottom streaming; 12-role palette with THEMES dict registry, --theme flag > TAI_THEME > default, set_theme + F4 cycle, resolve-at-draw with raw-color escape hatch, file overrides deferred. A same-session internal tai.py inventory (no chat-transcript widget, no theme object, hardcoded inline styles) informed both conclusions but produced no source documents (internal code, not external research). Nothing built yet — both conclusions are specified-not-shipped. Carried gaps: no shipped client implements auto breakpoints (80-col rule is guidance-doc only); no streaming/tool-call rendering observed (inferred); fixed-cell sidebars appear only in guidance docs; ratatui core styling, pytermgui NO_COLOR, Textual get_css_variables, and lipgloss v2 LightDark unverified (snippet or inference only). Subject total now 78 sources (33 Tier 1 / 45 Tier 2), 3 conclusions. Counts verified directly against the written files (per-subject grep; global grep also matches README.md's own template rows, excluded). | +| 2026-10-11 | `tui-framework-design` | Extended with 16 more sources (all Tier 1, no Tier 2 — every consulted source body was fetched by the researching agents) + 2 conclusions (`conclusions/telegram-chat-grammar-adoption.md`, `conclusions/telegram-theme-roles-mapping.md`): 10 dossiers on Telegram chat look-and-feel (tdesktop day/night theme files, lang.strings copy sheet, Android DialogCell/ChatMessageCell, FAQ check semantics, chat-themes blog, third-party checkmarks explainer, Bot API keyboards/commands, bot features onboarding) and 6 on Mini App theming (official WebApps ThemeParams/events/design rules; SDK docs for main/back, settings, viewport, theming; third-party iOS teardown). Decisions: adopt Telegram's metadata grammar as rows (clock/checks/blue-checks/eye, no delivered state), 8-hue peer palette, service/date pills, literal status/composer/bot copy, and reply-vs-inline keyboard grammar, rejecting bubbles, gradient themes, and pixel geometry; map the 15 ThemeParams keys onto tai's 12 roles with Desktop-file plus dark-sample defaults and a never-hardcode/re-read-on-switch discipline. A same-session internal tai.py inventory (chat scene present but plain: no ticks/dividers/header/rich rows/composer buttons; 6 of 12 roles used, hardcoded borders) informed both conclusions with per-item patch targets but produced no source documents (internal code, not external research). Nothing built yet — both conclusions are specified-not-shipped. Carried gaps: iOS/Web hexes unverified (Desktop day/night only); bubble radii/paddings/spacing/tail geometry, header icon inventory, chat-list time/date formatting and truncation, send-vs-voice swap and media-bubble time overlay unknown; no official typography/spacing spec (teardown values only); light defaults for section_*/subtitle/destructive unpublished; WebViewColors diagram uninspected; back-button SDK page yielded no captured evidence. Subject total now 94 sources (49 Tier 1 / 45 Tier 2), 5 conclusions. Counts verified directly against the written files via `research/audit.py` (PASS). | +| 2026-10-11 | `muse-responses-openai-transpiler` | New subject: 66 sources (3 Tier 1 / 63 Tier 2) + 2 conclusions, covering the Meta muse Responses wire format vs classic Chat Completions (official migration guide, Responses reference, Chat reference fetched and synthesized; 63 search listings logged as seen-not-analyzed). Decisions: bidirectional transpile is feasible with a fixed warn-on-drop loss table, and system guidance has three channels (instructions preferred, developer/system Items otherwise). Backed by a scratch stdlib transpiler (`/tmp/openai_transpile.py`, self-test green, real-capture round trip verified); nothing merged into tai.py. Counts verified directly against the written files via `research/audit.py` (PASS). | ## How to use this index diff --git a/research/muse-responses-openai-transpiler/benchlm-chat-completions-responses-migration.md b/research/muse-responses-openai-transpiler/benchlm-chat-completions-responses-migration.md new file mode 100644 index 0000000..0a70997 --- /dev/null +++ b/research/muse-responses-openai-transpiler/benchlm-chat-completions-responses-migration.md @@ -0,0 +1,28 @@ +# OpenAI Responses API vs Chat Completions: Migrate and Test + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | OpenAI Responses API vs Chat Completions: Migrate and Test | +| Source URL | https://benchlm.ai/blog/posts/chat-completions-to-responses-api | +| Source type | blog post | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Third-party comparison citing the official references; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/conclusions/bidirectional-transpiler-feasible-with-loss-table.md b/research/muse-responses-openai-transpiler/conclusions/bidirectional-transpiler-feasible-with-loss-table.md new file mode 100644 index 0000000..7674bea --- /dev/null +++ b/research/muse-responses-openai-transpiler/conclusions/bidirectional-transpiler-feasible-with-loss-table.md @@ -0,0 +1,51 @@ +# Conclusion: Chat Completions and Responses transpile both ways with a fixed loss table + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | High | + +## Question / problem statement + +Can classic Chat Completions traffic convert to the Responses wire format Meta's `muse` client speaks, and can Responses traffic convert back, well enough to build a protocol transpiler? + +## Conclusion + +Yes, both directions transpile, and the conversion is exact for plain text, multimodal text/image messages, function tools and calls, structured outputs, and the common streaming events. Everything outside that core has a fixed, warn-on-drop loss table; nothing is dropped silently. + +## Supporting sources + +- [OpenAI migration guide](../openai-migrate-to-responses.md): the message-to-Item, instructions, tool re-tagging, `text.format`, single-generation, and typed-event mappings. +- [Responses API reference](../openai-responses-api-reference.md): exact create params, input/output Item shapes, `call_id` correlation, and SSE vocabulary. +- [Chat Completions reference](../openai-chat-completions-api-reference.md): the classic messages/tools/chunks shapes and the Chat-only field list. +- Local capture `/tmp/mitm_probe/request.txt` (internal evidence, not an external source): proves Meta's client sends `instructions`, `developer`-role input, one `namespace` tool, `store: false`, `reasoning.effort`, `include: ["reasoning.encrypted_content"]`, and `prompt_cache_key`. + +## Alternatives considered and rejected + +- One-way transpiler (Chat to Responses only): rejected, the user explicitly asked for both directions and the reverse mapping is equally mechanical. +- Lossless transpiler with no warnings: rejected, provably impossible (`n` choices, `stop`, sampling penalties, reasoning items, `previous_response_id`, namespaces, and native tools have no counterpart). +- Vendoring the official OpenAPI spec for schema validation: deferred, the reference pages settled every shape the transpiler needs; vendoring stays an option if drift is ever suspected. + +## Risks / open questions + +- Meta response bytes were never observed (the probe stub answered HTTP 500 to all 11 requests), so the response-object and SSE mappings rest on the OpenAI standard shapes the Meta client demonstrably shares on the request side. A recording forward proxy would close this gap. +- Audio and file content parts are warn-and-drop in both directions because their exact cross-API shapes were not verified. +- Model-gated behavior (Responses-required tool calling on newer models) can make a faithful transpile fail at runtime on one side; the transpiler maps protocol, not model capability. + +## Action taken + +Reference implementation exercised as scratch script `/tmp/openai_transpile.py` (stdlib only): `chat_to_responses`, `responses_to_chat`, both object converters, both streaming translators, self-test green, plus a real-capture round trip (Meta request to Chat and back, namespace/include losses warned). Nothing merged into `tai.py` yet. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | diff --git a/research/muse-responses-openai-transpiler/conclusions/system-message-three-channels.md b/research/muse-responses-openai-transpiler/conclusions/system-message-three-channels.md new file mode 100644 index 0000000..ff76d08 --- /dev/null +++ b/research/muse-responses-openai-transpiler/conclusions/system-message-three-channels.md @@ -0,0 +1,50 @@ +# Conclusion: System guidance has three channels, and Meta's client uses two of them + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | High | + +## Question / problem statement + +Is a system message possible on the Responses wire format, and which channel should a transpiler use for Chat `system` / `developer` messages? + +## Conclusion + +Yes. System guidance travels on three channels: top-level `instructions` (preferred), `developer`-role input messages, and `system`-role input messages. Meta's client uses the first two together: a large `instructions` string plus a `developer`-role input message. A transpiler folds leading Chat system/developer messages into `instructions` and preserves non-leading ones as role-kept message Items; the reverse emits `instructions` as the first Chat `system` message. + +## Supporting sources + +- [OpenAI migration guide](../openai-migrate-to-responses.md): guidance maps to "Top-level `instructions`, or compatible message Items when you need to preserve an existing transcript"; `previous_response_id` does not carry `instructions` forward. +- [Responses API reference](../openai-responses-api-reference.md): `instructions` is "A system (or developer) message"; input roles include both `system` and `developer`. +- [Chat Completions reference](../openai-chat-completions-api-reference.md): on o1-and-newer models `developer` replaces `system`, which explains the role split across clients. +- Local capture `/tmp/mitm_probe/request.txt` (internal evidence): requests carry 25-44KB `instructions` strings and, in the main shape, a 31KB `developer`-role input message next to the user message. + +## Alternatives considered and rejected + +- Always emitting system guidance as `system`-role Items instead of `instructions`: rejected, the first-party client and the migration guide both prefer top-level `instructions`. +- Merging all guidance into one string regardless of position: rejected, it scrambles multi-turn transcripts where guidance appears mid-conversation; only leading guidance folds. +- Treating `developer` as Meta-specific: rejected, it is standard Responses vocabulary and standard Chat vocabulary on newer models. + +## Risks / open questions + +- Instruction precedence between `instructions` and same-turn developer/system Items is documented only as hierarchy ("developer or system take precedence over user"), not as ordering between the two guidance channels; observed client behavior (both at once) suggests they compose. +- Whether Meta's server honors a bare `system`-role Item identically to `developer` was not tested live; the reference allows both roles. + +## Action taken + +Documented here and implemented in the scratch transpiler (`/tmp/openai_transpile.py`); verified against the real capture (25KB instructions plus 31KB developer message survive the round trip as guidance). Nothing merged into `tai.py` yet. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-assistants-migration-guide.md b/research/muse-responses-openai-transpiler/developers-openai-assistants-migration-guide.md new file mode 100644 index 0000000..ad055c4 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-assistants-migration-guide.md @@ -0,0 +1,28 @@ +# Assistants migration guide + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Assistants migration guide | +| Source URL | https://developers.openai.com/api/docs/assistants/migration.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Assistants-to-Responses migration; tangential to Chat interop. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-changelog.md b/research/muse-responses-openai-transpiler/developers-openai-changelog.md new file mode 100644 index 0000000..9cd3db2 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-changelog.md @@ -0,0 +1,28 @@ +# Changelog | OpenAI API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Changelog | OpenAI API | +| Source URL | https://developers.openai.com/api/docs/changelog | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Changelog noting Responses-required tool calling on newer models; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-compaction-guide.md b/research/muse-responses-openai-transpiler/developers-openai-compaction-guide.md new file mode 100644 index 0000000..16804e9 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-compaction-guide.md @@ -0,0 +1,28 @@ +# Compaction + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Compaction | +| Source URL | https://developers.openai.com/api/docs/guides/compaction.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Compaction guide replaying output items with store:false; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-error-codes-guide.md b/research/muse-responses-openai-transpiler/developers-openai-error-codes-guide.md new file mode 100644 index 0000000..36f49ce --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-error-codes-guide.md @@ -0,0 +1,28 @@ +# Error codes + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Error codes | +| Source URL | https://developers.openai.com/api/docs/guides/error-codes.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Error-code guide with a Responses snippet; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-go-chat-completions-reference.md b/research/muse-responses-openai-transpiler/developers-openai-go-chat-completions-reference.md new file mode 100644 index 0000000..ed122c4 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-go-chat-completions-reference.md @@ -0,0 +1,28 @@ +# Completions + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Completions | +| Source URL | https://developers.openai.com/api/reference/go/resources/chat/subresources/completions/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Go chat reference entry; not opened because the language-neutral reference was used instead. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-gpt-5-4-guide.md b/research/muse-responses-openai-transpiler/developers-openai-gpt-5-4-guide.md new file mode 100644 index 0000000..d51d283 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-gpt-5-4-guide.md @@ -0,0 +1,28 @@ +# Using GPT-5.4 + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Using GPT-5.4 | +| Source URL | https://developers.openai.com/api/docs/guides/latest-model/gpt-5-4.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Model guide noting chain-of-thought-between-turns as the migration reason; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-image-generation-guide.md b/research/muse-responses-openai-transpiler/developers-openai-image-generation-guide.md new file mode 100644 index 0000000..e43a9d7 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-image-generation-guide.md @@ -0,0 +1,28 @@ +# Image generation + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Image generation | +| Source URL | https://developers.openai.com/api/docs/guides/image-generation.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Image guide with a Responses image_generation tool; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-java-responses-create.md b/research/muse-responses-openai-transpiler/developers-openai-java-responses-create.md new file mode 100644 index 0000000..8769d83 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-java-responses-create.md @@ -0,0 +1,28 @@ +# Create a model response + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Create a model response | +| Source URL | https://developers.openai.com/api/reference/java/resources/responses/methods/create/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Java create-response entry confirming POST /responses; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-python-chat-reference.md b/research/muse-responses-openai-transpiler/developers-openai-python-chat-reference.md new file mode 100644 index 0000000..35a4996 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-python-chat-reference.md @@ -0,0 +1,28 @@ +# Chat Completions + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Chat Completions | +| Source URL | https://developers.openai.com/api/reference/python/resources/chat/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Python chat reference entry; not opened because the language-neutral reference was used instead. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-python-realtime-client-secrets.md b/research/muse-responses-openai-transpiler/developers-openai-python-realtime-client-secrets.md new file mode 100644 index 0000000..2a7c1ef --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-python-realtime-client-secrets.md @@ -0,0 +1,28 @@ +# Client Secrets + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Client Secrets | +| Source URL | https://developers.openai.com/api/reference/python/resources/realtime/subresources/client_secrets/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Realtime secrets; off-topic. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-realtime-client-secrets.md b/research/muse-responses-openai-transpiler/developers-openai-realtime-client-secrets.md new file mode 100644 index 0000000..6174580 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-realtime-client-secrets.md @@ -0,0 +1,28 @@ +# Client Secrets | OpenAI API Reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Client Secrets | OpenAI API Reference | +| Source URL | https://developers.openai.com/api/reference/resources/realtime/subresources/client_secrets/ | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Realtime secrets reference; off-topic. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-create.md b/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-create.md new file mode 100644 index 0000000..8851201 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-create.md @@ -0,0 +1,28 @@ +# Create eval + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Create eval | +| Source URL | https://developers.openai.com/api/reference/ruby/resources/evals/methods/create/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Evals API; off-topic. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-runs-create.md b/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-runs-create.md new file mode 100644 index 0000000..883ab7e --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-ruby-evals-runs-create.md @@ -0,0 +1,28 @@ +# Create eval run + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Create eval run | +| Source URL | https://developers.openai.com/api/reference/ruby/resources/evals/subresources/runs/methods/create/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Evals API; off-topic. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-shell-tool-guide.md b/research/muse-responses-openai-transpiler/developers-openai-shell-tool-guide.md new file mode 100644 index 0000000..af5e618 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-shell-tool-guide.md @@ -0,0 +1,28 @@ +# Shell + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Shell | +| Source URL | https://developers.openai.com/api/docs/guides/tools-shell.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Shell tool guide, Responses-only; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-text-generation-guide.md b/research/muse-responses-openai-transpiler/developers-openai-text-generation-guide.md new file mode 100644 index 0000000..18fccb9 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-text-generation-guide.md @@ -0,0 +1,28 @@ +# Text generation | OpenAI API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Text generation | OpenAI API | +| Source URL | https://developers.openai.com/api/docs/guides/text | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Official text guide recommending Responses with instructions and roles; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-text-generation-markdown.md b/research/muse-responses-openai-transpiler/developers-openai-text-generation-markdown.md new file mode 100644 index 0000000..5770cf9 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-text-generation-markdown.md @@ -0,0 +1,28 @@ +# Text generation + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Text generation | +| Source URL | https://developers.openai.com/api/docs/guides/text.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Markdown variant of the text guide; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-typescript-chat-reference.md b/research/muse-responses-openai-transpiler/developers-openai-typescript-chat-reference.md new file mode 100644 index 0000000..efb94ac --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-typescript-chat-reference.md @@ -0,0 +1,28 @@ +# Chat Completions + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Chat Completions | +| Source URL | https://developers.openai.com/api/reference/typescript/resources/chat/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. TypeScript chat reference entry; not opened because the language-neutral reference was used instead. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-typescript-realtime-client-secrets.md b/research/muse-responses-openai-transpiler/developers-openai-typescript-realtime-client-secrets.md new file mode 100644 index 0000000..b8a5b96 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-typescript-realtime-client-secrets.md @@ -0,0 +1,28 @@ +# Create client secret + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Create client secret | +| Source URL | https://developers.openai.com/api/reference/typescript/resources/realtime/subresources/client_secrets/methods/create/index.md | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com reference Create response` search on 2026-10-11. Realtime secrets; off-topic. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/developers-openai-web-search-guide.md b/research/muse-responses-openai-transpiler/developers-openai-web-search-guide.md new file mode 100644 index 0000000..e9ed301 --- /dev/null +++ b/research/muse-responses-openai-transpiler/developers-openai-web-search-guide.md @@ -0,0 +1,28 @@ +# Web search | OpenAI API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Web search | OpenAI API | +| Source URL | https://developers.openai.com/api/docs/guides/tools-web-search | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:developers.openai.com Migrate to Responses` search on 2026-10-11. Web-search tool guide with a Chat-versus-Responses path note; not opened. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-agenvoy-gpt6-guide.md b/research/muse-responses-openai-transpiler/github-agenvoy-gpt6-guide.md new file mode 100644 index 0000000..ebf9fa9 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-agenvoy-gpt6-guide.md @@ -0,0 +1,28 @@ +# agenvoy/skill-extract-official-guide - offical_guide/gpt-6.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | agenvoy/skill-extract-official-guide - offical_guide/gpt-6.md | +| Source URL | https://github.com/agenvoy/skill-extract-official-guide/blob/HEAD/offical_guide/gpt-6.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Model guide notes on reasoning-effort params and Responses-required tool calling; version-sensitive and unverified. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-anahata-asi-migrate-to-responses.md b/research/muse-responses-openai-transpiler/github-anahata-asi-migrate-to-responses.md new file mode 100644 index 0000000..14320b8 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-anahata-asi-migrate-to-responses.md @@ -0,0 +1,28 @@ +# anahata-os/anahata-asi - anahata-asi-openai/src/test/java/migrate-to-responses.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | anahata-os/anahata-asi - anahata-asi-openai/src/test/java/migrate-to-responses.md | +| Source URL | https://github.com/anahata-os/anahata-asi/blob/HEAD/anahata-asi-openai/src/test/java/migrate-to-responses.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Vendored migration notes on the endpoint swap plus previous_response_id and Conversations. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-apple-swift-openapi-generator-issue.md b/research/muse-responses-openai-transpiler/github-apple-swift-openapi-generator-issue.md new file mode 100644 index 0000000..9db609f --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-apple-swift-openapi-generator-issue.md @@ -0,0 +1,28 @@ +# Different Return Types Depending on the Request Made to the /chat/completions Endpoint in the OpenAI OpenAPI + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Different Return Types Depending on the Request Made to the /chat/completions Endpoint in the OpenAI OpenAPI | +| Source URL | https://github.com/apple/swift-openapi-generator/issues/614 | +| Source type | forum thread | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Old issue on stream versus non-stream return types in the spec. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-benshapyro-devkit-responses-skill.md b/research/muse-responses-openai-transpiler/github-benshapyro-devkit-responses-skill.md new file mode 100644 index 0000000..e1a47f3 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-benshapyro-devkit-responses-skill.md @@ -0,0 +1,28 @@ +# benshapyro/devkit - skills/ai-automation/openai-responses-api/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | benshapyro/devkit - skills/ai-automation/openai-responses-api/SKILL.md | +| Source URL | https://github.com/benshapyro/devkit/blob/HEAD/skills/ai-automation/openai-responses-api/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Skill with a migrate checklist: system-to-instructions, messages-to-input, max_tokens mapping, previous_response_id versus conversation. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-byterefinery-openai-python-skill.md b/research/muse-responses-openai-transpiler/github-byterefinery-openai-python-skill.md new file mode 100644 index 0000000..889bade --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-byterefinery-openai-python-skill.md @@ -0,0 +1,28 @@ +# byterefinery/skills - .agents/skills-python/openai-python-3-19-2/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | byterefinery/skills - .agents/skills-python/openai-python-3-19-2/SKILL.md | +| Source URL | https://github.com/byterefinery/skills/blob/HEAD/.agents/skills-python/openai-python-3-19-2/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. SDK skill with Responses-primary and Chat previous-standard examples including the developer role. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-clavia-labs-tanstack-ai-openai.md b/research/muse-responses-openai-transpiler/github-clavia-labs-tanstack-ai-openai.md new file mode 100644 index 0000000..f635dac --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-clavia-labs-tanstack-ai-openai.md @@ -0,0 +1,28 @@ +# clavia-labs/tanstack-ai - docs/adapters/openai.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | clavia-labs/tanstack-ai - docs/adapters/openai.md | +| Source URL | https://github.com/clavia-labs/tanstack-ai/blob/HEAD/docs/adapters/openai.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Adapter docs for chat completions streaming. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-cpiprint-bodhiapp-openai-api-guide.md b/research/muse-responses-openai-transpiler/github-cpiprint-bodhiapp-openai-api-guide.md new file mode 100644 index 0000000..85818c9 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-cpiprint-bodhiapp-openai-api-guide.md @@ -0,0 +1,28 @@ +# cpiprint/bodhiapp - docs/guides/openai-api.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | cpiprint/bodhiapp - docs/guides/openai-api.md | +| Source URL | https://github.com/cpiprint/bodhiapp/blob/HEAD/docs/guides/openai-api.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Local-server guide for chat completions with a system-role example. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-cyli00-otterpad-openai-image-generation.md b/research/muse-responses-openai-transpiler/github-cyli00-otterpad-openai-image-generation.md new file mode 100644 index 0000000..59d746c --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-cyli00-otterpad-openai-image-generation.md @@ -0,0 +1,28 @@ +# cyli00/otterpad - test/openai-image-generation.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | cyli00/otterpad - test/openai-image-generation.md | +| Source URL | https://github.com/cyli00/otterpad/blob/HEAD/test/openai-image-generation.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Image generation through the Responses image tool with streaming. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-eglove-ethang-openrouter-responses-commit.md b/research/muse-responses-openai-transpiler/github-eglove-ethang-openrouter-responses-commit.md new file mode 100644 index 0000000..776c5e6 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-eglove-ethang-openrouter-responses-commit.md @@ -0,0 +1,28 @@ +# eglove/ethang-agent - feat(openrouter): switch to the Responses API; eleven server tools; error bodies surfaced + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | eglove/ethang-agent - feat(openrouter): switch to the Responses API; eleven server tools; error bodies surfaced | +| Source URL | https://github.com/eglove/ethang-agent/commit/c2567f22543965cc32d2ebfea8db0f933b2be7ed | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Commit migrating a wire layer to /responses with typed SSE; corroborates stream-shape claims at snippet level only. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-enkrateialucca-responses-api-2026.md b/research/muse-responses-openai-transpiler/github-enkrateialucca-responses-api-2026.md new file mode 100644 index 0000000..e20fc17 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-enkrateialucca-responses-api-2026.md @@ -0,0 +1,28 @@ +# enkrateialucca/oreilly_live_training_llm_apps - research/responses-api-2026.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | enkrateialucca/oreilly_live_training_llm_apps - research/responses-api-2026.md | +| Source URL | https://github.com/enkrateialucca/oreilly_live_training_llm_apps/blob/HEAD/research/responses-api-2026.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Training research confirming instructions as the system-role equivalent, citing the official guide. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-fairmehit-bifrost-harness-coverage.md b/research/muse-responses-openai-transpiler/github-fairmehit-bifrost-harness-coverage.md new file mode 100644 index 0000000..e24f478 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-fairmehit-bifrost-harness-coverage.md @@ -0,0 +1,28 @@ +# fairmehit/bifrost-lite - tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | fairmehit/bifrost-lite - tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md | +| Source URL | https://github.com/fairmehit/bifrost-lite/blob/HEAD/tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. E2E coverage list naming system messages, streaming, vision, function calling, forced tool choice, json_schema, and reasoning effort. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-fesshompa-promptfoo-openai-provider.md b/research/muse-responses-openai-transpiler/github-fesshompa-promptfoo-openai-provider.md new file mode 100644 index 0000000..fd383c5 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-fesshompa-promptfoo-openai-provider.md @@ -0,0 +1,28 @@ +# fesshompa/promptfoo - site/docs/providers/openai.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | fesshompa/promptfoo - site/docs/providers/openai.md | +| Source URL | https://github.com/fesshompa/promptfoo/blob/HEAD/site/docs/providers/openai.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Provider docs recommending Responses for new evals, citing the official guide. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-ggboykxz-apex-api-reference.md b/research/muse-responses-openai-transpiler/github-ggboykxz-apex-api-reference.md new file mode 100644 index 0000000..4378514 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-ggboykxz-apex-api-reference.md @@ -0,0 +1,28 @@ +# ggboykxz/apex - docs/reference/api.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | ggboykxz/apex - docs/reference/api.md | +| Source URL | https://github.com/ggboykxz/apex/blob/HEAD/docs/reference/api.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Third-party API doc mirroring the chat completions shape with a system message. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-guedesdiogo-kelpie-llm-providers.md b/research/muse-responses-openai-transpiler/github-guedesdiogo-kelpie-llm-providers.md new file mode 100644 index 0000000..52e9e83 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-guedesdiogo-kelpie-llm-providers.md @@ -0,0 +1,28 @@ +# guedesdiogo/kelpie - docs/research/07-llm-providers-and-auth.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | guedesdiogo/kelpie - docs/research/07-llm-providers-and-auth.md | +| Source URL | https://github.com/guedesdiogo/kelpie/blob/HEAD/docs/research/07-llm-providers-and-auth.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Provider research citing the Responses recommendation plus store:false encrypted reasoning. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-hassanhashmi-ai-ml-course-openai-sdk.md b/research/muse-responses-openai-transpiler/github-hassanhashmi-ai-ml-course-openai-sdk.md new file mode 100644 index 0000000..b45bbf5 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-hassanhashmi-ai-ml-course-openai-sdk.md @@ -0,0 +1,28 @@ +# hassanhashmi16/ai-ml-course - Phase 1(AI)/STEP 15/Step15-Anthropic-OpenAI-SDK.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | hassanhashmi16/ai-ml-course - Phase 1(AI)/STEP 15/Step15-Anthropic-OpenAI-SDK.md | +| Source URL | https://github.com/hassanhashmi16/ai-ml-course/blob/HEAD/Phase%201(AI)/STEP%2015/Step15-Anthropic-OpenAI-SDK.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Course notes with a system/user/assistant messages example. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-ibobbyts-codex-rosetta-openapi-specs.md b/research/muse-responses-openai-transpiler/github-ibobbyts-codex-rosetta-openapi-specs.md new file mode 100644 index 0000000..682d667 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-ibobbyts-codex-rosetta-openapi-specs.md @@ -0,0 +1,28 @@ +# ibobbyts/codex-rosetta - docs/dev/sdk_ir/openapi_specs_and_open_responses.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | ibobbyts/codex-rosetta - docs/dev/sdk_ir/openapi_specs_and_open_responses.md | +| Source URL | https://github.com/ibobbyts/codex-rosetta/blob/HEAD/docs/dev/sdk_ir/openapi_specs_and_open_responses.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Notes on the official openai-openapi repo, branch, and raw URL covering both endpoints. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-immutex-mcode-model-layer.md b/research/muse-responses-openai-transpiler/github-immutex-mcode-model-layer.md new file mode 100644 index 0000000..4f2574e --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-immutex-mcode-model-layer.md @@ -0,0 +1,28 @@ +# immutex/mcode - docs/15-model-layer.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | immutex/mcode - docs/15-model-layer.md | +| Source URL | https://github.com/immutex/mcode/blob/HEAD/docs/15-model-layer.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Provider-matrix doc noting Responses as the primary surface with input items, instructions, store, and built-in tools. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-isaachorowitz-ziplyne-images-api.md b/research/muse-responses-openai-transpiler/github-isaachorowitz-ziplyne-images-api.md new file mode 100644 index 0000000..94e547f --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-isaachorowitz-ziplyne-images-api.md @@ -0,0 +1,28 @@ +# isaachorowitz/ziplyne-agent-setup - external-providers/openai/api-reference/images-api.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | isaachorowitz/ziplyne-agent-setup - external-providers/openai/api-reference/images-api.md | +| Source URL | https://github.com/isaachorowitz/ziplyne-agent-setup/blob/HEAD/external-providers/openai/api-reference/images-api.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Vendored images-API notes with a Responses image-tool snippet. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-langdock-custom-model-example.md b/research/muse-responses-openai-transpiler/github-langdock-custom-model-example.md new file mode 100644 index 0000000..de10935 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-langdock-custom-model-example.md @@ -0,0 +1,28 @@ +# Langdock/custom-model-example + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Langdock/custom-model-example | +| Source URL | https://github.com/Langdock/custom-model-example | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Custom-model example citing the chat messages schema with a system role. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-lucasurrutia-zeroq-openai-responses.md b/research/muse-responses-openai-transpiler/github-lucasurrutia-zeroq-openai-responses.md new file mode 100644 index 0000000..0e15ad5 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-lucasurrutia-zeroq-openai-responses.md @@ -0,0 +1,28 @@ +# lucasurrutia22/zeroq-support-hub - .claude/skills/zeroq-openai/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | lucasurrutia22/zeroq-support-hub - .claude/skills/zeroq-openai/SKILL.md | +| Source URL | https://github.com/lucasurrutia22/zeroq-support-hub/blob/HEAD/.claude/skills/zeroq-openai/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Skill doc asserting Responses-first usage with instructions, input, tools, and stream. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-mandax94-openai-readme.md b/research/muse-responses-openai-transpiler/github-mandax94-openai-readme.md new file mode 100644 index 0000000..0ea7f5a --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-mandax94-openai-readme.md @@ -0,0 +1,28 @@ +# mandax94/openai - README.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | mandax94/openai - README.md | +| Source URL | https://github.com/mandax94/openai/blob/HEAD/README.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Fork README describing the Responses surface and spec tag groups. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-matthewtaormina-agentskills-openai-sdk.md b/research/muse-responses-openai-transpiler/github-matthewtaormina-agentskills-openai-sdk.md new file mode 100644 index 0000000..d6df720 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-matthewtaormina-agentskills-openai-sdk.md @@ -0,0 +1,28 @@ +# matthewtaormina/agentskills - .agents/skills/openai-sdk/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | matthewtaormina/agentskills - .agents/skills/openai-sdk/SKILL.md | +| Source URL | https://github.com/matthewtaormina/agentskills/blob/HEAD/.agents/skills/openai-sdk/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. SDK skill with a Responses call plus built-in web search example. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-maxzhao-maxa-responses-protocol.md b/research/muse-responses-openai-transpiler/github-maxzhao-maxa-responses-protocol.md new file mode 100644 index 0000000..2daca33 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-maxzhao-maxa-responses-protocol.md @@ -0,0 +1,28 @@ +# maxzhao/maxa - .supermax/wiki/protocols/openai-responses.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | maxzhao/maxa - .supermax/wiki/protocols/openai-responses.md | +| Source URL | https://github.com/maxzhao/maxa/blob/HEAD/.supermax/wiki/protocols/openai-responses.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Community protocol notes scraped from the official OpenAPI, covering request fields and events. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-milad-o-cogent-responses-migration.md b/research/muse-responses-openai-transpiler/github-milad-o-cogent-responses-migration.md new file mode 100644 index 0000000..ca4905d --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-milad-o-cogent-responses-migration.md @@ -0,0 +1,28 @@ +# milad-o/cogent - feat(models/openai): migrate adapter to the Responses API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | milad-o/cogent - feat(models/openai): migrate adapter to the Responses API | +| Source URL | https://github.com/milad-o/cogent/commit/7126a0e56d3012b547b13d93c04c77b049778898 | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Commit noting messages-to-items, system-to-instructions, and internally-tagged tools. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-minami-bein-ai-web3-school-notes.md b/research/muse-responses-openai-transpiler/github-minami-bein-ai-web3-school-notes.md new file mode 100644 index 0000000..401394f --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-minami-bein-ai-web3-school-notes.md @@ -0,0 +1,28 @@ +# minami-bein/ai-web3-school - notes/nobodyhi.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | minami-bein/ai-web3-school - notes/nobodyhi.md | +| Source URL | https://github.com/minami-bein/ai-web3-school/blob/HEAD/notes/nobodyhi.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Study notes on chat completions roles and streaming. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-minorcell-aquaregia-responses-migration.md b/research/muse-responses-openai-transpiler/github-minorcell-aquaregia-responses-migration.md new file mode 100644 index 0000000..b727542 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-minorcell-aquaregia-responses-migration.md @@ -0,0 +1,28 @@ +# minorcell/aquaregia - refactor: migrate OpenAI adapter to Responses API, drop think-tag parsing + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | minorcell/aquaregia - refactor: migrate OpenAI adapter to Responses API, drop think-tag parsing | +| Source URL | https://github.com/minorcell/aquaregia/commit/5752522026bc0314423ffb142591e8db3d1fdf8d | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Commit noting system-to-instructions, flat function tools, and function_call_output. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-morning-start-prism-openapi-vendoring.md b/research/muse-responses-openai-transpiler/github-morning-start-prism-openapi-vendoring.md new file mode 100644 index 0000000..41a8897 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-morning-start-prism-openapi-vendoring.md @@ -0,0 +1,28 @@ +# morning-start/prism - feat(schemas): vendor official OpenAI OpenAPI spec for conformance cross-check (TD-FV-1) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | morning-start/prism - feat(schemas): vendor official OpenAI OpenAPI spec for conformance cross-check (TD-FV-1) | +| Source URL | https://github.com/morning-start/prism/commit/abd1fa4d4fb78b6c43e37bdf73ea2cbe4fc65cb | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Commit vendoring the official spec for both endpoints for conformance checks. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-oaklight-llm-rosetta-spec-compliance.md b/research/muse-responses-openai-transpiler/github-oaklight-llm-rosetta-spec-compliance.md new file mode 100644 index 0000000..4ec4079 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-oaklight-llm-rosetta-spec-compliance.md @@ -0,0 +1,28 @@ +# epic: continuous spec compliance testing across all API standards + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | epic: continuous spec compliance testing across all API standards | +| Source URL | https://github.com/oaklight/llm-rosetta/issues/411 | +| Source type | forum thread | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Tracking issue listing official spec locations across API standards. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-openai-openapi-error-responses-commit.md b/research/muse-responses-openai-transpiler/github-openai-openapi-error-responses-commit.md new file mode 100644 index 0000000..b3fe0f4 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-openai-openapi-error-responses-commit.md @@ -0,0 +1,28 @@ +# openai/openai-openapi - Add detailed error responses for chat completion endpoints + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | openai/openai-openapi - Add detailed error responses for chat completion endpoints | +| Source URL | https://github.com/openai/openai-openapi/commit/412c7b9820f61449eeded838e88d168a2ebd1794 | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Official spec-repo commit; confirms the repo exists and is maintained. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-perongh-oai2ant-readme.md b/research/muse-responses-openai-transpiler/github-perongh-oai2ant-readme.md new file mode 100644 index 0000000..a7f3779 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-perongh-oai2ant-readme.md @@ -0,0 +1,28 @@ +# perongh/oai2ant - README.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | perongh/oai2ant - README.md | +| Source URL | https://github.com/perongh/oai2ant/blob/HEAD/README.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Proxy README mapping system prompts, tool calls/results, and tool_choice between OpenAI chat and Anthropic shapes. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-piotrmieszczak-llm-utils-openai-api.md b/research/muse-responses-openai-transpiler/github-piotrmieszczak-llm-utils-openai-api.md new file mode 100644 index 0000000..973c4ad --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-piotrmieszczak-llm-utils-openai-api.md @@ -0,0 +1,28 @@ +# piotrmieszczak/llm_utils - plugins/llm-app-patterns/skills/openai-api/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | piotrmieszczak/llm_utils - plugins/llm-app-patterns/skills/openai-api/SKILL.md | +| Source URL | https://github.com/piotrmieszczak/llm_utils/blob/HEAD/plugins/llm-app-patterns/skills/openai-api/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Responses-default quickstart using instructions and input. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-rynfar-meridian-responses-issue.md b/research/muse-responses-openai-transpiler/github-rynfar-meridian-responses-issue.md new file mode 100644 index 0000000..726088c --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-rynfar-meridian-responses-issue.md @@ -0,0 +1,28 @@ +# feat: support OpenAI Responses API (`/v1/responses`) for Codex CLI 0.96+ + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | feat: support OpenAI Responses API (`/v1/responses`) for Codex CLI 0.96+ | +| Source URL | https://github.com/rynfar/meridian/issues/475 | +| Source type | forum thread | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Issue sketching Responses request/response mapping including instructions-as-system. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-sabyasachi-seal-sync-openai-apis.md b/research/muse-responses-openai-transpiler/github-sabyasachi-seal-sync-openai-apis.md new file mode 100644 index 0000000..ef44fe4 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-sabyasachi-seal-sync-openai-apis.md @@ -0,0 +1,28 @@ +# sabyasachi-seal/gpt-4 - .claude/commands/aix/sync-openai-apis.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | sabyasachi-seal/gpt-4 - .claude/commands/aix/sync-openai-apis.md | +| Source URL | https://github.com/sabyasachi-seal/gpt-4/blob/HEAD/.claude/commands/aix/sync-openai-apis.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Command doc listing official reference URLs for both APIs. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-sarthib7-sokosumi-openai-agent-chat.md b/research/muse-responses-openai-transpiler/github-sarthib7-sokosumi-openai-agent-chat.md new file mode 100644 index 0000000..15ca8a4 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-sarthib7-sokosumi-openai-agent-chat.md @@ -0,0 +1,28 @@ +# sarthib7/sokosumi - apps/core/.agents/skills/openai-agent-chat/SKILL.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | sarthib7/sokosumi - apps/core/.agents/skills/openai-agent-chat/SKILL.md | +| Source URL | https://github.com/sarthib7/sokosumi/blob/HEAD/apps/core/.agents/skills/openai-agent-chat/SKILL.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Responses API reference` search on 2026-10-11. Agent-chat skill showing instructions as the system prompt with store and tool_choice. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-startvibecoding-vibecoding-gateway.md b/research/muse-responses-openai-transpiler/github-startvibecoding-vibecoding-gateway.md new file mode 100644 index 0000000..84a6617 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-startvibecoding-vibecoding-gateway.md @@ -0,0 +1,28 @@ +# startvibecoding/vibecoding - docs/en/gateway.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | startvibecoding/vibecoding - docs/en/gateway.md | +| Source URL | https://github.com/startvibecoding/vibecoding/blob/HEAD/docs/en/gateway.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Gateway doc with a chat completions endpoint and system-message example. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-ulisestemichtome-bifrost-harness-coverage.md b/research/muse-responses-openai-transpiler/github-ulisestemichtome-bifrost-harness-coverage.md new file mode 100644 index 0000000..4503ae2 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-ulisestemichtome-bifrost-harness-coverage.md @@ -0,0 +1,28 @@ +# ulisestemichtome-create/bifrost - tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | ulisestemichtome-create/bifrost - tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md | +| Source URL | https://github.com/ulisestemichtome-create/bifrost/blob/HEAD/tests/e2e/api/HARNESS_COVERAGE_BACKLOG.md | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI Chat Completions API reference` search on 2026-10-11. Fork of the same e2e coverage list as the fairmehit copy above. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/github-workglow-dev-libs-responses-migration.md b/research/muse-responses-openai-transpiler/github-workglow-dev-libs-responses-migration.md new file mode 100644 index 0000000..084e553 --- /dev/null +++ b/research/muse-responses-openai-transpiler/github-workglow-dev-libs-responses-migration.md @@ -0,0 +1,28 @@ +# workglow-dev/libs - Migrate OpenAI text run-fns to the Responses API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | workglow-dev/libs - Migrate OpenAI text run-fns to the Responses API | +| Source URL | https://github.com/workglow-dev/libs/commit/9356528caccd764a83968d58781c67c019e10b51 | +| Source type | repository | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Commit noting JSON mode via text.format.json_schema and Responses stream accumulation. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/llmfly-gpt6-astra-migration-guide.md b/research/muse-responses-openai-transpiler/llmfly-gpt6-astra-migration-guide.md new file mode 100644 index 0000000..da196c5 --- /dev/null +++ b/research/muse-responses-openai-transpiler/llmfly-gpt6-astra-migration-guide.md @@ -0,0 +1,28 @@ +# GPT-6 Astra API Migration Guide: Breaking Changes + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | GPT-6 Astra API Migration Guide: Breaking Changes | +| Source URL | https://llmfly.ai/blog/2026/09/05/gpt-6-astra-api-migration-guide/ | +| Source type | blog post | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `migrate Chat Completions to Responses` search on 2026-10-11. Third-party migration guide claiming Responses-required tool calling on newer models. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/medium-praveen-singh-responses-vs-chat.md b/research/muse-responses-openai-transpiler/medium-praveen-singh-responses-vs-chat.md new file mode 100644 index 0000000..7953af6 --- /dev/null +++ b/research/muse-responses-openai-transpiler/medium-praveen-singh-responses-vs-chat.md @@ -0,0 +1,28 @@ +# OpenAI's API Evolution: Responses API vs. Chat Completions API | by Praveen Singh | Jan, 2026 | Medium + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | OpenAI's API Evolution: Responses API vs. Chat Completions API | by Praveen Singh | Jan, 2026 | Medium | +| Source URL | https://medium.com/@praveenkumarsingh/openais-api-evolution-responses-api-vs-chat-completions-api-0463d73ce631 | +| Source type | blog post | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `OpenAI official OpenAPI specification` search on 2026-10-11. Evolution overview: Chat supported, Responses recommended for new work. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/openai-chat-completions-api-reference.md b/research/muse-responses-openai-transpiler/openai-chat-completions-api-reference.md new file mode 100644 index 0000000..399c11a --- /dev/null +++ b/research/muse-responses-openai-transpiler/openai-chat-completions-api-reference.md @@ -0,0 +1,60 @@ +# Chat Completions | OpenAI API Reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Chat Completions | +| Source URL | https://developers.openai.com/api/reference/resources/chat | +| Source publisher / author | OpenAI | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The full Chat Completions reference. It defines `POST /chat/completions` over a `messages` array with system/developer/user/assistant/tool roles, externally-tagged function tools, `tool_choice` (none/auto/required/named/allowed-tools), `response_format` structured outputs, and `delta`-based stream chunks. This is the "classic" side of the transpiler. + +## Key findings + +- Create call is `POST /chat/completions`; "Returns a chat completion object, or a streamed sequence of chat completion chunk objects if the request is streamed." +- "Starting a new project? We recommend trying Responses to take advantage of the latest OpenAI platform features." +- Developer messages: "Developer-provided instructions that the model should follow, regardless of messages sent by the user. With o1 models and newer, `developer` messages replace the previous `system` messages." The system entry says "With o1 models and newer, use `developer` messages for this purpose instead." +- Assistant tool calls are `{id, type: "function", function: {name, arguments}}` with string JSON arguments; tool answers are `{role: "tool", tool_call_id, content}` with text-only content. +- `tool_choice`: "`none` means the model will not call any tool", "`auto` means the model can pick", "`required` means the model must call one or more tools"; named choice is `{"type": "function", "function": {"name": ...}}`, plus an `allowed_tools` mode. +- Function tools are externally tagged: `{type: "function", function: {name, description, parameters, strict}}`. +- `response_format` supports text, `json_object`, and `json_schema {name, description, schema, strict}`. +- Stream chunks are `chat.completion.chunk` objects with `choices[].delta` (`role`, `content`, `tool_calls`) and terminal `finish_reason` of `stop`, `length`, or `tool_calls`. +- The request surface includes Chat-only fields with no Responses counterpart: `n`, `stop`, `seed`, `logprobs`, `frequency_penalty`, `presence_penalty`, `logit_bias`, `prediction`, `modalities`, audio, and `web_search_options`. + +## Pros / strengths + +- Authoritative and complete for the classic surface, including deprecated `function_call` and refusal parts. +- Exact `tool_calls` / `tool_call_id` correlation semantics, which map 1:1 onto Responses `call_id`. +- Explicit Responses recommendation links the two APIs as one migration story. + +## Cons / limitations / caveats + +- The fetch was truncated; findings rest on the messages/tools/choice/format/streaming sections, not the modality guides. +- Chat is the legacy-recommended surface, so new model capabilities (reasoning + tools, newer built-ins) may never land here. +- Some newer model constraints (e.g. tool-calling limits with reasoning effort) live in guides, not this page. + +## Relevance to tai + +- Defines the classic request, object, and chunk shapes the transpiler accepts and emits. +- The system/developer role history explains why Meta's wire uses `developer` while older clients use `system`: both are valid guidance channels. +- The Chat-only field list becomes the documented drop set with warnings in `chat_to_responses`. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/muse-responses-openai-transpiler/openai-migrate-to-responses.md b/research/muse-responses-openai-transpiler/openai-migrate-to-responses.md new file mode 100644 index 0000000..2c1b88e --- /dev/null +++ b/research/muse-responses-openai-transpiler/openai-migrate-to-responses.md @@ -0,0 +1,61 @@ +# Migrate to the Responses API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Migrate to the Responses API | +| Source URL | https://developers.openai.com/api/docs/guides/migrate-to-responses | +| Source publisher / author | OpenAI | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +OpenAI's official migration guide from Chat Completions to the Responses API. It states Responses is the recommended primitive for new projects while Chat Completions remains supported, then gives side-by-side mappings: messages to Items, system guidance to `instructions`, externally-tagged function tools to internally-tagged ones, `response_format` to `text.format`, and `delta` stream chunks to typed server-sent events. + +## Key findings + +- "While Chat Completions remains supported, Responses is recommended for all new projects." +- "The input to, and result of, a call to Chat Completions is an array of _Messages_, while the Responses API uses _Items_." A `message` is one Item type alongside `function_call` and `function_call_output`. +- "Chat Completions can return multiple parallel generations as `choices`, using the `n` parameter. The Responses API omits this parameter and returns only one generation." +- System or developer guidance maps to "Top-level `instructions`, or compatible message Items when you need to preserve an existing transcript". +- "Use `previous_response_id` when you want OpenAI to manage prior response context. Resend stable `instructions` on each request, because `previous_response_id` does not carry over the previous response's top-level `instructions`." +- Function definitions differ twice: "In Chat Completions, function definitions are externally tagged. In Responses, they are internally tagged." Chat functions are non-strict by default; Responses omitting `strict` attempts strict mode and falls back best-effort, so explicit `strict: false` preserves Chat behavior. +- "In the Responses API, Structured Outputs definitions have moved from `response_format` to `text.format`". +- "Chat Completions streaming returns incremental chunks with a `delta` field. Responses streaming uses typed server-sent events." Text uses `response.created`, `response.output_text.delta`, `response.completed`, `error`; function calls add `response.function_call_arguments.delta` and `response.function_call_arguments.done`. +- State: "Responses are stored by default. Chat completions are stored by default for new accounts. To disable storage in either API, set `store: false`." Stateless reasoning continues via encrypted reasoning items. +- Starting with GPT-5.4, "Chat Completions does not support tool calling with `reasoning_effort` values other than `none`". + +## Pros / strengths + +- Authoritative primary source with side-by-side request/response/streaming examples in six languages. +- Explicit loss points (single generation, no `choices`, typed events) instead of marketing gloss. +- Covers failure modes: common migration errors list plus an incremental rollout checklist. + +## Cons / limitations / caveats + +- The capabilities comparison table rendered with empty cells in the fetched copy, so per-capability parity claims could not be verified from this page. +- Model-specific claims (GPT-5.x/6.x behavior, eval deltas) are version-sensitive and will rot. +- Says nothing about vendor extensions such as Meta's `type: namespace` tools, `prompt_cache_key` values, or `x-tbh-*` headers. + +## Relevance to tai + +- This is the primary mapping spec behind the bidirectional transpiler: instructions/system equivalence, tool re-tagging, `text.format`, single-generation loss, and typed-event streaming. +- Confirms the system-message answer three ways (top-level `instructions` preferred, message Items otherwise). +- Confirms `store: false` + encrypted reasoning as the stateless pattern Meta's client uses (`include: ["reasoning.encrypted_content"]` in the capture). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/muse-responses-openai-transpiler/openai-responses-api-reference.md b/research/muse-responses-openai-transpiler/openai-responses-api-reference.md new file mode 100644 index 0000000..da43773 --- /dev/null +++ b/research/muse-responses-openai-transpiler/openai-responses-api-reference.md @@ -0,0 +1,59 @@ +# Responses | OpenAI API Reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Responses | +| Source URL | https://developers.openai.com/api/reference/resources/responses | +| Source publisher / author | OpenAI | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The full Responses API reference. It defines `POST /responses` body parameters, the `EasyInputMessage` input shape, internally-tagged function tools, `function_call` / `function_call_output` Items correlated by `call_id`, output messages with `output_text` / `refusal` parts, and the typed SSE event vocabulary. Every Meta request field in the local capture has a documented counterpart here except the `muse` namespace tool. + +## Key findings + +- Create call is `POST /responses` with body parameters including `input`, `instructions`, `tools`, `tool_choice`, `text`, `stream`, `store`, `previous_response_id`, `max_output_tokens`, `reasoning`, `include`, `prompt_cache_key`, `parallel_tool_calls`, `temperature`, `top_p`, `truncation`, `metadata`, and `user`. +- `instructions` is "A system (or developer) message inserted into the model's context." and "When using along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response." +- `EasyInputMessage` roles are exactly `user`, `assistant`, `system`, `developer`; string content or part lists of `input_text`, `input_image`, `input_file`. +- Function tools are internally tagged: `{type: "function", name, parameters, strict, description, ...}`. +- `function_call` Items carry string `arguments`, a `call_id` ("The unique ID of the function tool call generated by the model"), and `name`; `function_call_output` answers with the same `call_id` plus string or part-list `output`. +- Output messages contain `output_text` (`{text, annotations, logprobs, type}`) or `refusal` (`{refusal, type}`) parts. +- Streaming vocabulary includes `response.created`, `response.in_progress`, `response.output_text.delta` (`{item_id, output_index, content_index, delta}`), `response.function_call_arguments.delta` / `.done`, and `response.completed` carrying the full response object with `usage {input_tokens, output_tokens, total_tokens}`. +- `include` supports `reasoning.encrypted_content`: "Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly". + +## Pros / strengths + +- Authoritative schema detail down to field optionality, with request and SSE examples. +- `include` / `store: false` / encrypted-reasoning semantics directly explain the Meta client's stateless posture. +- Documents both lifecycle events and delta events, which is exactly what a stream transpiler needs. + +## Cons / limitations / caveats + +- The page is about 5 MB; the fetch was truncated and the dossier rests on targeted excerpts (create params, input/tool/output/streaming sections), not a full read. +- No `namespace` tool type is documented, confirming Meta's `muse` tool set is a vendor extension with no portable mapping. +- Fast-moving surface: newer built-in tools and programmatic-calling fields postdate any fixed summary. + +## Relevance to tai + +- Supplies the exact request, object, and event shapes the transpiler emits and parses. +- Verifies the absence of `n`, `stop`, `seed`, and sampling-penalty parameters, which become documented transpile-time drops. +- The `prompt_cache_key` parameter exists upstream too, so Meta's cache keys transpile as scalars rather than extensions. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/muse-responses-openai-transpiler/platform-openai-moderations-reference.md b/research/muse-responses-openai-transpiler/platform-openai-moderations-reference.md new file mode 100644 index 0000000..bf34715 --- /dev/null +++ b/research/muse-responses-openai-transpiler/platform-openai-moderations-reference.md @@ -0,0 +1,28 @@ +# Moderations | OpenAI API Reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Moderations | OpenAI API Reference | +| Source URL | https://platform.openai.com/docs/api-reference/moderations | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:platform.openai.com Create response` search on 2026-10-11. Surfaced on the `instructions` keyword via the self-harm/instructions category; irrelevant. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/platform-openai-realtime-conversation-item-delete.md b/research/muse-responses-openai-transpiler/platform-openai-realtime-conversation-item-delete.md new file mode 100644 index 0000000..34dba14 --- /dev/null +++ b/research/muse-responses-openai-transpiler/platform-openai-realtime-conversation-item-delete.md @@ -0,0 +1,28 @@ +# API Reference - OpenAI API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | API Reference - OpenAI API | +| Source URL | https://platform.openai.com/docs/api-reference/realtime-client-events/conversation/item/delete?ref=pubrio.com | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:platform.openai.com Create response` search on 2026-10-11. Realtime conversation-event page; off-topic for the text APIs. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/platform-openai-realtime-input-audio-commit.md b/research/muse-responses-openai-transpiler/platform-openai-realtime-input-audio-commit.md new file mode 100644 index 0000000..430f56d --- /dev/null +++ b/research/muse-responses-openai-transpiler/platform-openai-realtime-input-audio-commit.md @@ -0,0 +1,28 @@ +# API Reference - OpenAI API + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | API Reference - OpenAI API | +| Source URL | https://platform.openai.com/docs/api-reference/realtime-beta-client-events/input_audio_buffer/commit?ref=hackernoon.com | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:platform.openai.com Create response` search on 2026-10-11. Realtime client-event page mentioning response.create instructions and tools; off-topic for the text APIs. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/muse-responses-openai-transpiler/platform-openai-realtime-session-client-events.md b/research/muse-responses-openai-transpiler/platform-openai-realtime-session-client-events.md new file mode 100644 index 0000000..fa5d4ac --- /dev/null +++ b/research/muse-responses-openai-transpiler/platform-openai-realtime-session-client-events.md @@ -0,0 +1,28 @@ +# Client events | OpenAI API Reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | muse-responses-openai-transpiler | +| Document type | Source Citation Card | +| Tier | 2 | +| Source title | Client events | OpenAI API Reference | +| Source URL | https://platform.openai.com/docs/api-reference/realtime-client-events/session?ref=nekonya.cyou | +| Source type | vendor docs | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark (Muse Code), on behalf of retoor | +| Research method | Search aggregator result listing (not independently opened or quoted) | +| Confidence | Not independently verified | +| Status | Active | + +## Why it's here + +Surfaced by the `site:platform.openai.com Create response` search on 2026-10-11. Realtime session-events page; off-topic for the text APIs. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Logged as consulted-but-not-analyzed. | diff --git a/research/tui-framework-design/ai-nexus-ratatui-best-practices.md b/research/tui-framework-design/ai-nexus-ratatui-best-practices.md new file mode 100644 index 0000000..a3c2ff5 --- /dev/null +++ b/research/tui-framework-design/ai-nexus-ratatui-best-practices.md @@ -0,0 +1,48 @@ +# ai-nexus ratatui best-practices — 80-column breakpoint guidance + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | ai-nexus ratatui best-practices.md — side-by-side vs stacked guidance | +| Source URL | https://raw.githubusercontent.com/jsk9999/ai-nexus/main/config/skills/ratatui_rs/referencecs/best-practices.md | +| Source publisher / author | jsk9999 (ai-nexus project) | +| Source type | other (guidance/reference doc in repository) | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Low | +| Status | Active | + +## Summary + +A guidance document (not a shipped client) recommending side-by-side panes at widths of 80 columns and above with a stacked layout below, and mentioning fixed-cell sidebar widths. It is the sole source of the 80-column breakpoint number — and its guidance-doc status, versus the unanimous Percentage(30) splits and manual toggles of the inspected shipped clients, is its main caveat. + +## Key findings + +- Recommends side-by-side layout at terminal widths >= 80 columns, stacked layout below 80. +- Mentions fixed-cell sidebar widths (e.g. `Length`-style constants) rather than percentage splits. + +## Pros / strengths + +- The only inspected source that states any breakpoint number at all, giving tai a starting value to validate rather than a blank field. + +## Cons / limitations / caveats + +- Guidance doc, not a shipped client: no inspected real client implements automatic narrow-terminal breakpoints, so the 80-column rule is unvalidated by shipped behavior. +- Its fixed-cell sidebar widths contradict every inspected client, which all use `Percentage(30)` — the clients win this argument, not the doc. + +## Relevance to tai + +- Supplies the provisional sub-80-column auto-hide breakpoint in the messaging-layout conclusion, explicitly flagged there as guidance-doc-sourced and sequenced after the manual toggle that shipped clients actually implement. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/axhub-telegram-mobile-design.md b/research/tui-framework-design/axhub-telegram-mobile-design.md new file mode 100644 index 0000000..b74ad67 --- /dev/null +++ b/research/tui-framework-design/axhub-telegram-mobile-design.md @@ -0,0 +1,51 @@ +# axhub-make Telegram mobile theme teardown (DESIGN.md) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | telegram-mobile DESIGN.md (axhub-make theme teardown) | +| Source URL | https://raw.githubusercontent.com/lintendo/axhub-make/HEAD/client/src/themes/telegram-mobile/DESIGN.md | +| Source publisher / author | lintendo/axhub-make (third party) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A third-party teardown of Telegram's iOS client recording native chrome colors (outgoing accent-blue bubbles, neutral incoming bubbles, `#0088CC` accent) and the only type-and-spacing scale found anywhere: system fonts, 17pt body, 14pt in-bubble sender names, 11pt in-bubble time, 44px touch targets, 10pt radii, 50pt CTA height. Valuable and entirely unofficial. + +## Key findings + +- Native chrome: outgoing bubble `#2B86FD` with white text; incoming bubble white (light) / `#2A2A2A` (dark); accent `#0088CC`; canvas `#FFFFFF` (light) / `#212121` (dark). +- Typography is the system font (SF Pro on iOS, Roboto on Android): 17pt body text, 17pt semibold names, 14pt semibold sender names inside bubbles, 13pt list time, 11pt in-bubble time. +- Spacing scale: 44px-plus touch targets, 16px-plus input font (avoids mobile zoom), 10pt corner radii, 50pt CTA height. + +## Pros / strengths + +- The only source found with concrete type sizes and spacing numbers for anything Telegram-shaped. +- Chrome colors corroborate the official Desktop theme files directionally (blue outgoing, neutral incoming). + +## Cons / limitations / caveats + +- Third-party iOS teardown, unverified against Android and Desktop: treat every number as indicative, not canonical. +- No official typography or spacing specification exists in Telegram's docs, so there is nothing authoritative to check these numbers against (open gap). +- Pixel units (radii, CTA height, touch targets) have no literal terminal equivalent; only relative emphasis transfers. + +## Relevance to tai + +The sole basis for tai's Telegram-derived type emphasis scale (body > sender > time) and the accent-blue outgoing convention; every value it contributes is flagged third-party in the conclusions that use it. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/bubbletea-chat-example.md b/research/tui-framework-design/bubbletea-chat-example.md new file mode 100644 index 0000000..1fcf79f --- /dev/null +++ b/research/tui-framework-design/bubbletea-chat-example.md @@ -0,0 +1,50 @@ +# bubbletea examples/chat — viewport plus textarea chat example + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | bubbletea examples/chat/main.go — chat example (no sidebar) | +| Source URL | https://raw.githubusercontent.com/charmbracelet/bubbletea/main/examples/chat/main.go | +| Source publisher / author | Charm (bubbletea project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Charm's own minimal chat example: a full-width transcript viewport over a 3-row textarea with a 280-character limit, resizing both to the window on `WindowSizeMsg`, jumping to the bottom on send and resize, with Enter to send and Esc/Ctrl+C to quit. Notably sidebar-free. + +## Key findings + +- Layout is a transcript viewport plus a 3-row textarea (placeholder `Send a message...`, `CharLimit` 280, box-glyph prompt); there is no sidebar or chat list. +- `WindowSizeMsg` resizes both components to full width with viewport height set to window height minus textarea height; sends and resizes trigger `GotoBottom`. +- Enter sends; Esc or Ctrl+C quits. + +## Pros / strengths + +- Authoritative minimal precedent from the framework authors: the viewport-resize math and send-then-bottom pattern are directly reusable. +- Shows the no-sidebar endpoint of the design space, bounding tai's choice. + +## Cons / limitations / caveats + +- An example, not a shipped client: no chat list, no status bar, no history, no per-message state — tai needs the fuller clients for those. +- Full-width single-pane layout is rejected for tai, which needs a conversation list. + +## Relevance to tai + +- Contributes the viewport height math (window minus input) and send-then-bottom behavior to the messaging-layout conclusion; its sidebar-free shape is recorded there as a considered and rejected alternative. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/bubbletea-glamour-example.md b/research/tui-framework-design/bubbletea-glamour-example.md new file mode 100644 index 0000000..4ece394 --- /dev/null +++ b/research/tui-framework-design/bubbletea-glamour-example.md @@ -0,0 +1,49 @@ +# bubbletea examples/glamour — markdown rendering width math + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | bubbletea examples/glamour/main.go — Glamour markdown example | +| Source URL | https://raw.githubusercontent.com/charmbracelet/bubbletea/main/examples/glamour/main.go | +| Source publisher / author | Charm (bubbletea project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Charm's markdown-in-a-viewport example: content is rendered through the Glamour markdown renderer into a viewport, with the render width computed as viewport width minus frame size minus a 3-column gutter, and dark/light style auto-detected. A thin source; the width formula is the finding. + +## Key findings + +- Markdown is rendered via the Glamour renderer into a scrollable viewport (static content, not streaming). +- Render width equals viewport width minus frame size minus a 3-column gutter; dark/light style is auto-detected. + +## Pros / strengths + +- The width-minus-chrome formula is exactly the rule tai's markdown renderer needs, from the framework authors. +- Demonstrates that markdown belongs in the transcript viewport, not in a separate pane. + +## Cons / limitations / caveats + +- Static markdown only: no streaming or incremental re-render behavior to learn from. +- Glamour itself is a Go library; tai needs a native equivalent, not this code. + +## Relevance to tai + +- Supplies the markdown width-minus-chrome rule adopted in the messaging-layout conclusion (markdown for assistant content, rendered at viewport width minus frame and gutter). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/bubbletint-readme.md b/research/tui-framework-design/bubbletint-readme.md new file mode 100644 index 0000000..b3d9268 --- /dev/null +++ b/research/tui-framework-design/bubbletint-readme.md @@ -0,0 +1,49 @@ +# bubbletint README — tint registry and runtime switching + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | bubbletint README — theme collection for bubbletea/lipgloss | +| Source URL | https://raw.githubusercontent.com/lrstanley/bubbletint/master/README.md | +| Source publisher / author | lrstanley (bubbletint project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A 340-plus theme collection for the bubbletea/lipgloss ecosystem with the registry shape tai wants: a global default registry plus custom registries, runtime switching, and JSON file loading. The registry mechanics are the finding, not the tint count. + +## Key findings + +- Ships 340+ named tints behind a registry API with a global default registry plus support for custom registries. +- Supports switching themes at runtime and loading themes from JSON files. + +## Pros / strengths + +- Registry-shape precedent: global default plus custom registries plus file loading covers every lookup need with one pattern. +- Proves JSON file loading composes cleanly with a dict-style registry. + +## Cons / limitations / caveats + +- Tints target lipgloss's role-less model, so per-theme structure is thinner than tai's role palette; the registry shape ports, the theme contents do not. +- Scale (340+) is ecosystem-collection scale; tai ships 4–6 builtins. + +## Relevance to tai + +- Registry-shape precedent for the palette-role conclusion (`THEMES` dict plus `register_theme`), and the JSON-load precedent behind the deferred file-override design. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/conclusions/messaging-layout-chat-scene.md b/research/tui-framework-design/conclusions/messaging-layout-chat-scene.md new file mode 100644 index 0000000..268f886 --- /dev/null +++ b/research/tui-framework-design/conclusions/messaging-layout-chat-scene.md @@ -0,0 +1,64 @@ +# Conclusion: Telegram-like messaging layout for tai's chat scene + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | Medium | + +## Question / problem statement + +How should tai's Telegram-like chat scene (conversation sidebar, message transcript, input box, status line) be laid out, navigated, and rendered on top of the retained-DOM framework — which geometry, which keybindings, which scroll and send contracts — given that the working tree has no chat-transcript widget, no status-bar widget, no send-on-Enter mode, and no responsive breakpoints (established by the same-session internal inventory of tai.py)? + +## Conclusion + +Build the chat scene as a left chat list at 30% width (min 24, max 36 columns) beside a right transcript plus input, with the input 3 rows collapsed growing to 5–8 rows with content and a 1-line status bar at the bottom carrying transient status plus per-focus hints on one side and connection/user/chat identity on the other. Ship a manual sidebar toggle first (F2/Ctrl+B or Tab cycle), adding automatic hide below 80 columns only as an enhancement. Navigate modally (Normal/Input) with Tab/Shift+Tab pane cycling, `i`/Enter/Esc, `j`/`k` plus arrows, `g`/`G`, PgUp/PgDn, `/` search, `?` hints, `q` quit. Render left-aligned wrapped rows with sender grouping and per-message sending/failed state (never right-aligned bubbles); render markdown only for assistant content at viewport width minus frame minus gutter; stream by re-setting viewport content with pin-to-bottom only when already at the bottom; show tool calls as collapsible bordered block rows. Input is multiline with Enter to send, Shift+Enter (or Alt+Enter) for newline, per-chat draft retention, send history, and a ~2000-character cap with optimistic echo. + +## Supporting sources + +- `../telecli-tui-chat-layout.md` — base numbers: 30/70 split, 3-row input, 1-line status overlay, modal Normal/Input keys. +- `../send-rs-tui-draw-main.md` — confirms the 30/70 + 1-line-status skeleton; focused-pane accent border. +- `../send-rs-tui-focus-state.md` — explicit focus state with per-chat draft retention on focus moves. +- `../send-rs-config-keymap.md` — default keymap (Tab cycle, `i`/Enter/Esc, Shift+Enter newline) and 5-line input cap. +- `../send-rs-tui-status-bar.md` — status content policy: per-focus hints with transient-override messages. +- `../send-rs-chat-widget.md` — pre-wrapped rows plus scrollbar, dynamic input height, and the decisive bubble rejection. +- `../za-tui-app-styles.md` — cross-framework corroboration of 30/70 + 3–8-row input + 1-row status. +- `../za-tui-main-screen.md` — manual sidebar toggle (F2/Ctrl+B) with auto-hide deliberately omitted; F6 focus cycle. +- `../za-tui-status-bar.md` — identity half of status content: connection dot + user + active conversation. +- `../za-tui-input-bar.md` — input contract: Enter send, Shift+Enter newline, 2000-char cap, 100-entry history. +- `../za-tui-chat-view.md` — transcript contract: sender grouping, per-message status, conditional pin-to-bottom, scroll-top history load. +- `../bubbletea-chat-example.md` — viewport height math (window minus input) and send-then-bottom behavior. +- `../bubbletea-glamour-example.md` — markdown width-minus-chrome rule (viewport minus frame minus 3-column gutter). +- `../ai-nexus-ratatui-best-practices.md` — provisional sub-80-column breakpoint number (guidance-doc sourced, flagged as such). + +## Alternatives considered and rejected + +- Right-aligned outgoing bubbles: rejected — send-rs implemented them and reverted them as ugly; all shipped clients use left-aligned rows. +- Automatic sidebar auto-hide from day one: rejected as v1 — za-tui deliberately omitted it (breaks tests) and ships manual toggle; auto-hide below 80 columns follows as an enhancement. +- Sidebar-free full-width layout (bubbletea chat example): rejected — tai needs a conversation/agent list beside the transcript. +- Fixed-cell sidebar width (`Length(30)`): rejected — appears only in the guidance doc while every inspected client uses `Percentage(30)`; percentage with min/max clamps wins. +- Always-stacked layout: rejected — all three messaging clients ship side-by-side as the default, stacking only as the narrow fallback. + +## Risks / open questions + +- The 80-column breakpoint comes from a guidance doc, not a shipped client — no inspected real client implements automatic narrow-terminal breakpoints. Validate the number against real terminals before treating it as settled. +- No streaming/token rendering or tool-call blocks were observed in any messaging client; the re-set-plus-pin-to-bottom carrier and collapsible-block rows are inferred patterns, with Glamour covering static markdown only. +- tai still needs a markdown-to-styled-run renderer (the REPL's `render_markdown` emits ANSI strings unusable by the compositor), a send-on-Enter input mode, and a wide-character width table — all established gaps from the same-session inventory. +- Agent turns are blocking and must run in threads posting back via timers; the streaming contract assumes that bridge works. + +## Action taken + +Nothing built yet: the chat scene is specified by this conclusion and its sources, but no chat-transcript widget, status-bar widget, or scene builder exists in the working tree. This conclusion records what to build, not what shipped. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | diff --git a/research/tui-framework-design/conclusions/palette-role-theming.md b/research/tui-framework-design/conclusions/palette-role-theming.md new file mode 100644 index 0000000..b325016 --- /dev/null +++ b/research/tui-framework-design/conclusions/palette-role-theming.md @@ -0,0 +1,59 @@ +# Conclusion: Minimal palette-role theming for tai's TUI + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | Medium | + +## Question / problem statement + +How should tai's retained-DOM TUI gain themes — how many color roles, what registry and switching mechanism, what flag/env precedence, and how widgets resolve colors — given that the working tree has no theme object, no stylesheet, and no palette indirection (every widget hardcodes inline `TuiStyle` values, established by the same-session internal inventory of tai.py)? + +## Conclusion + +Ship a 12-role palette: surfaces `bg` and `surface`; text `fg` and `muted`; chrome `border`, `accent`, `on_accent`, and `selection`; semantic `success`, `warning`, `error`, and `info` — each theme also carrying a `dark` flag, colors as hex strings resolved at render. Hold themes in a `THEMES: dict[str, Theme]` registry (`Theme` a dataclass of name, dark flag, and role dict) with `register_theme()` for user themes and 4–6 kebab-case builtins (`dark`, `light`, `nord`, `gruvbox`, `ansi`). Select with a `--theme` flag validated against the registry (unknown names print the list and exit 2); precedence is flag > `TAI_THEME` env var > default. Switch at runtime via `App.set_theme(name)`, which swaps the pointer and triggers a full redraw, plus one cycle key (e.g. F4) advancing registry order. Style objects store role names and resolve against the current theme at draw time; raw colors (`#rrggbb`, ANSI names) pass through as an escape hatch; per-widget override dicts merge over theme roles. Defer file-based overrides; if ever added, merge a partial role dict from TOML/JSON over a named theme. + +## Supporting sources + +- `../textual-theme-module.md` — role names and kebab-case dict registry template (11 bases, 21 builtins); generated-shade machinery explicitly not copied. +- `../textual-design-guide.md` — live-switch contract (swap pointer plus redraw) and user-facing switcher precedent. +- `../textual-constants-theme-env.md` — env-var default precedent behind flag > `TAI_THEME` > default. +- `../lipgloss-pkg-docs.md` — negation precedent (roles omitted) and the deferred `AdaptiveColor` light/dark idea. +- `../bubbletint-readme.md` — registry-shape precedent (global default plus custom registries, JSON file load). +- `../ratatui-themes-readme.md` — closest minimal precedent: small fixed role set, named registry, next/prev cycling, serialization. +- `../ratatui-kit-theming.md` — resolution pattern: palette as source of truth, derive at draw time, non-exhaustive growth headroom. +- `../pytermgui-styling-docs.md` — live-regenerate spirit (a switch repaints everything) and shade offsets; single-primary limit is why tai takes 12 roles. +- `../pytermgui-file-loaders.md` — file-override precedent behind the deferred TOML/JSON partial-dict merge. + +## Alternatives considered and rejected + +- Full Textual-style generated shade/variable system: rejected — the generator machinery is Textual-scale overkill for tai; copy the role names and registry, not the generator. +- lipgloss-style raw colors with no roles: rejected — leaves every theme need to the user, which is the gap being filled; roles are the point. +- pytermgui-style single-primary global palette: rejected — one primary cannot express independent semantic hues (success/warning/error/info); 12 roles instead. +- File-based TOML/JSON theme overrides now: rejected as v1 — deferred until a real user need appears; the merge design is recorded so it can be added without registry changes. +- Light/dark auto-detection (`AdaptiveColor` style) now: rejected as v1 — recorded as a later enhancement, not launch scope. + +## Risks / open questions + +- The 12-role set is an intersection of surveyed systems, not a validated minimum; new widget needs may force additions (the non-exhaustive lesson anticipates this). +- ratatui core's own styling primitives were never fetched — "no registry in core" is inference from ecosystem crates only, so a core-side precedent may exist unexamined. +- pytermgui `NO_COLOR` details, Textual's app-level `get_css_variables` override, and lipgloss v2's `LightDark` successor were seen in snippets only and remain unverified; the REPL already honors `NO_COLOR`, and the TUI must match it when themes land. +- Full-redraw switching assumes redraws stay cheap as scenes grow; revisit if theme switches visibly lag. + +## Action taken + +Nothing built yet: no `Theme` dataclass, registry, flag, or role resolution exists in the working tree — widgets still hardcode inline styles. This conclusion records what to build, not what shipped. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | diff --git a/research/tui-framework-design/conclusions/telegram-chat-grammar-adoption.md b/research/tui-framework-design/conclusions/telegram-chat-grammar-adoption.md new file mode 100644 index 0000000..5e9b788 --- /dev/null +++ b/research/tui-framework-design/conclusions/telegram-chat-grammar-adoption.md @@ -0,0 +1,65 @@ +# Conclusion: Telegram chat grammar tai adopts (rows, not bubbles) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | High | + +## Question / problem statement + +Which Telegram look-and-feel patterns should tai's TUI chat scene adopt now that rows-not-bubbles is already decided — which glyphs, palettes, pills, labels, and bot surfaces transfer to a terminal, and which stay behind — given that the working tree has no bubbles, ticks, date dividers, header bar, rich list rows, or composer buttons (established by the same-session internal inventory of tai.py, which mapped each missing piece to a patch target but produced no source documents, being internal code)? + +## Conclusion + +Adopt Telegram's metadata grammar rendered as left-aligned rows: clock for sending, single check for cloud receipt, blue double check for read, eye-plus-count for broadcast views, and no delivered state ever; color group sender names from the 8-hue peer palette in its day and night re-tones; render date dividers and service events as centered pills with `{month} {day}` phrasing, and unread position as an `N Unread Message(s)` bar; use Telegram's literal copy for the status line (`online`, `typing...`, the seven-step last-seen scale), the composer (`Write a message...`, red `Draft:`, blue typing override), and bot surfaces (`Menu` button, `Show/Hide bot keyboard`, Start button on first open, `/start` deep links up to 64 chars, global `/start` `/help` `/settings`, max 100 scoped commands with `/` autocomplete, reply keyboards distinct from inline message buttons). Reject right-aligned bubbles (already rejected), gradient/animated per-chat bubble themes, and any delivered-to-device state. + +## Supporting sources + +- `../tdesktop-day-blue-theme.md` — light defaults: bubble, time, service-pill, unread-pill hexes; day peer palette. +- `../tdesktop-night-theme.md` — dark defaults pairing every day key; night peer palette re-tones. +- `../telegram-faq.md` — check semantics (cloud, read, no delivered state) and the 30s online rule. +- `../telegram-blog-chat-themes-read-receipts.md` — group receipt rule (one reader, tap-for-readers, 7 days); gradient themes as the explicit rejection boundary. +- `../techmesto-telegram-checkmarks.md` — corroborates clock/blue-checks; supplies the channel eye-plus-views treatment. +- `../tdesktop-lang-strings.md` — literal copy for status scale, unread bar, composer, attach, bot toggles, reply/edit. +- `../telegram-android-dialog-cell.md` — sidebar row element inventory: avatar, name plus time, snippet with prefixes, pill, pin/mute, draft-red, typing-blue. +- `../telegram-android-chat-message-cell.md` — grouping grammar (joined same-sender runs, tail-on-last, trailing time plus checks, peer-hue names). +- `../telegram-bot-api.md` — reply vs inline keyboard grammar, menu button variants, 100-command cap, placeholder contract. +- `../telegram-bot-features.md` — Start-button first open, `?start=` deep links, three global commands. + +## Alternatives considered and rejected + +- Literal bubble rendering with tails and alternating alignment: rejected — rows-not-bubbles is already decided, and send-rs precedent plus all shipped clients confirm rows. +- Inventing tai-native status glyphs: rejected — Telegram's clock/check/eye vocabulary is settled and recognizable; invention adds learning cost for no gain. +- Copying per-chat gradient/animated bubble themes: rejected — no terminal equivalent exists; theming stays at the palette-role level. +- A delivered-to-device state: rejected — Telegram deliberately has none (multi-device), so there is nothing to mirror. + +## Risks / open questions + +- iOS and Web client exact hexes were never verified; only Desktop day/night values are canonical here. +- Bubble corner radii, paddings, inter-message spacing, and tail shape/side per client are unknown — mostly moot under rows-not-bubbles, but any future bubble attempt must re-research them. +- Conversation header icon inventory per client (call/video/search/more) was not captured. +- Chat-list time/date formatting rules and snippet truncation behavior were not captured. +- Send-vs-voice button swap behavior and media-bubble time-overlay details were not captured. + +## Action taken + +Nothing built yet: the transcript still renders plain left rows with sender-change headers only, the sidebar shows plain names, and no ticks, pills, header bar, or bot surfaces exist. The same-session internal inventory maps each adoption to its patch target (transcript rows, send path, status painter, sidebar rows, input container), so this conclusion records what to build and where, not what shipped. + +## Amendment (2026-10-11): user override to literal bubbles + +retoor overrode the rows verdict after seeing the rows UI: `--tui` must look exactly like Telegram, and rows-only does not. Implemented as bg-fill aligned bubble blocks (no box borders): outgoing right-aligned, incoming left-aligned, max 70% width, pad 1, time plus ticks bottom-right inside the bubble. Tails omitted (no terminal equivalent in evidence). Retained from this conclusion: the full metadata grammar (clock/checks/blue-read, no delivered state), service pills, literal copy, bot surfaces. Below the narrow breakpoint bubbles degrade to full-width rows. Original verdict preserved above for the record. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | +| 2026-10-11 | Amendment: user override rows to literal bg-fill bubbles; tails omitted; narrow fallback to full-width rows. | diff --git a/research/tui-framework-design/conclusions/telegram-theme-roles-mapping.md b/research/tui-framework-design/conclusions/telegram-theme-roles-mapping.md new file mode 100644 index 0000000..c0cd6b3 --- /dev/null +++ b/research/tui-framework-design/conclusions/telegram-theme-roles-mapping.md @@ -0,0 +1,62 @@ +# Conclusion: Telegram ThemeParams as tai's theme-role reference + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Conclusion | +| Tier | N/A | +| Date decided | 2026-10-11 | +| Decided by | retoor, advised by tai (agent, Muse Spark) | +| Status | Active | +| Confidence | Medium | + +## Question / problem statement + +How should Telegram's official `ThemeParams` vocabulary relate to tai's already-decided 12-role palette — which keys map to which roles, what default values ship, and what switching discipline applies — given that Telegram's values are user-themeable samples rather than constants, and that the working tree resolves roles at draw time but leaves borders hardcoded and several roles unused (established by the same-session internal inventory of tai.py, internal code, no source documents)? + +## Conclusion + +Treat Telegram's 15 `ThemeParams` keys as the reference vocabulary mapped onto tai's 12 roles: canvas keys (`bg_color`, `secondary_bg_color`, `section_bg_color`, `header_bg_color`, `bottom_bar_bg_color`) onto `bg`/`surface`; text keys (`text_color`, `subtitle_text_color`, `section_header_text_color`, `accent_text_color`) onto `fg`/`muted`/`accent`; `hint_color` onto `muted`; `link_color` onto `accent`; `button_color`/`button_text_color` onto `accent`/`on_accent`; `section_separator_color` onto `border`; `destructive_text_color` onto `error` — with representative light/dark defaults taken from the Desktop theme files and the dark samples (`#17212b` canvas, `#f5f5f5` text, `#708499` hint, `#6ab3f3` link, `#5288c1` button, `#6ab2f2` accent text, `#ec3942` destructive), accent-blue `#2B86FD` outgoing convention, and the 17/14/11pt emphasis scale (third-party, flagged as such). Adopt Telegram's switching discipline as law: never hardcode colors, re-read the theme on every switch (tai's `set_theme` plus full repaint is the `themeChanged` equivalent), and never cache resolved colors across a switch. Defer exact light defaults for `section_*`/`subtitle`/`destructive` until officially published. + +## Supporting sources + +- `../telegram-webapps-docs.md` — the 15-key contract, `light`/`dark` scheme plus `themeChanged`, design rules, chrome inventory. +- `../mini-apps-docs-theming.md` — dark sample values and the never-hardcode/re-read rule. +- `../mini-apps-docs-main-button.md` — bottom primary-action grammar with active/progress states; back control with no implicit behavior. +- `../mini-apps-docs-settings-button.md` — settings-in-overflow-menu placement rule (v6.10+). +- `../mini-apps-docs-viewport.md` — chrome-padding discipline and stable-height rule for bottom-pinned UI. +- `../axhub-telegram-mobile-design.md` — accent-blue outgoing convention and the only type/spacing scale found (third-party, unverified). +- `../tdesktop-day-blue-theme.md` — light-side default values for the mapped roles. +- `../tdesktop-night-theme.md` — dark-side default values for the mapped roles. + +## Alternatives considered and rejected + +- Tai-only role names with no Telegram mapping: rejected — mapping to the industry's most-deployed chat theme vocabulary keeps defaults recognizable and reviewable. +- Hardcoding Telegram hexes as constants: rejected — Telegram's own docs forbid it (values are user-themeable); samples are defaults, resolved at draw through roles. +- Copying pixel geometry (10pt radii, 50pt CTA, 44px targets): rejected — pixel units have no terminal meaning; only relative emphasis and placement discipline transfer. +- Light defaults for `section_*`/`subtitle`/`destructive` invented by symmetry: rejected — unpublished values stay explicitly deferred rather than guessed. + +## Risks / open questions + +- Exact default light-theme hexes for `section_*`, `subtitle`, and `destructive` are not published officially; only dark samples were observed. +- The type/spacing scale rests entirely on a third-party iOS teardown, unverified against Android/Desktop, because no official spec exists. +- The `WebViewColors` diagram (image-only, no alt data) was never inspected and may hold additional guidance. +- The sibling back-button SDK page was listed as consulted but yielded no captured evidence; its details remain unarchived. + +## Action taken + +Nothing built yet: role resolution exists but chat uses only 6 of 12 roles, borders are hardcoded white, and no Telegram-derived defaults or section roles exist. This conclusion records the mapping and discipline to implement, not what shipped. + +## Amendment (2026-10-11): dedicated bubble roles added + +Bubble rendering needed roles the 12-role mapping could not carry without collisions: `bubble_in`, `bubble_out`, `bubble_fg`, `meta_in`, `meta_out`, `tick_read`, `service_bg`, `service_fg`, `unread`, `unread_muted` (dark/light from the tdesktop day/night files, nord/gruvbox mapped by tone, ansi in plain names; `register_theme` now requires all 22 roles). The 12-role mapping above still holds for everything else. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial conclusion recorded. | +| 2026-10-11 | Amendment: 10 dedicated bubble/service/unread roles added (22 total). | diff --git a/research/tui-framework-design/lipgloss-pkg-docs.md b/research/tui-framework-design/lipgloss-pkg-docs.md new file mode 100644 index 0000000..ed2388d --- /dev/null +++ b/research/tui-framework-design/lipgloss-pkg-docs.md @@ -0,0 +1,49 @@ +# lipgloss package docs — raw colors, no role system + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | lipgloss package documentation (pkg.go.dev) | +| Source URL | https://pkg.go.dev/github.com/charmbracelet/lipgloss | +| Source publisher / author | Charm (lipgloss project) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Lipgloss's API documentation shows a styling library with deliberately no role or theme system: it offers raw colors plus `AdaptiveColor` (separate Light/Dark values, auto-detected) and `CompleteColor` (per-terminal-profile values), leaving role structs to the user. Evidence for what tai should not copy wholesale — and for deferring adaptive color. + +## Key findings + +- No built-in theme roles: lipgloss provides color primitives and style composition; role groupings are user-defined structs. +- `AdaptiveColor` carries separate Light and Dark values resolved by auto-detected terminal background; `CompleteColor` carries per-terminal-color-profile values. + +## Pros / strengths + +- `AdaptiveColor` is the cleanest light/dark primitive surveyed: two values plus background detection, no theme machinery required. +- Demonstrates that a styling layer can ship without any role system and still succeed. + +## Cons / limitations / caveats + +- No registry, no switching, no roles — every theme-shaped need is left to the user, which is exactly the gap tai is filling. +- lipgloss v2's `LightDark` successor to `AdaptiveColor` was seen in snippet only, not fetched — not claimed here. + +## Relevance to tai + +- Shapes the palette-role conclusion by negation (tai needs the roles lipgloss omits) and by deferral (the `AdaptiveColor` idea is recorded as a later enhancement, not v1 scope). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/mini-apps-docs-main-button.md b/research/tui-framework-design/mini-apps-docs-main-button.md new file mode 100644 index 0000000..a49f20a --- /dev/null +++ b/research/tui-framework-design/mini-apps-docs-main-button.md @@ -0,0 +1,50 @@ +# Mini Apps SDK docs — MainButton and BackButton + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Main Button documentation (Telegram Mini Apps SDK docs) | +| Source URL | https://docs.telegram-mini-apps.com/platform/main-button | +| Source publisher / author | Telegram Mini Apps community (docs.telegram-mini-apps.com, over the official protocol) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Community SDK documentation for the two primary Mini App buttons: the bottom full-width MainButton reserved for the final action (with text, active, progress, and color control), and the header BackButton, which carries visibility and click plumbing but deliberately no built-in navigation action. + +## Key findings + +- MainButton is a bottom full-width call-to-action for the final action, supporting text, active/disabled state, progress loader, and colors; for attachment-menu launches it stays hidden until the user interacts. +- The class was renamed BottomButton with a SecondaryButton stacked above it, keeping the same bottom-CTA role. +- BackButton is a header-left chevron with show/hide/onClick control and no built-in action: the developer handles every press. + +## Pros / strengths + +- Precise behavioral detail (hidden-until-interact, no-built-in-nav) that the official page states more tersely. +- Documents the current BottomButton/SecondaryButton shape, not just the legacy MainButton name. + +## Cons / limitations / caveats + +- Community docs over the official protocol: may lag or drift from Telegram's own reference, so load-bearing behavior wants official corroboration. +- The sibling back-button page was listed as consulted but no evidence from it was captured, so it is not archived here (open gap). + +## Relevance to tai + +Shapes tai's action-button grammar: one bottom primary action with active/progress states, a header back control with no implicit behavior, and hidden-until-relevant discipline for contextual actions. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/mini-apps-docs-settings-button.md b/research/tui-framework-design/mini-apps-docs-settings-button.md new file mode 100644 index 0000000..c183a08 --- /dev/null +++ b/research/tui-framework-design/mini-apps-docs-settings-button.md @@ -0,0 +1,50 @@ +# Mini Apps SDK docs — SettingsButton + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Settings Button documentation (Telegram Mini Apps SDK docs) | +| Source URL | https://docs.telegram-mini-apps.com/platform/settings-button | +| Source publisher / author | Telegram Mini Apps community (docs.telegram-mini-apps.com, over the official protocol) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Community SDK documentation for the Mini App Settings button: a top-right menu item that developers opt into showing, publicly available to all developers since version 6.10. + +## Key findings + +- The Settings button lives in the top-right menu of the Mini App chrome. +- It is opt-in: the developer calls `show()` to make it appear. +- It has been public to all developers since v6.10. + +## Pros / strengths + +- Settles placement (menu, not header button) and availability (opt-in, v6.10+) in three checkable facts. +- Consistent with the official chrome inventory (Settings as context-menu item). + +## Cons / limitations / caveats + +- Community docs over the official protocol; thin page with no behavioral edge cases. +- Version-pinned availability needs re-checking if tai ever targets older clients (it does not currently). + +## Relevance to tai + +Completes the header-action inventory: settings belongs in an overflow menu reached from the top-right, not as a permanent header button — a placement rule tai's own header actions should follow. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/mini-apps-docs-theming.md b/research/tui-framework-design/mini-apps-docs-theming.md new file mode 100644 index 0000000..220a2ff --- /dev/null +++ b/research/tui-framework-design/mini-apps-docs-theming.md @@ -0,0 +1,50 @@ +# Mini Apps SDK docs — theming samples and re-read discipline + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Theming documentation (Telegram Mini Apps SDK docs) | +| Source URL | https://docs.telegram-mini-apps.com/platform/theming | +| Source publisher / author | Telegram Mini Apps community (docs.telegram-mini-apps.com, over the official protocol) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Community SDK documentation for Mini App theming: representative dark-theme sample values for the core `ThemeParams` keys plus accent, section-header, and destructive samples, and the hard rule to never hardcode colors and always re-read theme parameters on change. + +## Key findings + +- Dark-theme samples: `bg_color #17212b`, `text_color #f5f5f5`, `hint_color #708499`, `link_color #6ab3f3`, `button_color #5288c1`. +- Further dark samples: `accent_text_color #6ab2f2`, `section_header_text_color #6ab3f3`, `destructive_text_color #ec3942`. +- Apps must never hardcode colors and must never cache them without refresh: re-read theme parameters and color scheme on every `themeChanged` event. + +## Pros / strengths + +- The only concrete sample values found for the `ThemeParams` keys, and they agree with the Desktop night theme file (`#17212b`, `#f5f5f5`). +- The re-read discipline is stated as a hard rule, not advice, which settles tai's switch contract. + +## Cons / limitations / caveats + +- Dark samples only: exact default light-theme hexes for the `section_*`, `subtitle`, and `destructive` keys are not published officially (open gap). +- Community docs; samples are representative values from a user-themeable system, not constants to bake in. + +## Relevance to tai + +Provides the dark defaults for tai's Telegram-derived theme roles and the never-hardcode/re-read-on-switch rule that `set_theme` plus full repaint already implements in spirit. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/mini-apps-docs-viewport.md b/research/tui-framework-design/mini-apps-docs-viewport.md new file mode 100644 index 0000000..182baef --- /dev/null +++ b/research/tui-framework-design/mini-apps-docs-viewport.md @@ -0,0 +1,52 @@ +# Mini Apps SDK docs — viewport, safe areas, fullscreen + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Viewport documentation (Telegram Mini Apps SDK docs) | +| Source URL | https://docs.telegram-mini-apps.com/platform/viewport | +| Source publisher / author | Telegram Mini Apps community (docs.telegram-mini-apps.com, over the official protocol) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Community SDK documentation for the Mini App viewport: mobile apps open in a draggable bottom sheet, fullscreen removes the top and bottom bars, layout must pad for both the device safe area and Telegram's content safe area, and bottom-pinned UI must use the animation-stable height. + +## Key findings + +- Mobile Mini Apps open in a draggable BottomSheet; fullscreen mode removes the top and bottom bars. +- Layout must pad for both `safeAreaInset` (notch, system navigation) and `contentSafeAreaInset` (Telegram's own chrome), especially in fullscreen. +- Bottom-pinned UI must use `viewportStableHeight`; `viewportHeight` is animation-unsafe. +- Apps must subscribe to `viewportChanged`, `safeAreaChanged`, and `contentSafeAreaChanged` rather than caching geometry. +- The design baseline is mobile-first at 320-480px widths. + +## Pros / strengths + +- The only source found that separates the two insets (device vs Telegram chrome) with concrete padding guidance. +- The stable-vs-live height distinction is an exact implementable rule for bottom-pinned elements. + +## Cons / limitations / caveats + +- Community docs over the official protocol; mobile-centric, with desktop viewport behavior thin. +- Pixel and sheet metaphors do not transfer literally to a terminal; only the inset/rounding principles carry over. + +## Relevance to tai + +Supplies the chrome-padding discipline tai's scenes should mirror (reserve space for frame chrome, never draw under it, re-read geometry on resize events) and the stable-height rule behind tai's bottom-pinned status line. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/pytermgui-file-loaders.md b/research/tui-framework-design/pytermgui-file-loaders.md new file mode 100644 index 0000000..2387c92 --- /dev/null +++ b/research/tui-framework-design/pytermgui-file-loaders.md @@ -0,0 +1,46 @@ +# pytermgui file_loaders reference — YAML/JSON style files + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | pytermgui file_loaders reference — config, markup, and widget files | +| Source URL | https://ptg.bczsalba.com/reference/pytermgui/file_loaders/ | +| Source publisher / author | bczsalba (pytermgui project) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A thin source with one finding: pytermgui loads YAML/JSON config, markup, and widget files through its `file_loaders` module, runnable via `ptg -f`. It exists here as the file-based-override precedent tai explicitly defers. + +## Key findings + +- YAML/JSON files define config, markup styles, and widget trees, loaded via the `file_loaders` module and runnable with `ptg -f`. + +## Pros / strengths + +- Shows file-based style overrides composing with a palette system with no registry changes. + +## Cons / limitations / caveats + +- Thin source: the merge semantics between file styles and the active palette were not part of the inspected evidence. + +## Relevance to tai + +- Precedent behind the palette-role conclusion's deferred file-override design (a partial role dict from TOML/JSON merged over a named theme, if ever added). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/pytermgui-styling-docs.md b/research/tui-framework-design/pytermgui-styling-docs.md new file mode 100644 index 0000000..209e5d8 --- /dev/null +++ b/research/tui-framework-design/pytermgui-styling-docs.md @@ -0,0 +1,49 @@ +# pytermgui styling docs — global palette and live regenerate + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | pytermgui styling documentation — palette, tags, and widgets | +| Source URL | https://github.com/bczsalba/pytermgui/blob/HEAD/docs/widgets/styling.md | +| Source publisher / author | bczsalba (pytermgui project) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +The simplest theme model surveyed: one global palette regenerated live from a single primary color (`palette.regenerate(primary)`), shade offsets derived from it, and markup tags (`@bg`, `#auto`) resolving against the palette. The live-regenerate spirit is the portable idea. + +## Key findings + +- A single global palette regenerates live from one primary color via `palette.regenerate(primary)`; shades derive as offsets. +- Markup tags (`@bg`, `#auto`) resolve colors against the current palette at render time. + +## Pros / strengths + +- Minimal possible theme API: one color in, whole palette out, live. +- Tag-based palette resolution is the same resolve-at-draw idea as ratatui-kit's derivation, in markup form. + +## Cons / limitations / caveats + +- One primary color cannot express tai's semantic roles (success/warning/error/info need independent hues); tai needs the fuller role set. +- pytermgui `NO_COLOR` support details were seen in snippet only, not fetched — not claimed here. + +## Relevance to tai + +- Contributes the live-regenerate spirit (a switch repaints everything immediately, via tai's full redraw) and the shade-offset idea to the palette-role conclusion; its single-primary limit is why tai adopts 12 roles instead. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/ratatui-kit-theming.md b/research/tui-framework-design/ratatui-kit-theming.md new file mode 100644 index 0000000..ff7cf93 --- /dev/null +++ b/research/tui-framework-design/ratatui-kit-theming.md @@ -0,0 +1,49 @@ +# ratatui-kit theming docs — palette-as-source-of-truth resolution + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | ratatui-kit theming documentation — Palette, themes, Provider switching | +| Source URL | https://github.com/yexiyue/ratatui-kit/blob/HEAD/docs/src/content/docs/core/theming.mdx | +| Source publisher / author | yexiyue (ratatui-kit project) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +The best style-resolution pattern surveyed: a 16-slot `Palette` in 5 groups serves as the single source of truth, component themes derive via `FooTheme::from_palette`, and an `Atom` + `Provider` pair switches the active theme. The palette-derives-everything flow is what tai ports. + +## Key findings + +- One 16-slot `Palette` organized in 5 groups is the source of truth; component themes derive from it (`FooTheme::from_palette`). +- Theme switching goes through an `Atom` + `Provider` pair that swaps the active theme for all derived styles. +- The palette type is marked non-exhaustive, leaving room for the role set to grow. + +## Pros / strengths + +- Derive-don't-duplicate: components never hardcode colors, so a switch propagates everywhere by construction. +- Non-exhaustive palette is the right growth story for a role set that will gain members. + +## Cons / limitations / caveats + +- The Atom/Provider reactivity machinery is framework-scale; tai ports the derivation direction (theme → styles at draw time), not the reactive plumbing. + +## Relevance to tai + +- Resolution pattern behind the palette-role conclusion: style objects store role names and resolve against the current theme at draw time, with raw colors as an escape hatch; the non-exhaustive lesson becomes tai's growth headroom. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/ratatui-themes-readme.md b/research/tui-framework-design/ratatui-themes-readme.md new file mode 100644 index 0000000..bf68b70 --- /dev/null +++ b/research/tui-framework-design/ratatui-themes-readme.md @@ -0,0 +1,50 @@ +# ratatui-themes README — minimal role palette with serde + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | ratatui-themes README — theme palette and registry | +| Source URL | https://github.com/ricardodantas/ratatui-themes/blob/HEAD/README.md | +| Source publisher / author | ricardodantas (ratatui-themes project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +The closest minimal precedent to tai's planned design: a 10-role `ThemePalette` struct, a `ThemeName` enum registry with all/next/prev traversal, and serde serialization for file-backed themes. Small enough to port nearly whole. + +## Key findings + +- Theme contents are a 10-role `ThemePalette` struct — a fixed, small role set. +- The registry is a `ThemeName` enum supporting all/next/prev traversal (listing and cycling). +- Themes serialize via serde, enabling file-backed theme definitions. + +## Pros / strengths + +- Minimal-role palette plus enum registry plus cycling is almost exactly tai's target shape at a slightly smaller role count. +- Serde support shows file-backed themes need no special machinery beyond serialization. + +## Cons / limitations / caveats + +- A Rust enum registry is less open than tai's planned string-keyed dict; user themes in tai register by name rather than by enum variant. +- The 10-role set is fixed; tai's 12 roles plus growth headroom differ in detail. + +## Relevance to tai + +- Closest structural precedent for the palette-role conclusion: fixed small role set, named registry, next/prev cycling key, serialization-ready theme objects. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/send-rs-chat-widget.md b/research/tui-framework-design/send-rs-chat-widget.md new file mode 100644 index 0000000..fff71e6 --- /dev/null +++ b/research/tui-framework-design/send-rs-chat-widget.md @@ -0,0 +1,49 @@ +# send-rs src/tui/chat/chat_widget.rs — message list, scrollbar, dynamic input + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | send-rs src/tui/chat/chat_widget.rs — chat widget (WhatsApp+Telegram ratatui client) | +| Source URL | https://raw.githubusercontent.com/pedromarquetti/send-rs/master/src/tui/chat/chat_widget.rs | +| Source publisher / author | pedromarquetti (send-rs / Sender project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Message rendering as a `List` of pre-wrapped rows with an explicit 1-column scrollbar, a write box whose height grows from its visual row count, and a notable reverted experiment: right-aligned outgoing bubbles were tried and abandoned as ugly. The rejection is as valuable as the patterns. + +## Key findings + +- Messages render as a `List` of pre-wrapped rows with an explicit 1-column scrollbar. +- The write box height is dynamic, derived from its visual row count (capped by config). +- Right-aligned outgoing message bubbles were implemented and then reverted as ugly; all messages stay left-aligned rows. + +## Pros / strengths + +- Pre-wrapped rows plus an explicit scrollbar are simple and portable — no layout-engine support needed. +- The documented bubble rejection settles a design argument with real-shipped-client evidence instead of taste. + +## Cons / limitations / caveats + +- No markdown, streaming, or tool-call rendering in the inspected evidence; the widget covers plain message rows only. + +## Relevance to tai + +- Decisive for the messaging-layout conclusion: tai renders left-aligned wrapped rows with sender grouping, not bubbles, and grows its input from visual rows — both directly from this source. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/send-rs-config-keymap.md b/research/tui-framework-design/send-rs-config-keymap.md new file mode 100644 index 0000000..f006a78 --- /dev/null +++ b/research/tui-framework-design/send-rs-config-keymap.md @@ -0,0 +1,49 @@ +# send-rs src/config.rs — default keymap and input limits + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | send-rs src/config.rs — configuration defaults (WhatsApp+Telegram ratatui client) | +| Source URL | https://raw.githubusercontent.com/pedromarquetti/send-rs/master/src/config.rs | +| Source publisher / author | pedromarquetti (send-rs / Sender project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Default keybindings and input limits for a ratatui messaging client: Tab/Shift+Tab cycle panes, `i` focuses the write box, Enter selects/sends, with the write box capped at 5 visual lines. A thin source, but the defaults are the finding. + +## Key findings + +- Default pane keys: Tab / Shift+Tab cycle focus, `i` focuses the write box, Enter selects or sends, Shift+Enter inserts a newline, Esc dismisses, Ctrl+C quits. +- Chat navigation uses `j`/`k`/`g`/`G` for scroll and top/bottom; `/` searches, `s` opens settings. +- Write-box height is capped by `max_write_lines = 5`. + +## Pros / strengths + +- Sensible, conventional defaults (vim-ish navigation plus Tab cycling) that need no invention to adopt. +- The 5-line input cap is a concrete number for a growing input box. + +## Cons / limitations / caveats + +- Keymap defaults only; no rationale is given for any choice, and configurability mechanics were not part of the inspected evidence. + +## Relevance to tai + +- Supplies the default keybindings (Tab cycle, `i`/Enter/Esc, Shift+Enter newline) and the 5-line input cap adopted in the messaging-layout conclusion. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/send-rs-tui-draw-main.md b/research/tui-framework-design/send-rs-tui-draw-main.md new file mode 100644 index 0000000..c0bd04f --- /dev/null +++ b/research/tui-framework-design/send-rs-tui-draw-main.md @@ -0,0 +1,49 @@ +# send-rs src/tui/mod.rs — main draw loop and pane split + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | send-rs src/tui/mod.rs — main draw function (WhatsApp+Telegram ratatui client) | +| Source URL | https://raw.githubusercontent.com/pedromarquetti/send-rs/master/src/tui/mod.rs | +| Source publisher / author | pedromarquetti (send-rs / Sender project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +The top-level draw function of a ratatui messaging client: a vertical split giving the main area all but one row (`Fill(1)` + `Length(1)` status row) with the main area itself split 30/70 between chat list and conversation. The focused pane gets a provider-accent border; unfocused panes do not. + +## Key findings + +- `draw_main` splits vertically into `Fill(1)` main content plus a `Length(1)` status row, then splits the main area horizontally 30% / 70%. +- Only the focused pane carries a provider-accent border; inactive panes render without the accent, making focus visible at a glance. + +## Pros / strengths + +- Clean separation of layout (this file) from focus state, status content, and message rendering (sibling modules), so each piece can be studied alone. +- Focus-indicating border accent is a cheap, effective focus signal worth copying. + +## Cons / limitations / caveats + +- This file alone shows only the split skeleton; focus, status text, and message rows live in sibling modules and must be read with it. +- No narrow-terminal breakpoint; the 30/70 split is unconditional. + +## Relevance to tai + +- Confirms the 30/70 + 1-line-status skeleton as the shared convention across inspected ratatui messaging clients, and contributes the focused-pane-accent pattern to the messaging-layout conclusion. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/send-rs-tui-focus-state.md b/research/tui-framework-design/send-rs-tui-focus-state.md new file mode 100644 index 0000000..26eb95e --- /dev/null +++ b/research/tui-framework-design/send-rs-tui-focus-state.md @@ -0,0 +1,48 @@ +# send-rs src/tui/state.rs — focus model and draft retention + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | send-rs src/tui/state.rs — focus state (WhatsApp+Telegram ratatui client) | +| Source URL | https://raw.githubusercontent.com/pedromarquetti/send-rs/master/src/tui/state.rs | +| Source publisher / author | pedromarquetti (send-rs / Sender project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A four-variant focus enum (`ChatList` / `Chat` / `Write` / `Popup`) with a `cycle_focus` routine that saves per-chat `TextArea` drafts when focus moves away. Focus is explicit application state, not derived from widget identity. + +## Key findings + +- Focus is an explicit enum with four variants: `ChatList`, `Chat`, `Write`, `Popup`. +- `cycle_focus` saves the current per-chat `TextArea` draft before moving focus, so partially typed messages survive pane switches and chat switches. + +## Pros / strengths + +- Explicit focus enum makes per-focus status hints, keymaps, and border accents all keyed off one value — simple to port. +- Draft retention on focus move is the correct behavior for a chat input and is handled at the focus layer rather than per widget. + +## Cons / limitations / caveats + +- A fixed four-variant enum is less general than tai's traversal-ordered focus chain; porting the idea means mapping variants onto tai's focusable panels, not copying the enum. + +## Relevance to tai + +- Contributes the explicit-focus-state plus per-chat draft-retention pattern to the messaging-layout conclusion; tai's chat scene needs the same draft behavior on its `TextBox`-based input. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/send-rs-tui-status-bar.md b/research/tui-framework-design/send-rs-tui-status-bar.md new file mode 100644 index 0000000..55ddec7 --- /dev/null +++ b/research/tui-framework-design/send-rs-tui-status-bar.md @@ -0,0 +1,48 @@ +# send-rs src/tui/status_bar.rs — per-focus hints and transient overrides + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | send-rs src/tui/status_bar.rs — status bar content (WhatsApp+Telegram ratatui client) | +| Source URL | https://raw.githubusercontent.com/pedromarquetti/send-rs/master/src/tui/status_bar.rs | +| Source publisher / author | pedromarquetti (send-rs / Sender project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A one-line status bar showing `[chat]` plus key hints for the current focus, with transient status messages (rate-limit countdowns, window blur, backend status, disconnects) temporarily overriding the hints. Content policy and override behavior are the whole finding. + +## Key findings + +- Normal content is `[chat] ` followed by per-focus key hints that change with the focus enum. +- A transient `status_hint` (rate-limit countdown, window-blur notice, backend status, disconnect notice) overrides the hints while present, then the hints return. + +## Pros / strengths + +- The override pattern keeps one status line serving two jobs (teaching keys + reporting state) without layout churn. +- Per-focus hints make modal/focused UIs self-documenting. + +## Cons / limitations / caveats + +- Override timing and queueing (what happens when two transient states overlap) were not part of the inspected evidence. + +## Relevance to tai + +- Contributes the per-focus-hints plus transient-override content policy for tai's 1-line status bar in the messaging-layout conclusion. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/tdesktop-day-blue-theme.md b/research/tui-framework-design/tdesktop-day-blue-theme.md new file mode 100644 index 0000000..73f7cbb --- /dev/null +++ b/research/tui-framework-design/tdesktop-day-blue-theme.md @@ -0,0 +1,57 @@ +# Telegram Desktop day-blue theme file (day-blue.tdesktop-theme) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | day-blue.tdesktop-theme (Telegram Desktop built-in Day theme) | +| Source URL | https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/Resources/day-blue.tdesktop-theme | +| Source publisher / author | Telegram Desktop contributors (tdesktop project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The authoritative built-in light theme for Telegram Desktop: white incoming bubbles against pale-blue outgoing bubbles, grey/blue in-bubble timestamps, translucent service pills, and a fixed 8-hue peer palette for sender names and avatars. Every value below is an exact hex from the file. + +## Key findings + +- Message bubbles: incoming `msgInBg #ffffff`, outgoing `msgOutBg #def1fd`; selected-bubble overlay `#bbe1fc`; bubble shadows `#748ea229` / `#0d5a911a`. +- Message text is near-black (`windowFg`) on both bubble sides. +- In-bubble time color: incoming `#a0acb6`, outgoing `#86a8c2`. +- Service pills (date dividers, service messages): `msgServiceBg #00518059`; date pills render `{month} {day}` or `{month} {day}, {year}`. +- Unread bar: background `#fcfbfa`, foreground `#538bb4`. +- Chat-list unread pill: `#40a7e3`, muted `#bbbbbb`, white text; name `#222`, snippet `#999`. +- Group sender-name peer palette (8 hues): red `#c03d33`, green `#4fad2d`, yellow `#d09306`, blue `#168acd`, purple `#8544d6`, pink `#cd4073`, sea `#2996ad`, orange `#ce671b`; the same hues in different tones drive avatar gradients. +- Top bar background and compose background are white. + +## Pros / strengths + +- Authoritative source: the actual shipped built-in theme, not a teardown or guess. +- Exact hexes for every role, with a matching night file so day/night pairs can be compared key by key. +- The 8-hue peer palette is the canonical answer for sender-name coloring. + +## Cons / limitations / caveats + +- Desktop only: iOS, Android, and Web default hexes were not verified against this file and may differ. +- A key/value theme file carries no geometry: bubble corner radii, paddings, inter-message spacing, and tail shape are not in evidence from this source. +- Key semantics have to be inferred from names; the file alone does not say how each key is rendered. + +## Relevance to tai + +Canonical light-theme defaults for the Telegram look-and-feel decisions: bubble/ink/time hexes, service-pill treatment, unread-pill colors, and the peer-name palette tai's chat scene should mirror (as rows, per the rows-not-bubbles decision). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/tdesktop-lang-strings.md b/research/tui-framework-design/tdesktop-lang-strings.md new file mode 100644 index 0000000..d0f8e65 --- /dev/null +++ b/research/tui-framework-design/tdesktop-lang-strings.md @@ -0,0 +1,54 @@ +# Telegram Desktop language strings (lang.strings) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | lang.strings (Telegram Desktop UI string table) | +| Source URL | https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/Resources/langs/lang.strings | +| Source publisher / author | Telegram Desktop contributors (tdesktop project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The literal UI copy Telegram Desktop ships: the full last-seen scale, the unread-bar phrasing, the composer placeholder and its broadcast variants, attach-menu and bot-keyboard labels, and reply/edit affordance strings. The canonical wording reference for every Telegram-look label tai adopts. + +## Key findings + +- Status line vocabulary: `online`, `typing...`, and the last-seen scale `last seen just now` / `today` / `yesterday at {time}` / `recently` / `within a week` / `within a month` / `a long time ago`. +- Unread bar copy: `{count} Unread Message(s)` and `Unread messages`. +- Composer placeholder: `Write a message...`, with Broadcast, Silent-broadcast, and Schedule variants. +- Attach entry labeled `Add attachment` (photo/video, file, camera, ...); emoji/sticker/gif picker and Send beside the field. +- Bot affordances: a command/keyboard toggle with `Show/Hide bot keyboard`, and a bot menu button labeled `Menu`. +- Reply preview bar carries a `Reply` header with a quoted snippet and a close control; the edit field placeholder is `New message...`; quote-selected-text is supported. + +## Pros / strengths + +- Literal shipped copy: no paraphrase risk, every label verifiable character-for-character. +- Covers the whole header/composer/status surface in one file, so wording stays mutually consistent. + +## Cons / limitations / caveats + +- Strings without layout context: order, truncation, and placement need the client code. +- Desktop wording; mobile clients may phrase some labels differently (not verified). +- Chat-list time/date formatting rules and snippet truncation behavior were not captured (open gap). + +## Relevance to tai + +The copy sheet for tai's Telegram-look surfaces: header status strings, unread bar, composer placeholder, and bot affordance labels should use this wording verbatim rather than tai-invented paraphrases. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/tdesktop-night-theme.md b/research/tui-framework-design/tdesktop-night-theme.md new file mode 100644 index 0000000..1cffb16 --- /dev/null +++ b/research/tui-framework-design/tdesktop-night-theme.md @@ -0,0 +1,56 @@ +# Telegram Desktop night theme file (night.tdesktop-theme) + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | night.tdesktop-theme (Telegram Desktop built-in Night theme) | +| Source URL | https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/Resources/night.tdesktop-theme | +| Source publisher / author | Telegram Desktop contributors (tdesktop project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The authoritative built-in dark theme for Telegram Desktop: dark-slate incoming bubbles against muted-blue outgoing bubbles, light in-bubble timestamps, near-transparent shadows, and brighter re-tones of the same 8-hue peer palette. Pairs key-by-key with the day file. + +## Key findings + +- Message bubbles: incoming `msgInBg #182533`, outgoing `msgOutBg #2b5278`; selected-bubble overlay `#2e70a5`; shadows near-transparent. +- Message text is near-white incoming (`#f5f5f5`-ish) and white outgoing. +- In-bubble time color: incoming `#6d7f8f`, outgoing `#7da8d3`. +- Service pills: `msgServiceBg #213040d5`. +- Chat-list unread pill ("badge"): `#4082bc`, muted `#3e546a`, white text; name `#f5f5f5`, snippet `#7f91a4`, date `#8696a8`. +- Group sender-name peer palette (night re-tones): red `#fb6169`, green `#85de85`, yellow `#f3bc5c`, blue `#65bdf3`, purple `#b48bf2`, pink `#ff5694`, sea `#62d4e3`, orange `#faa357`. +- Top bar background and compose background are `#17212b`. + +## Pros / strengths + +- Authoritative source: the actual shipped built-in dark theme. +- Exact hexes that pair with the day file, so every role has a verified light and dark default. +- Confirms the peer palette survives re-toning across schemes rather than being replaced. + +## Cons / limitations / caveats + +- Desktop only: iOS, Android, and Web dark defaults were not verified against this file. +- No geometry (radii, paddings, spacing, tail shape) is in evidence from this source. +- Key semantics inferred from names; rendering behavior needs the client code. + +## Relevance to tai + +Canonical dark-theme defaults for the Telegram look-and-feel decisions, and the dark half of every day/night role pair tai's theme defaults should carry. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/techmesto-telegram-checkmarks.md b/research/tui-framework-design/techmesto-telegram-checkmarks.md new file mode 100644 index 0000000..8e4066a --- /dev/null +++ b/research/tui-framework-design/techmesto-telegram-checkmarks.md @@ -0,0 +1,50 @@ +# TechMesto — Telegram checkmarks explainer + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Telegram checkmarks explainer (TechMesto) | +| Source URL | https://www.techmesto.com/telegram-checkmarks/ | +| Source publisher / author | TechMesto (third party) | +| Source type | blog post | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A third-party explainer of Telegram's message-state glyphs, consistent with the official FAQ: clock while sending, checks that turn blue on read, and the eye-plus-view-count treatment used by channels instead of checks. + +## Key findings + +- A clock icon marks a message still sending. +- Check marks turn blue once the message is read. +- Channels use an eye icon plus a view count rather than per-recipient checks. + +## Pros / strengths + +- Corroborates the official check semantics from an independent angle. +- The channel eye-plus-views detail fills a gap the FAQ subset did not cover. + +## Cons / limitations / caveats + +- Third-party explainer, not authoritative: useful as corroboration, not as the primary basis for any claim. +- Thin page with no client-version pinning; wording may drift from current clients. + +## Relevance to tai + +Confirms the glyph set tai's transcript rows need (clock, checks with a read color, eye+count for broadcast-style views) without inventing any new states. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telecli-tui-chat-layout.md b/research/tui-framework-design/telecli-tui-chat-layout.md new file mode 100644 index 0000000..6ddf359 --- /dev/null +++ b/research/tui-framework-design/telecli-tui-chat-layout.md @@ -0,0 +1,51 @@ +# telecli src/tui.rs — chat layout and modal keys + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | telecli src/tui.rs — ratatui/crossterm Telegram client TUI | +| Source URL | https://raw.githubusercontent.com/s3r1msultan/telecli/main/src/tui.rs | +| Source publisher / author | s3r1msultan (telecli project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A single-file ratatui Telegram client UI: a fixed 30/70 horizontal split with a chat list plus 3-row help bar on the left and messages plus a 3-row input on the right, a 1-line status overlay at the bottom, and modal Normal/Input key handling. There is no resize handling. + +## Key findings + +- Layout is a fixed horizontal `Percentage(30)` / `Percentage(70)` split; left pane holds a chat `List` plus a 3-row help bar, right pane holds messages (`Min(0)`) plus a `Length(3)` input. +- Status is drawn as a 1-line bottom overlay rect showing `status | Mode`. +- Modal keys: `j`/`k`/Up/Down navigate chats, `i`/Enter enters input mode, Esc cancels, Enter sends, `s`/`w` or PgUp/PgDn scroll by 10 lines, `r` refreshes, `?` shows hints, `q` then `y`/`n` quits. +- Messages render as rows of the form `-> text [HH:MM]`; outgoing messages are green. + +## Pros / strengths + +- Minimal complete precedent for a Telegram-like layout in a single file: split ratios, pane contents, and status overlay are all directly copyable numbers. +- Modal Normal/Input separation keeps chat navigation keys from colliding with typing. + +## Cons / limitations / caveats + +- No resize or narrow-terminal handling at all; the 30/70 split is unconditional. +- Single-file scope means no theming, no focus-cycle across panes, no streaming or markdown handling to learn from. + +## Relevance to tai + +- Supplies the base layout numbers for tai's chat scene (30/70 split, 3-row input, 1-line status overlay) and the modal Normal/Input key pattern adopted in the messaging-layout conclusion. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/telegram-android-chat-message-cell.md b/research/tui-framework-design/telegram-android-chat-message-cell.md new file mode 100644 index 0000000..24b7b1a --- /dev/null +++ b/research/tui-framework-design/telegram-android-chat-message-cell.md @@ -0,0 +1,53 @@ +# Telegram Android ChatMessageCell — bubble grouping, tails, in-bubble metadata + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | ChatMessageCell.java (Telegram Android message cell) | +| Source URL | https://raw.githubusercontent.com/DrKLO/Telegram/master/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java | +| Source publisher / author | Telegram (DrKLO/Telegram, official Android client) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The actual Android implementation of message grouping and in-bubble metadata: consecutive same-sender messages join via position flags with squared inner corners, the tail appears only on the last message of a group, and the timestamp sits at the bubble's bottom-right with the sender's checks immediately after. + +## Key findings + +- Joined message groups use `POSITION_FLAG` top/bottom/left/right combinations; inner (joined) corners are squared. +- The bubble tail renders only on the last message of a consecutive same-sender group. +- Timestamp is bottom-right inside the bubble (`timeX = backgroundWidth - dp(4) - timeWidth`); on own messages the checks render immediately after the time. +- Group sender names are header-colored from the 8-hue peer palette. +- Incoming bubbles sit left, outgoing right; the in/out key split holds across clients. + +## Pros / strengths + +- Ground-truth grouping and tail logic straight from the shipped renderer. +- Exact time-placement formula leaves no ambiguity about metadata position. + +## Cons / limitations / caveats + +- Android only; tail side, corner radii, paddings, and inter-message spacing per client were not captured (open gap). +- Media-bubble time-overlay details were not captured (open gap). +- The class is large; only the grouping/tail/metadata subset was synthesized. + +## Relevance to tai + +Defines the grouping grammar tai keeps even without bubbles (join consecutive same-sender rows, metadata at the row's trailing end, peer-hue sender names) and the bubble geometry tai deliberately does not need. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-android-dialog-cell.md b/research/tui-framework-design/telegram-android-dialog-cell.md new file mode 100644 index 0000000..e0ffdd3 --- /dev/null +++ b/research/tui-framework-design/telegram-android-dialog-cell.md @@ -0,0 +1,53 @@ +# Telegram Android DialogCell — chat-list row rendering + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | DialogCell.java (Telegram Android chat-list row cell) | +| Source URL | https://raw.githubusercontent.com/DrKLO/Telegram/master/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java | +| Source publisher / author | Telegram (DrKLO/Telegram, official Android client) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The actual Android implementation of a chat-list row: circular avatar, bold name with time at right, second-line snippet with sender/service prefixes and own-message checks or clock, unread pill with pin/mute overlays, red `Draft:` prefix, and typing status rendered in action blue over the snippet. + +## Key findings + +- Circular avatar with radius 26dp; bold chat name on the left, time on the right. +- Second line is a snippet with group-sender or service-message prefixes; own latest message is preceded by its checks or clock icon. +- Unread count renders as a pill at the right; the pin icon replaces or overlaps the count area; a mute (bell-off) icon sits after the name. +- Typing or voice-recording status replaces the snippet in action blue (`key_chats_actionMessage`). +- Unsent draft text is prefixed with `Draft:` in red (`key_chats_draft`). + +## Pros / strengths + +- Real shipped implementation, not a design mock: every element's presence and relative placement is ground truth for Android. +- Theme-key references (`key_chats_actionMessage`, `key_chats_draft`) tie each element to the theming system. + +## Cons / limitations / caveats + +- Android only; Desktop and iOS row geometry was not verified against this class. +- Chat-list time/date formatting rules and snippet truncation logic were not captured from this source (open gap). +- One class of a large client: surrounding list behavior (grouping, archives, folders) was not mined. + +## Relevance to tai + +The element inventory for tai's sidebar rows: avatar slot, name plus time, snippet with status prefixes, unread pill, pin/mute markers, draft-red and typing-blue overrides — the rich-row target tai's plain-name list must grow into. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-blog-chat-themes-read-receipts.md b/research/tui-framework-design/telegram-blog-chat-themes-read-receipts.md new file mode 100644 index 0000000..9c6c8b3 --- /dev/null +++ b/research/tui-framework-design/telegram-blog-chat-themes-read-receipts.md @@ -0,0 +1,50 @@ +# Telegram blog — chat themes, interactive emoji, read receipts + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Chat Themes, Interactive Emoji, Read Receipts and Live Recording (Telegram blog) | +| Source URL | https://telegram.org/blog/chat-themes-interactive-emoji-read-receipts | +| Source publisher / author | Telegram | +| Source type | blog post | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The official announcement covering group read receipts (double check once one other member reads, tap-for-readers, 7-day retention) and per-chat gradient bubble themes with day and night variants and animated backgrounds, set from the chat header and applied to both sides. + +## Key findings + +- In groups, a message shows double checks once at least one other member has read it; tapping the message in small groups shows the reader list; receipts are stored for 7 days. +- Per-chat themes (8 or more) offer gradient message bubbles, each with a day and a night variant plus an animated background and pattern. +- The theme is set via Chat Header > .../... > Change Colors on Android/iOS and applies to both sides of the conversation. + +## Pros / strengths + +- Official source for group receipt behavior, which the FAQ does not spell out. +- The only official statement found on per-chat theming scope (both sides, day+night variants, animated backgrounds). + +## Cons / limitations / caveats + +- Announcement framing: feature-positive, with no hex values, no geometry, and no API detail. +- Feature counts (8+ themes) are version-dated and have likely grown since publication. + +## Relevance to tai + +Supplies the group-read-receipt rule tai's status vocabulary should follow, and draws the line on what tai will not copy: gradient/animated per-chat bubble themes have no terminal equivalent and are explicitly out of scope. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-bot-api.md b/research/tui-framework-design/telegram-bot-api.md new file mode 100644 index 0000000..291ad90 --- /dev/null +++ b/research/tui-framework-design/telegram-bot-api.md @@ -0,0 +1,52 @@ +# Telegram Bot API — reply keyboards, inline keyboards, menu button, commands + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Telegram Bot API (bot keyboards, menu button, and commands sections) | +| Source URL | https://core.telegram.org/bots/api | +| Source publisher / author | Telegram | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The official protocol reference for bot input surfaces: custom reply keyboards that replace the system keyboard, inline keyboards pinned under a message that send nothing by themselves, the menu button opening the command list, and up to 100 scoped commands with slash autocomplete. + +## Key findings + +- Custom reply keyboards replace the system keyboard with rows of buttons; options include resize, one-time, persistent, and selective display, plus an `input_field_placeholder` of 1-64 characters. +- Inline keyboards sit under a message and send nothing on their own; buttons carry callback data, URLs, switch-inline queries, game, payment, styled, copy-text, or disabled actions, and are editable in place. +- The menu button near the input opens the command list; it has `commands` (default) and `web_app` variants. +- Commands are capped at 100, render highlighted, complete on `/`, and are set per scope and language via `setMyCommands`. +- Bots can also be invoked from the attachment menu and inline via `@username` queries. + +## Pros / strengths + +- The authoritative protocol contract: exact option names, limits (100 commands, 64-char placeholder), and button taxonomies. +- Cleanly separates the three surfaces (reply keyboard, inline keyboard, menu), which map to distinct UI widgets. + +## Cons / limitations / caveats + +- Protocol docs, not rendering guidance: how clients lay out keyboards (grid sizing, overflow, scrolling) is unspecified here. +- Only the keyboard/command/menu subset was synthesized; the page is far larger than what this subject needed. + +## Relevance to tai + +The grammar tai's bot affordances must mirror: a reply-keyboard surface distinct from inline message buttons, a `Menu`-labeled command entry point, `/` autocomplete over a capped command list, and a 64-char input placeholder contract. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-bot-features.md b/research/tui-framework-design/telegram-bot-features.md new file mode 100644 index 0000000..dc41730 --- /dev/null +++ b/research/tui-framework-design/telegram-bot-features.md @@ -0,0 +1,50 @@ +# Telegram bot features overview — Start flow and global commands + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Telegram bot features overview | +| Source URL | https://core.telegram.org/bots/features | +| Source publisher / author | Telegram | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The official feature-level statement of the bot onboarding contract: a Start button on first open, deep-link parameters carried by `/start`, and three global commands (`/start`, `/help`, `/settings`) every bot is expected to honor. + +## Key findings + +- The first open of a bot conversation shows a Start button rather than a bare input. +- `/start` carries deep-link parameters via `t.me/bot?start=` links of up to 64 characters. +- `/start`, `/help`, and `/settings` are global commands with settled meanings across all bots. + +## Pros / strengths + +- Official and concise: the whole onboarding contract in three facts. +- The 64-char deep-link limit is an exact implementable constraint. + +## Cons / limitations / caveats + +- Feature-overview level: no rendering, layout, or client-behavior detail. +- Thin for look-and-feel purposes beyond the Start-button affordance itself. + +## Relevance to tai + +Supplies the bot-conversation opening tai should mirror (a start affordance before free input) and the three global commands tai's own bot/command surface should reserve with their standard meanings. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-faq.md b/research/tui-framework-design/telegram-faq.md new file mode 100644 index 0000000..e2e9039 --- /dev/null +++ b/research/tui-framework-design/telegram-faq.md @@ -0,0 +1,51 @@ +# Telegram FAQ — check semantics and online presence + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Telegram FAQ | +| Source URL | https://telegram.org/faq | +| Source publisher / author | Telegram | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The official statement of Telegram's delivery-check semantics: one check means the message reached Telegram's cloud (and the recipient was notified if allowed), two checks mean it was read — there is deliberately no delivered-to-device state because of multi-device sync. Also the source for the online-presence grace rule. + +## Key findings + +- One check mark: the message was sent to the Telegram cloud and the recipient was notified if notifications are allowed. +- Two check marks: the message was read by the recipient (checks then render blue on the sender's side). +- There is no delivered-to-device state: with multi-device sync, cloud receipt is the only meaningful intermediate state. +- A user shows as online for roughly 30 seconds after sending, reading, or typing activity, regardless of privacy settings. + +## Pros / strengths + +- Official and unambiguous on the exact question it answers; kills any "sent vs delivered" guessing. +- The multi-device rationale explains why the state machine is clock/one-check/two-checks and nothing else. + +## Cons / limitations / caveats + +- FAQ-level brevity: states the semantics but gives no client rendering detail (glyphs, colors, placement). +- Only the check/presence subset of the page was synthesized; the rest of the FAQ was not mined for this subject. + +## Relevance to tai + +Settles the per-message status vocabulary tai's transcript rows should implement: sending clock, single check, blue double check, and no delivered state to ever design for. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/telegram-webapps-docs.md b/research/tui-framework-design/telegram-webapps-docs.md new file mode 100644 index 0000000..6e3f12b --- /dev/null +++ b/research/tui-framework-design/telegram-webapps-docs.md @@ -0,0 +1,52 @@ +# Telegram Web Apps (Mini Apps) documentation — ThemeParams, events, design rules + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Telegram Web Apps (Mini Apps) documentation | +| Source URL | https://core.telegram.org/bots/webapps | +| Source publisher / author | Telegram | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | High | +| Status | Active | + +## Summary + +The official Mini Apps reference: the 15-key `ThemeParams` contract theming every Mini App, the `light`/`dark` color scheme with its change event, the native button inventory (Back, Main/Secondary, Settings), and Telegram's own design rules for apps living inside its chrome. + +## Key findings + +- `ThemeParams` carries 15 optional keys: `bg_color`, `text_color`, `hint_color`, `link_color`, `button_color`, `button_text_color`, `secondary_bg_color`, `header_bg_color`, `bottom_bar_bg_color`, `accent_text_color`, `section_bg_color`, `section_header_text_color`, `section_separator_color`, `subtitle_text_color`, `destructive_text_color`. +- `colorScheme` is `light` or `dark` (mirrored in the `--tg-color-scheme` CSS variable); a `themeChanged` event fires on theme or night-mode switches and clients must re-read theme parameters then. +- Official design rules: mobile-first, mimic native components, sustain 60fps, use dynamic theme colors (never hardcode), and respect both the safe area and the content safe area. +- Native chrome inventory: the BackButton lives in the Mini App header, Main and Secondary buttons sit at the bottom, and Settings is a context-menu item. + +## Pros / strengths + +- The authoritative theming contract: exact key names, scheme values, and event semantics in one place. +- The design rules read as Telegram's own look-and-feel policy, directly reusable as tai theming principles. + +## Cons / limitations / caveats + +- The `WebViewColors` diagram is image-only with no alt data and its contents were not inspected (open gap). +- No official typography or spacing specification exists anywhere in Telegram's docs (open gap). +- Exact default light-theme hexes for the `section_*`, `subtitle`, and `destructive` keys are not published officially; only dark samples were observed elsewhere (open gap). + +## Relevance to tai + +The role vocabulary tai's theming should map onto: 15 Telegram keys against tai's 12 roles, the light/dark scheme contract behind theme switching, and the never-hardcode/re-read-on-change discipline behind `set_theme` plus repaint. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created. | diff --git a/research/tui-framework-design/textual-constants-theme-env.md b/research/tui-framework-design/textual-constants-theme-env.md new file mode 100644 index 0000000..af70c3a --- /dev/null +++ b/research/tui-framework-design/textual-constants-theme-env.md @@ -0,0 +1,46 @@ +# Textual constants.py — TEXTUAL_THEME environment default + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Textual src/textual/constants.py — TEXTUAL_THEME env handling | +| Source URL | https://raw.githubusercontent.com/Textualize/textual/main/src/textual/constants.py | +| Source publisher / author | Textualize (Textual project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A thin source with one finding: the `TEXTUAL_THEME` environment variable sets the default theme, taking a first-existing-wins list. It exists here as the precedent for tai's `TAI_THEME` variable. + +## Key findings + +- `TEXTUAL_THEME` sets the default theme from the environment, accepting a list where the first existing theme wins. + +## Pros / strengths + +- Env-var default with first-existing-wins fallback is a small, robust precedence mechanism worth copying exactly. + +## Cons / limitations / caveats + +- Thin source: one mechanism only, no interaction with flags or runtime switching visible here. + +## Relevance to tai + +- Direct precedent for the palette-role conclusion's precedence chain (flag > `TAI_THEME` env var > default). + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/textual-design-guide.md b/research/tui-framework-design/textual-design-guide.md new file mode 100644 index 0000000..bde50cf --- /dev/null +++ b/research/tui-framework-design/textual-design-guide.md @@ -0,0 +1,48 @@ +# Textual design guide — live theming and command palette + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Textual design guide — themes and variable system | +| Source URL | https://textual.textualize.io/guide/design/ | +| Source publisher / author | Textualize (Textual project) | +| Source type | vendor docs | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Textual's official design documentation: theme bases generate `$`-variables and shade ramps, assigning `self.theme` applies a theme live, and the Ctrl+P command palette offers theme switching. Documents the runtime-switch behavior tai wants in miniature. + +## Key findings + +- Theme base colors generate `$`-variables plus shade ramps consumed throughout the widget system. +- Setting `self.theme` applies a theme live at runtime; the Ctrl+P command palette exposes theme switching to the user. + +## Pros / strengths + +- Official docs confirming the live-switch contract: swapping the theme pointer plus a redraw is the whole mechanism. +- Shows user-facing switching (palette UI) as a first-class feature, not an afterthought. + +## Cons / limitations / caveats + +- The variable/shade generation pipeline is Textual-scale machinery; tai adopts the switch contract, not the generator. + +## Relevance to tai + +- Backs the palette-role conclusion's switch design (`set_theme` swaps the pointer and triggers a full redraw) and the single-cycle-key user switcher as tai's miniature of the command palette entry. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/textual-theme-module.md b/research/tui-framework-design/textual-theme-module.md new file mode 100644 index 0000000..a32cf9f --- /dev/null +++ b/research/tui-framework-design/textual-theme-module.md @@ -0,0 +1,50 @@ +# Textual theme.py — Theme model and builtin registry + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | Textual src/textual/theme.py — Theme class and BUILTIN_THEMES | +| Source URL | https://raw.githubusercontent.com/Textualize/textual/main/src/textual/theme.py | +| Source publisher / author | Textualize (Textual project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Textual's theme model: a `Theme` built from 11 base colors of which only `primary` is required, with the bases generating the full variable/shade/text system, plus a `BUILTIN_THEMES` dict holding 21 named presets. The richest theme model surveyed, and the explicit template for tai's role names and kebab-case registry. + +## Key findings + +- A `Theme` is defined by 11 base colors; only `primary` is required, the rest fall back to defaults. +- The base colors generate the full design system: `$`-variables, shade ramps, and text variants. +- `BUILTIN_THEMES` is a dict registry holding 21 named preset themes. + +## Pros / strengths + +- One-required-color authoring makes custom themes cheap while the generated system keeps them complete. +- A plain-dict named registry with kebab-case names is the simplest registry shape that scales to 21 presets. + +## Cons / limitations / caveats + +- The generated shade/text machinery is far heavier than tai needs; copying the model whole would violate tai's scope discipline. +- App-level `get_css_variables` override behavior was seen in snippet only, not fetched — not claimed here. + +## Relevance to tai + +- Template for the palette-role conclusion: tai copies the role names and the kebab-case dict registry, but not the generated-shade machinery. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/za-tui-app-styles.md b/research/tui-framework-design/za-tui-app-styles.md new file mode 100644 index 0000000..1a02585 --- /dev/null +++ b/research/tui-framework-design/za-tui-app-styles.md @@ -0,0 +1,49 @@ +# za-tui app.tcss — sidebar/chat/input proportions + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | za-tui app.tcss — application stylesheet (Textual Zalo client) | +| Source URL | https://raw.githubusercontent.com/buihongduc132/za-tui/main/src/za_tui/app.tcss | +| Source publisher / author | buihongduc132 (za-tui project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +The stylesheet behind a Textual messaging client: a 30% sidebar beside a 70% chat area, the chat area stacking a `1fr` transcript over an auto-height input clamped to 3–8 rows, with a 1-row status bar. A thin source whose numbers corroborate the ratatui clients. + +## Key findings + +- Sidebar takes 30% width, chat area 70%. +- Chat area is a vertical stack: `ChatView` at `1fr` over an `InputBar` with automatic height clamped to 3–8 rows. +- The status bar has a fixed height of 1 row. + +## Pros / strengths + +- Independent corroboration (Textual/CSS rather than ratatui) of the same 30/70 + growing-input + 1-line-status geometry. +- The 3–8 row input clamp gives a concrete growth range. + +## Cons / limitations / caveats + +- Stylesheet only: no behavior, keymap, or rendering logic visible here; the companion `.py` widgets carry those. + +## Relevance to tai + +- Cross-framework confirmation of the layout numbers adopted in the messaging-layout conclusion; the 3–8 clamp informs tai's input growth range. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/za-tui-chat-view.md b/research/tui-framework-design/za-tui-chat-view.md new file mode 100644 index 0000000..a28f97a --- /dev/null +++ b/research/tui-framework-design/za-tui-chat-view.md @@ -0,0 +1,49 @@ +# za-tui widgets/chat_view.py — transcript rows, grouping, scroll behavior + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | za-tui widgets/chat_view.py — chat view widget (Textual Zalo client) | +| Source URL | https://raw.githubusercontent.com/buihongduc132/za-tui/main/src/za_tui/widgets/chat_view.py | +| Source publisher / author | buihongduc132 (za-tui project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Transcript rendering as plain rows with sender grouping on a 90-minute gap, per-message `[sending]`/`[failed]` status suffixes, a selection arrow, a `New messages (n)` indicator, scroll-to-bottom only when already at the bottom, and older-message loading at scroll-top. The fullest transcript-behavior precedent inspected. + +## Key findings + +- Messages render as plain rows with sender grouping: consecutive messages from one sender group until a 90-minute gap. +- Each message can carry a `[sending]` or `[failed]` status suffix; a selection arrow marks the selected row; a `New messages (n)` indicator counts unseen messages. +- New arrivals auto-scroll to the bottom only when the view is already at the bottom; scrolling to the top loads older messages. + +## Pros / strengths + +- Pin-to-bottom-only-if-at-bottom is the correct scroll contract for a live transcript and is stated as behavior, not inferred. +- Sender grouping plus per-message status plus unread indicator covers the whole transcript feature set in one widget. + +## Cons / limitations / caveats + +- Plain rows only: no markdown, streaming-token, or tool-call rendering in the inspected evidence, so those tai needs remain inferred patterns. + +## Relevance to tai + +- Supplies the transcript contract (grouped rows, per-message status, conditional pin-to-bottom, history loading) adopted in the messaging-layout conclusion; its scroll contract is also the inferred carrier for tai's streaming rendering. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/za-tui-input-bar.md b/research/tui-framework-design/za-tui-input-bar.md new file mode 100644 index 0000000..85d82ce --- /dev/null +++ b/research/tui-framework-design/za-tui-input-bar.md @@ -0,0 +1,49 @@ +# za-tui widgets/input_bar.py — multiline input behavior + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | za-tui widgets/input_bar.py — input bar widget (Textual Zalo client) | +| Source URL | https://raw.githubusercontent.com/buihongduc132/za-tui/main/src/za_tui/widgets/input_bar.py | +| Source publisher / author | buihongduc132 (za-tui project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A multiline `TextArea`-based input bar: Enter sends, Shift+Enter inserts a newline, with a 2000-character cap, a 100-entry send history on up/down, a 3-second typing-notification throttle, and a reply-quote slot. The fullest input-behavior precedent of the three messaging clients. + +## Key findings + +- Enter sends the message; Shift+Enter inserts a newline. +- Messages are capped at 2000 characters; up/down recall from a 100-entry history. +- Typing notifications are throttled to one per 3 seconds; the bar holds a reply-quote slot for quoted replies. + +## Pros / strengths + +- Complete input contract in one place: send/newline split, cap, history, typing signal, reply quoting — all directly adoptable numbers. +- The 2000-char cap and 100-entry history are concrete defaults tai would otherwise have to invent. + +## Cons / limitations / caveats + +- Typing throttle and reply-quote slot assume a chat-server backend; tai's agent-turn context may need different semantics for both. + +## Relevance to tai + +- Supplies the input contract (Enter send, Shift+Enter newline, 2000-char cap, send history) adopted in the messaging-layout conclusion. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/za-tui-main-screen.md b/research/tui-framework-design/za-tui-main-screen.md new file mode 100644 index 0000000..afc2cb9 --- /dev/null +++ b/research/tui-framework-design/za-tui-main-screen.md @@ -0,0 +1,49 @@ +# za-tui screens/main.py — screen composition and manual sidebar toggle + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | za-tui screens/main.py — main screen (Textual Zalo client) | +| Source URL | https://raw.githubusercontent.com/buihongduc132/za-tui/main/src/za_tui/screens/main.py | +| Source publisher / author | buihongduc132 (za-tui project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +Main-screen composition (Header, StatusBar, sidebar/chat Horizontal, Footer) with F2 sidebar toggle and F6 focus cycling — and a code comment stating that `on_resize` auto-hide of the sidebar was intentionally omitted because it breaks tests, keeping the manual toggle instead. The deliberate omission is the key finding. + +## Key findings + +- `MainScreen` composes a Header, StatusBar, a Horizontal split of Sidebar and chat area, and a Footer. +- `F2` toggles the sidebar; `Ctrl+B` is a manual toggle alternative; `F6` cycles focus Sidebar → ChatView → InputBar. +- A code comment records that automatic sidebar hiding on resize was intentionally omitted (it breaks tests); manual toggle is the shipped behavior. + +## Pros / strengths + +- Honest in-code rationale for shipping manual toggle over auto-hide gives tai a precedent for sequencing: manual first, automatic later. +- F6 single-key focus cycling is a simple alternative to Tab cycling. + +## Cons / limitations / caveats + +- No automatic narrow-terminal behavior to copy — this source is evidence for what to defer, not a breakpoint implementation. + +## Relevance to tai + +- Directly shapes the messaging-layout conclusion's sequencing: ship a manual sidebar toggle first (F2/Ctrl+B style), add the sub-80-column auto-hide as an enhancement, per this source's stated reasoning. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/research/tui-framework-design/za-tui-status-bar.md b/research/tui-framework-design/za-tui-status-bar.md new file mode 100644 index 0000000..990480b --- /dev/null +++ b/research/tui-framework-design/za-tui-status-bar.md @@ -0,0 +1,47 @@ +# za-tui widgets/status_bar.py — identity-style status content + +## Metadata + +| Field | Value | +|---|---| +| Institute | Molodetz Institute — Research & Retrieval Division | +| Subject | tui-framework-design | +| Document type | Source Dossier | +| Tier | 1 | +| Source title | za-tui widgets/status_bar.py — status bar widget (Textual Zalo client) | +| Source URL | https://raw.githubusercontent.com/buihongduc132/za-tui/main/src/za_tui/widgets/status_bar.py | +| Source publisher / author | buihongduc132 (za-tui project) | +| Source type | repository | +| Source date (published) | Unknown — not stated | +| Date researched | 2026-10-11 | +| Researched by | tai (agent), model: Muse Spark, on behalf of retoor | +| Research method | direct page fetch | +| Confidence | Medium | +| Status | Active | + +## Summary + +A status bar showing identity rather than hints: a connection-status dot, the current user, and the active conversation. A thin source that complements send-rs's hint-style status bar. + +## Key findings + +- Status content is a connection indicator (emoji dot), the current user identity, and the active conversation name. + +## Pros / strengths + +- Identity content (who am I, am I connected, which chat is this) answers the questions a hint bar cannot. +- Pairs naturally with send-rs's hint bar: identity on one side, hints on the other. + +## Cons / limitations / caveats + +- Thin source: one content pattern only, no transient-state or override behavior in the inspected evidence. + +## Relevance to tai + +- Supplies the identity half of tai's status-bar content policy (connection + user + chat) in the messaging-layout conclusion, alongside send-rs's hints. + +## Changelog + +| Date | Change | +|---|---| +| 2026-10-11 | Initial dossier created from 2026-10-11 research-pass evidence (body opened via web_fetch by researching agent). | diff --git a/tai.py b/tai.py index 131f78c..90dc6c0 100755 --- a/tai.py +++ b/tai.py @@ -4,6 +4,7 @@ import argparse import base64 import codecs import collections +import contextlib import difflib import getpass import glob @@ -11,6 +12,7 @@ import hashlib import importlib.util import hmac import html +import io import json import os import queue @@ -26,6 +28,7 @@ import struct import subprocess import sys import tempfile +import textwrap import threading import time import urllib.error @@ -303,6 +306,21 @@ def dir_key(directory=None): return "" +def orientation_block(directory=None, sandbox=False): + """Working-directory orientation for the system prompt. Without it the + model improvises its location: CLI backends run in a /tmp scratch dir + their harness reports as cwd, and an unoriented model hedges with + broad cross-project searches instead of working in the real cwd.""" + if sandbox: + return ("\n\n## Working directory\nSandboxed container: shell and file tools execute " + "inside the container, not on the host. Stay inside the mounted workdir " + "unless the user names another path.") + return ("\n\n## Working directory\n%s\nYour shell and file tools execute here. Stay inside " + "it unless the user names another path. If your harness reports a different " + "working directory (a scratch or temp dir), ignore it: it is not the workspace." + % dir_key(directory)) + + def split_leading_tags(text): tags = [] rest = text or "" @@ -3423,15 +3441,16 @@ def muse_prompt(messages, tools): if tools: parts.append("TOOLS:\n%s" % json.dumps(tools)) parts.append("Answer with content text plus tool_calls for every tool to invoke now. Empty tool_calls ends the turn.") + parts.append("Reply with data only: never invoke assistant or harness tools yourself. The TOOLS block above is response vocabulary, not executable tools.") return "\n\n".join(part for part in parts if part.strip()) def muse_argv(config, schema_path, prompt_path, session_id=None): - argv = [muse_binary(), "exec", "--json", "--max-model-steps", str(MUSE_MAX_STEPS), "--disable-web-tools", "--disable-reminders", "--allow-workspace-switch", "--output-schema", schema_path, "--prompt-file", prompt_path] + argv = [muse_binary(), "exec", "--json", "--max-model-steps", str(MUSE_MAX_STEPS), "--disable-web-tools", "--disable-reminders", "--disable-shell", "--disable-write", "--output-schema", schema_path, "--prompt-file", prompt_path] if session_id is None: argv.append("--no-session-log") else: - argv.extend(["--session-id", session_id]) + argv.extend(["--allow-workspace-switch", "--session-id", session_id]) if config.explicit_model: argv.extend(["--model", config.explicit_model]) return argv @@ -7202,6 +7221,7 @@ class Agent: def apply_system(self): content = self.system_message + skill_catalog(self.skills) + tool_catalog() + content += orientation_block(sandbox=self.env == "sandbox") if self.auto: content += "\n\n" + AUTONOMOUS_NOTE self.messages[0] = {"role": "system", "content": content} @@ -7212,6 +7232,7 @@ class Agent: def reset_history(self): self.messages = [{"role": "system", "content": self.system_message}] self.apply_system() + self.apply_system() def switch_profile(self, name, silent=False): if self.messages and self.persist: @@ -8954,6 +8975,107 @@ TUI_LAYERS = {"base": 0, "panel": 10, "dialog": 20, "toast": 30} TUI_COLORS = {"black": 0, "red": 1, "green": 2, "yellow": 3, "blue": 4, "magenta": 5, "cyan": 6, "white": 7} +TUI_THEME_ROLES = ("bg", "surface", "fg", "muted", "border", "accent", "on_accent", "selection", "success", "warning", "error", "info", + "bubble_in", "bubble_out", "bubble_fg", "meta_in", "meta_out", "tick_read", + "service_bg", "service_fg", "unread", "unread_muted") + +TUI_THEME_DEFAULT = "dark" + + +class TuiTheme: + """Named palette: 12 role colors plus a dark flag. Role values use + the same color language as TuiStyle (names, #rrggbb, ints).""" + + def __init__(self, name, dark, roles): + self.name = name + self.dark = bool(dark) + self.roles = dict(roles) + + def color(self, role): + return self.roles.get(role) + + +TUI_THEMES = {} + + +def tui_register_theme(theme): + missing = [role for role in TUI_THEME_ROLES if not theme.color(role)] + if missing: + raise ValueError("theme '%s' lacks roles: %s" % (theme.name, ", ".join(missing))) + TUI_THEMES[theme.name] = theme + return theme + + +def _tui_builtin_themes(): + tui_register_theme(TuiTheme("dark", True, { + "bg": "#101418", "surface": "#1b222c", "fg": "#e6edf3", "muted": "#8b949e", + "border": "#30363d", "accent": "#2f81f7", "on_accent": "#ffffff", "selection": "#1f3a5f", + "success": "#3fb950", "warning": "#d29922", "error": "#f85149", "info": "#39c5cf", + "bubble_in": "#182533", "bubble_out": "#2b5278", "bubble_fg": "#f5f5f5", + "meta_in": "#6d7f8f", "meta_out": "#7da8d3", "tick_read": "#4082bc", + "service_bg": "#213040", "service_fg": "#ffffff", "unread": "#4082bc", "unread_muted": "#3e546a"})) + tui_register_theme(TuiTheme("light", False, { + "bg": "#ffffff", "surface": "#f6f8fa", "fg": "#1f2328", "muted": "#59636e", + "border": "#d1d9e0", "accent": "#0969da", "on_accent": "#ffffff", "selection": "#b6d8ff", + "success": "#1a7f37", "warning": "#9a6700", "error": "#cf222e", "info": "#1b7c83", + "bubble_in": "#ffffff", "bubble_out": "#def1fd", "bubble_fg": "#222222", + "meta_in": "#a0acb6", "meta_out": "#86a8c2", "tick_read": "#40a7e3", + "service_bg": "#a6c2d3", "service_fg": "#ffffff", "unread": "#40a7e3", "unread_muted": "#bbbbbb"})) + tui_register_theme(TuiTheme("nord", True, { + "bg": "#2e3440", "surface": "#3b4252", "fg": "#eceff4", "muted": "#7c8698", + "border": "#4c566a", "accent": "#88c0d0", "on_accent": "#2e3440", "selection": "#434c5e", + "success": "#a3be8c", "warning": "#ebcb8b", "error": "#bf616a", "info": "#81a1c1", + "bubble_in": "#3b4252", "bubble_out": "#4c6a8a", "bubble_fg": "#eceff4", + "meta_in": "#7c8698", "meta_out": "#88c0d0", "tick_read": "#88c0d0", + "service_bg": "#4c566a", "service_fg": "#eceff4", "unread": "#88c0d0", "unread_muted": "#4c566a"})) + tui_register_theme(TuiTheme("gruvbox", True, { + "bg": "#282828", "surface": "#3c3836", "fg": "#ebdbb2", "muted": "#928374", + "border": "#504945", "accent": "#83a598", "on_accent": "#282828", "selection": "#458588", + "success": "#b8bb26", "warning": "#fabd2f", "error": "#fb4934", "info": "#8ec07c", + "bubble_in": "#3c3836", "bubble_out": "#458588", "bubble_fg": "#ebdbb2", + "meta_in": "#928374", "meta_out": "#83a598", "tick_read": "#83a598", + "service_bg": "#504945", "service_fg": "#ebdbb2", "unread": "#458588", "unread_muted": "#665c54"})) + tui_register_theme(TuiTheme("ansi", True, { + "bg": "black", "surface": "black", "fg": "white", "muted": "bright_black", + "border": "white", "accent": "cyan", "on_accent": "black", "selection": "blue", + "success": "green", "warning": "yellow", "error": "red", "info": "cyan", + "bubble_in": "black", "bubble_out": "blue", "bubble_fg": "white", + "meta_in": "white", "meta_out": "cyan", "tick_read": "bright_blue", + "service_bg": "black", "service_fg": "white", "unread": "blue", "unread_muted": "white"})) + + +_tui_builtin_themes() + +TUI_THEME = TUI_THEMES[TUI_THEME_DEFAULT] + + +def tui_theme(): + return TUI_THEME + + +def tui_set_theme(name): + global TUI_THEME + if name not in TUI_THEMES: + raise ValueError("unknown theme '%s' (available: %s)" % (name, ", ".join(sorted(TUI_THEMES)))) + TUI_THEME = TUI_THEMES[name] + return TUI_THEME + + +def tui_resolve_theme_name(flag): + """Precedence: --theme flag, TAI_THEME env, default. Raises ValueError + naming the available themes when the pick is unknown.""" + name = flag or os.environ.get("TAI_THEME") or TUI_THEME_DEFAULT + if name not in TUI_THEMES: + raise ValueError("unknown theme '%s' (available: %s)" % (name, ", ".join(sorted(TUI_THEMES)))) + return name + + +def tui_cycle_theme_name(current): + names = list(TUI_THEMES) + if current in names: + return names[(names.index(current) + 1) % len(names)] + return TUI_THEME_DEFAULT + class TuiStyle: """Foreground/background/attribute bundle. Colors are names ("red", @@ -9022,6 +9144,9 @@ class TuiStyle: return "%d;2;%d;%d;%d" % ((48 if background else 38,) + tuple(max(0, min(255, int(part))) for part in color)) if isinstance(color, str): text = color.strip().lower() + if text.startswith("role:"): + resolved = tui_theme().color(text[len("role:"):]) + return TuiStyle.color_sgr(resolved, background) if resolved else "" if text.startswith("#") and len(text) == 7: try: rgb = tuple(int(text[pos:pos + 2], 16) for pos in (1, 3, 5)) @@ -10145,6 +10270,8 @@ def tui_parse_one(buf, final): char, length, need_more = tui_utf8_head(buf[1:]) if need_more: return ("need_more", buf) + if char == "\r": + return (TuiKey(key="alt+enter", char="\n", modifiers=["alt"]), buf[1 + length:]) return (TuiKey(key="alt+" + char, char=char), buf[1 + length:]) @@ -10934,6 +11061,69 @@ class TuiOptions(TuiPanel): COMPLETE_WORD_RE = re.compile(r"(?:^|\s)([/@])([A-Za-z0-9_./-]*)$") +class TuiChatList(TuiOptions): + """Two-line chat rows: name / snippet. Options carry (label, value) + as usual; row_meta maps value -> {"snippet": str, "draft": str}. + Selection moves per chat while each chat paints two terminal rows.""" + + def __init__(self, options=(), **kwargs): + super().__init__(options, **kwargs) + self.row_meta = {} + + def measure(self): + width, _height = super().measure() + return (width, max(1, 2 * len(self.options))) + + def _follow_selection(self, height): + top = self.selected * 2 + if top < self.scroll_y: + self.scroll_y = top + elif top + 1 >= self.scroll_y + max(1, height): + self.scroll_y = top + 2 - max(1, height) + + def content_rows(self): + width = self._content_w() + height = self._content_h() + self._follow_selection(height) + focused = self.app is not None and self.app.focused is self + rows = [] + for pos in range(height): + index = self.scroll_y + pos + chat, sub = divmod(index, 2) + if 0 <= chat < len(self.options): + label, value = self.options[chat] + meta = self.row_meta.get(value) or {} + if chat == self.selected and self.enabled: + style = self.style.merged(TuiStyle(reverse=True, bold=focused)) + else: + style = self.style + if sub == 0: + rows.append([TuiSpan((" " + label)[:width].ljust(width), style)]) + else: + snippet = str(meta.get("snippet") or "") + draft = str(meta.get("draft") or "") + if draft: + head = TuiSpan(" Draft: ", style.merged(TuiStyle(fg="role:error"))) + tail = TuiSpan(draft[:max(0, width - 9)], style) + rows.append(tui_pad_spans([head, tail], width, style)) + else: + rows.append([TuiSpan((" " + snippet)[:width].ljust(width), style)]) + else: + rows.append([TuiSpan(" " * width, self.style)]) + return rows + + def on_click(self, event): + if not self.enabled or not event.pressed: + return + event.stop() + self.focus() + pad_top = self.padding[0] + (1 if self.border else 0) + index = self.scroll_y + (event.y - self.ay - pad_top) + chat = index // 2 + if 0 <= chat < len(self.options): + self.choose(chat) + + class TuiAutocomplete(TuiOptions): """Non-focusable completion popup owned by a TuiTextBox. The box keeps focus and drives the list: typing filters, arrows move, Enter accepts @@ -11016,7 +11206,7 @@ class TuiTextBox(TuiPanel): prefix-to-items callable for /words and mentions= the same for @words, both driving a TuiAutocomplete popup.""" - def __init__(self, text="", complete=None, mentions=None, **kwargs): + def __init__(self, text="", complete=None, mentions=None, send_on_enter=False, on_send=None, max_chars=0, placeholder="", **kwargs): kwargs.setdefault("focusable", True) kwargs.setdefault("border", True) super().__init__(**kwargs) @@ -11027,6 +11217,10 @@ class TuiTextBox(TuiPanel): self.complete_fn = complete self.mention_fn = mentions self.complete_popup = None + self.send_on_enter = send_on_enter + self.on_send = on_send + self.max_chars = max(0, int(max_chars or 0)) + self.placeholder = placeholder or "" @property def value(self): @@ -11060,23 +11254,34 @@ class TuiTextBox(TuiPanel): self.top = self.cy - height + 1 left = max(0, self.cx - width + 1) focused = self.app is not None and self.app.focused is self and self.enabled + hint = self.placeholder if (self.placeholder and not self.value.strip()) else "" + hint_style = self.style.merged(TuiStyle(fg="role:muted", dim=True)) if hint else self.style rows = [] for pos in range(height): index = self.top + pos line = self.lines[index][left:left + width] if 0 <= index < len(self.lines) else "" + style = self.style + if hint and index == 0: + line, style = hint, hint_style line = line.ljust(width) if focused and index == self.cy: col = self.cx - left before, at, after = line[:col], line[col:col + 1], line[col + 1:] - rows.append([TuiSpan(before, self.style), - TuiSpan(at or " ", self.style.merged(TuiStyle(reverse=True))), - TuiSpan(after, self.style)]) + rows.append([TuiSpan(before, style), + TuiSpan(at or " ", style.merged(TuiStyle(reverse=True))), + TuiSpan(after, style)]) else: - rows.append([TuiSpan(line[:width], self.style)]) + rows.append([TuiSpan(line[:width], style)]) return rows def insert(self, text): - parts = str(text).split("\n") + text = str(text) + if self.max_chars: + room = self.max_chars - len(self.value) + if room <= 0: + return + text = text[:room] + parts = text.split("\n") line = self.lines[self.cy] head, tail = line[:self.cx], line[self.cx:] self.lines[self.cy] = head + parts[0] @@ -11254,6 +11459,15 @@ class TuiTextBox(TuiPanel): step = max(1, self._content_h()) self.cy += -step if key == "pageup" else step elif key == "enter": + event.stop() + if self.send_on_enter and callable(self.on_send): + self._complete_hide() + self.on_send(self.value) + return + self.insert("\n") + self._complete_refresh() + return + elif key in ("shift+enter", "alt+enter"): event.stop() self.insert("\n") self._complete_refresh() @@ -11417,7 +11631,9 @@ class TuiProgress(TuiPanel): class TuiLog(TuiPanel): """Virtualized scrollback view. Wheel scrolls; appending follows the - tail only while already pinned there.""" + tail only while already pinned there. Lines are (text, spans) pairs: + append() takes plain text plus one style, append_spans() takes + pre-built multi-style runs (chat bubbles).""" def __init__(self, **kwargs): kwargs.setdefault("scrollable", True) @@ -11426,18 +11642,26 @@ class TuiLog(TuiPanel): def measure(self): width = 0 - for text, _style in self.lines[-500:]: + for text, _spans in self.lines[-500:]: width = max(width, len(text)) return (width, max(1, len(self.lines))) - def append(self, text, style=None): + def _push(self, text, spans): pinned = self.scroll_y >= max(0, len(self.lines) - self._content_h()) - self.lines.append((str(text), style or self.style)) + self.lines.append((text, spans)) if pinned: self.scroll_y = max(0, len(self.lines) - self._content_h()) if self.app is not None: self.app.dirty_paint() + def append(self, text, style=None): + text = str(text) + self._push(text, [TuiSpan(text, style or self.style)]) + + def append_spans(self, spans): + spans = list(spans) or [TuiSpan("", self.style)] + self._push("".join(span.text for span in spans), spans) + def content_rows(self): width = self._content_w() height = self._content_h() @@ -11445,8 +11669,8 @@ class TuiLog(TuiPanel): for pos in range(height): index = self.scroll_y + pos if 0 <= index < len(self.lines): - text, style = self.lines[index] - rows.append([TuiSpan(text[:width].ljust(width), style)]) + _text, spans = self.lines[index] + rows.append(tui_pad_spans(tui_slice_spans(spans, self.scroll_x, width, self.style), width, self.style)) else: rows.append([TuiSpan(" " * width, self.style)]) return rows @@ -11752,6 +11976,13 @@ class TuiApp: def dirty_paint(self): self._need_paint = True + def set_theme(self, name): + """Switch the global theme and redraw everything. Raises + ValueError naming the available themes when unknown.""" + tui_set_theme(name) + self.dirty_paint() + return tui_theme() + def after(self, delay, callback): return self._schedule(float(delay), None, callback) @@ -12354,6 +12585,439 @@ def tui_demo_shot(rows=30, cols=100): return 0 +TUI_CHAT_SIDEBAR_MIN = 24 +TUI_CHAT_SIDEBAR_MAX = 36 +TUI_CHAT_NARROW_COLS = 80 +TUI_CHAT_INPUT_CAP = 2000 +TUI_CHAT_HISTORY = 40 +TUI_CHAT_LINE_CAP = 500 + +TUI_ANSI_RE = re.compile(r"\x1b\[[0-9;]*m") + + +def tui_strip_ansi(text): + return TUI_ANSI_RE.sub("", text or "") + + +def tui_chat_sidebar_w(cols): + return max(TUI_CHAT_SIDEBAR_MIN, min(TUI_CHAT_SIDEBAR_MAX, int(cols * 0.3))) + + +TUI_CHAT_BUBBLE_MAX = 0.7 +TUI_CHAT_TICK_SEND = "◷" +TUI_CHAT_TICK_SENT = "✓" +TUI_CHAT_TICK_READ = "✓✓" + + +def tui_chat_bubble_rows(text, width, side, styles, stamp="", ticks="", ticks_read=False): + """One aligned bg-fill bubble as span-rows. side out (right) or in + (left); stamp+ticks tuck bottom-right inside the bubble. styles needs + base, bubble, meta, tick entries. Below usable width bubbles degrade + to full-width left rows. Returns a list of span lists.""" + width = max(10, int(width)) + base = styles["base"] + if width < 34: + rows = [] + for para in str(text or "").split("\n"): + rows.extend(TuiText(para, wrap=True).lines(width) or [""]) + meta = " ".join(part for part in (stamp, ticks) if part).strip() + if meta: + rows.append(meta.rjust(width)) + return [[TuiSpan(line[:width].ljust(width), base)] for line in rows] + meta = " ".join(part for part in (stamp, ticks) if part).strip() + cap = max(12, int(width * TUI_CHAT_BUBBLE_MAX)) + wrapped = [] + for para in str(text or "").split("\n"): + parts = textwrap.wrap(para, cap - 2, expand_tabs=True, replace_whitespace=False, + drop_whitespace=False, break_long_words=True, break_on_hyphens=False) + wrapped.extend(part.rstrip() for part in parts or [""]) + want = max([len(line) for line in wrapped] + [0]) + 2 + if meta and wrapped: + want = max(want, len(wrapped[-1]) + 1 + len(meta) + 2, len(meta) + 2) + bubble_w = min(cap, want) + bubble = styles["bubble"] + time_span = TuiSpan((stamp + " ") if stamp and ticks else stamp, styles["meta"]) if stamp else None + tick_span = TuiSpan(ticks, styles["tick"] if ticks_read else styles["meta"]) if ticks else None + meta_spans = [span for span in (time_span, tick_span) if span is not None] + rows = [] + body = list(wrapped) + if meta and body and len(body[-1]) + 1 + len(meta) <= bubble_w - 2: + tail = body.pop() + for line in body: + rows.append([TuiSpan(" " + line.ljust(bubble_w - 2) + " ", bubble)]) + gap = bubble_w - 2 - len(tail) - len(meta) + rows.append([TuiSpan(" ", bubble), TuiSpan(tail, bubble), TuiSpan(" " * gap, bubble)] + meta_spans + [TuiSpan(" ", bubble)]) + else: + for line in body: + rows.append([TuiSpan(" " + line.ljust(bubble_w - 2) + " ", bubble)]) + if meta: + gap = bubble_w - 2 - len(meta) + rows.append([TuiSpan(" ", bubble), TuiSpan(" " * gap, bubble)] + meta_spans + [TuiSpan(" ", bubble)]) + if not rows: + rows.append([TuiSpan(" " * bubble_w, bubble)]) + aligned = [] + for spans in rows: + cells = bubble_w + if side == "out": + aligned.append([TuiSpan(" " * max(0, width - cells), base)] + spans) + else: + aligned.append(spans + [TuiSpan(" " * max(0, width - cells), base)]) + return aligned + + +def tui_chat_pill_row(text, width, base_style, pill_style): + label = (" %s " % (text or "").strip())[:max(0, width)] + left = max(0, (width - len(label)) // 2) + right = max(0, width - left - len(label)) + return [TuiSpan(" " * left, base_style), TuiSpan(label, pill_style), TuiSpan(" " * right, base_style)] + + +def tui_build_chat(app, agent): + """Telegram-style chat scene: bots sidebar, transcript, input, status. + Turns run inline via a deferred timer (see run_pending): the worker + thread the research sketch assumed would share one sqlite connection + across threads, which sqlite forbids, so the echo paints first and + the turn blocks the loop like the telegram bot already does.""" + refs = {"drafts": {}, "pending": None, "note": "", "sidebar_auto": False, + "sidebar_hide": False, "last_side": None, "bots": [], "pending_tick": None, + "blocks": [], "render_w": 0} + panel_style = TuiStyle(bg="role:bg", fg="role:fg") + dim_style = TuiStyle(bg="role:bg", fg="role:muted") + err_style = TuiStyle(bg="role:bg", fg="role:error") + bar_style = TuiStyle(bg="role:surface", fg="role:fg") + name_style = TuiStyle(bg="role:bg", fg="role:fg", bold=True) + in_style = TuiStyle(bg="role:bubble_in", fg="role:bubble_fg") + out_style = TuiStyle(bg="role:bubble_out", fg="role:bubble_fg") + dim_in_style = TuiStyle(bg="role:bubble_in", fg="role:muted") + err_in_style = TuiStyle(bg="role:bubble_in", fg="role:error") + meta_in_style = TuiStyle(bg="role:bubble_in", fg="role:meta_in") + meta_out_style = TuiStyle(bg="role:bubble_out", fg="role:meta_out") + tick_style = TuiStyle(bg="role:bubble_out", fg="role:tick_read") + pill_style = TuiStyle(bg="role:service_bg", fg="role:service_fg") + in_styles = {"base": panel_style, "bubble": in_style, "meta": meta_in_style, "tick": meta_in_style} + out_styles = {"base": panel_style, "bubble": out_style, "meta": meta_out_style, "tick": tick_style} + dim_styles = {"base": panel_style, "bubble": dim_in_style, "meta": meta_in_style, "tick": meta_in_style} + err_styles = {"base": panel_style, "bubble": err_in_style, "meta": meta_in_style, "tick": meta_in_style} + + root = TuiPanel(flow="rows", style=TuiStyle(bg="role:bg"), id="chat") + body = TuiCols(h="1fr", style=TuiStyle(bg="role:bg"), id="body") + sidebar_wrap = TuiPanel(w=tui_chat_sidebar_w(app.cols), h="100%", border=True, title="Bots", + style=panel_style, id="sidebar") + sidebar = TuiChatList([], h="1fr", style=panel_style, id="bots") + sidebar_wrap.add(sidebar) + right = TuiRows(w="1fr", h="100%", style=TuiStyle(bg="role:bg"), id="right") + header = TuiRows(h=3, style=TuiStyle(bg="role:bg"), id="header") + head_name = TuiText("", h=1, wrap=False, style=name_style, id="head_name") + head_status = TuiText("", h=1, wrap=False, style=dim_style, id="head_status") + head_hair = TuiText("", h=1, wrap=False, style=dim_style, id="head_hair") + header.add(head_name, head_status, head_hair) + transcript = TuiLog(border=True, focusable=True, h="1fr", style=panel_style, id="transcript") + composer = TuiCols(h=3, style=TuiStyle(bg="role:bg"), id="composer") + box = TuiTextBox(w="1fr", h="100%", border=True, style=panel_style, id="input", + complete=tui_complete_command, + mentions=lambda prefix: tui_complete_mention(prefix, bots=tuple(refs["bots"])), + send_on_enter=True, on_send=lambda value: do_send(value), + max_chars=TUI_CHAT_INPUT_CAP, placeholder="Write a message...") + send_btn = TuiButton("Send", w=10, h="100%", style=TuiStyle(bg="role:accent", fg="role:on_accent", bold=True), + on_press=lambda event: do_send(box.value), id="send") + composer.add(box, send_btn) + right.add(header, transcript, composer) + body.add(sidebar_wrap, right) + status = TuiText("", h=1, wrap=False, style=bar_style, id="status") + root.add(body, status) + refs.update({"root": root, "sidebar_wrap": sidebar_wrap, "sidebar": sidebar, + "transcript": transcript, "box": box, "status": status, "composer": composer, + "head_name": head_name, "head_status": head_status, "head_hair": head_hair}) + + def render_block(block): + width = max(10, transcript._content_w()) + if block[0] == "pill": + transcript.append_spans(tui_chat_pill_row(block[1], width, panel_style, pill_style)) + return + _kind, side, text, styles, stamp, ticks, ticks_read = block + if transcript.lines and refs["last_side"] not in (None, side): + transcript.append("") + for spans in tui_chat_bubble_rows(text, width, side, styles, stamp, ticks, ticks_read): + transcript.append_spans(spans) + refs["last_side"] = side + + def replay(): + if not transcript.aw: + return + pinned = transcript.scroll_y >= max(0, len(transcript.lines) - transcript._content_h()) + transcript.lines = [] + refs["last_side"] = None + for block in refs["blocks"]: + render_block(block) + while len(transcript.lines) > TUI_CHAT_LINE_CAP and len(refs["blocks"]) > 1: + refs["blocks"].pop(0) + transcript.lines = [] + refs["last_side"] = None + for block in refs["blocks"]: + render_block(block) + if pinned: + transcript.scroll_y = max(0, len(transcript.lines) - transcript._content_h()) + else: + transcript._clamp_scroll() + refs["render_w"] = transcript._content_w() + app.dirty_paint() + + def maybe_replay(): + if transcript.aw and transcript._content_w() != refs["render_w"]: + replay() + + def bubble(side, text, styles, stamp="", ticks="", ticks_read=False): + """Journal one aligned bubble and render it when laid out. Same-side + neighbors join with no gap; a side switch gets one blank line. + Returns the journal block (stable across replays).""" + block = ["bubble", side, text, styles, stamp, ticks, ticks_read] + refs["blocks"].append(block) + if transcript.aw: + render_block(block) + if len(transcript.lines) > TUI_CHAT_LINE_CAP and len(refs["blocks"]) > 1: + refs["blocks"].pop(0) + replay() + return block + + def pill(text): + block = ["pill", text] + refs["blocks"].append(block) + if transcript.aw: + render_block(block) + return block + + def show(sender, text, style): + side = "out" if sender == "you" else "in" + styles = dim_styles if style in (dim_style, err_style) else (out_styles if side == "out" else in_styles) + if style is err_style: + styles = err_styles + return bubble(side, text, styles) + + def render_history(): + refs["blocks"] = [] + refs["pending_tick"] = None + transcript.lines = [] + refs["last_side"] = None + past = [msg for msg in agent.messages if msg.get("role") != "system"][-TUI_CHAT_HISTORY:] + if not past: + now = datetime.now() + pill("%s %d" % (now.strftime("%B"), now.day)) + for msg in past: + if msg.get("role") == "user": + bubble("out", tui_strip_ansi(msg.get("content") or ""), out_styles) + elif msg.get("role") == "assistant": + if msg.get("content"): + bubble("in", tui_strip_ansi(msg["content"]), in_styles) + for call in msg.get("tool_calls") or []: + fn = (call.get("function") or {}) + bubble("in", "- %s %s" % (fn.get("name"), (fn.get("arguments") or "")[:100]), dim_styles) + + def paint_status(): + width = max(20, app.cols) + left = refs["note"] or "F2 sidebar - F4 theme - Tab switch - i input - /help" + pins = " ".join(part for part in (agent.chat.provider_pin, agent.chat.model_pin) if part) + right = "%s/%s - %s" % (agent.profile, agent.bot, pins or "auto") + busy = running_agents() + if busy: + right += " +%d" % busy + if len(left) + 1 + len(right) > width: + status.text = left[:width] + else: + status.text = left + right.rjust(width - len(left)) + head_name.text = "[%s] %s" % (agent.bot[:1].upper(), agent.bot) + head_status.text = "typing..." if refs["pending"] is not None else "online" + head_hair.text = "─" * max(1, head_hair._content_w() or 20) + app.dirty_paint() + + def clear_box(): + box.lines = [""] + box.cx = box.cy = box.top = 0 + box._complete_hide() + app.dirty_paint() + + def bot_snippet(name): + try: + msgs = agent.messages if name == agent.bot else agent.store.load_session(agent.profile, name) + except Exception: + return "" + for msg in reversed(msgs or []): + content = (msg.get("content") or "").strip() + if content: + return content.split("\n")[0][:40] + return "" + + def refresh_bots(): + names = [item["name"] for item in agent.store.list_bots(agent.profile)] + if agent.bot not in names: + names = [agent.bot] + names + refs["bots"] = names + sidebar.options = [TuiOptions.norm_option(name) for name in names] + sidebar.selected = names.index(agent.bot) + sidebar.row_meta = {name: {"snippet": bot_snippet(name), + "draft": refs["drafts"].get(name, "").split("\n")[0][:40]} + for name in names} + app.dirty_paint() + + def select_bot(name): + if name == agent.bot: + return + refs["drafts"][agent.bot] = box.value + agent.switch_bot(name, silent=True) + draft = refs["drafts"].get(agent.bot, "") + box.lines = draft.split("\n") or [""] + box.cx = len(box.lines[-1]) + box.cy = len(box.lines) - 1 + box.top = 0 + refresh_bots() + render_history() + paint_status() + + def run_command(text): + buf = io.StringIO() + try: + with contextlib.redirect_stdout(buf): + stay = handle_command(agent, text) + except Exception as exc: + bubble("in", "error: %s" % short_error(exc), err_styles) + return + out = tui_strip_ansi(buf.getvalue()).strip() + if out: + bubble("in", "\n".join(out.split("\n")[:100]), dim_styles) + if not stay: + app.quit() + return + refresh_bots() + paint_status() + + def settle_pending_tick(): + block = refs["pending_tick"] + refs["pending_tick"] = None + if block is None or not any(entry is block for entry in refs["blocks"]): + return + block[5] = TUI_CHAT_TICK_READ + block[6] = True + replay() + + def do_send(value): + text = (value or "").strip() + if not text or refs["pending"] is not None: + return + clear_box() + refs["drafts"][agent.bot] = "" + if text.startswith("/"): + run_command(text) + return + stamp = datetime.now().strftime("%H:%M") + refs["pending_tick"] = bubble("out", text, out_styles, stamp, TUI_CHAT_TICK_SEND) + refs["pending"] = text + refs["note"] = "thinking..." + refresh_bots() + paint_status() + app.after(0.05, run_pending) + + def run_pending(): + text = refs["pending"] + refs["pending"] = None + if not text: + return + old_stdin = sys.stdin + sys.stdin = io.StringIO("") + buried = io.StringIO() + try: + with contextlib.redirect_stdout(buried): + answer = agent.run_turn(text, capture=True) + except KeyboardInterrupt: + agent.checkpoint() + answer = "[interrupted]" + except BackendError as exc: + answer = "error: %s" % short_error(exc) + finally: + sys.stdin = old_stdin + settle_pending_tick() + stamp = datetime.now().strftime("%H:%M") + bubble("in", tui_strip_ansi(answer or "[no reply]"), in_styles, stamp) + refs["note"] = "" + refresh_bots() + paint_status() + + def toggle_sidebar(): + sidebar_wrap.visible = not sidebar_wrap.visible + refs["sidebar_hide"] = not sidebar_wrap.visible + refs["sidebar_auto"] = False + if sidebar_wrap.visible: + sidebar_wrap.w = tui_chat_sidebar_w(app.cols) + app.dirty_layout() + app.ensure_focus() + + def on_resize(event): + sidebar_wrap.w = tui_chat_sidebar_w(app.cols) + if app.cols < TUI_CHAT_NARROW_COLS and sidebar_wrap.visible and not refs["sidebar_hide"]: + sidebar_wrap.visible = False + refs["sidebar_auto"] = True + elif app.cols >= TUI_CHAT_NARROW_COLS and refs["sidebar_auto"] and not refs["sidebar_hide"]: + sidebar_wrap.visible = True + refs["sidebar_auto"] = False + app.dirty_layout() + app.ensure_focus() + app.after(0.05, maybe_replay) + + def on_root_key(event): + key = event.key or "" + if key == "f2": + event.stop() + toggle_sidebar() + elif key == "f4": + event.stop() + nxt = tui_cycle_theme_name(tui_theme().name) + app.set_theme(nxt) + refs["note"] = "theme: %s" % nxt + paint_status() + elif key == "q": + event.stop() + app.quit() + elif key in ("i", "escape"): + event.stop() + box.focus() + + def tick_input(): + want = max(3, min(7, len(box.lines) + 2)) + if composer.h != want: + composer.h = want + app.dirty_layout() + + sidebar.on_select = lambda event: select_bot(event.value) + root.on_key = on_root_key + root.on_resize = on_resize + app.every(0.2, tick_input) + app.every(1.0, paint_status) + refresh_bots() + render_history() + paint_status() + refs.update({"do_send": do_send, "run_pending": run_pending, "toggle_sidebar": toggle_sidebar, + "paint_status": paint_status, "show": show, "replay": replay, + "render_history": render_history}) + return root, refs + + +def tui_chat(agent, theme_name): + tui_set_theme(theme_name) + agent.quiet = True + app = TuiApp() + scheduler_stop = start_scheduler(agent.config, agent.store.seal) + try: + root, refs = tui_build_chat(app, agent) + app.mount(root) + refs["replay"]() + refs["box"].focus() + return app.run() + except TuiError as exc: + print("tui unavailable: %s" % exc, file=sys.stderr) + return 2 + finally: + scheduler_stop.set() + agent.store.save_session(agent.profile, agent.messages, agent.bot) + + def build_parser(): parser = argparse.ArgumentParser(prog="tai", description="single-file autonomous agent, standard library only") parser.add_argument("--profile", default=None) @@ -12371,6 +13035,8 @@ def build_parser(): parser.add_argument("--plexer-wrap", action="store_true", help="internal: invoked by the bashrc plexer hook, not meant to be run by hand") parser.add_argument("--demo", action="store_true", help="run the fullscreen TUI framework showcase") parser.add_argument("--demo-shot", action="store_true", help="print one composed demo frame as text and exit") + parser.add_argument("--tui", action="store_true", help="run the fullscreen Telegram-style chat UI") + parser.add_argument("--theme", default=None, metavar="NAME", help="TUI theme: dark, light, nord, gruvbox, ansi (or TAI_THEME)") parser.add_argument("prompt", nargs="*") return parser @@ -12462,6 +13128,11 @@ def main(argv=None): return tui_demo() if args.demo_shot: return tui_demo_shot() + try: + theme_name = tui_resolve_theme_name(args.theme) + except ValueError as exc: + print(exc, file=sys.stderr) + return 2 if args.plexer_wrap: home = os.environ.get("TAI_HOME") or os.path.join(os.path.expanduser("~"), ".tai") profile = args.profile or "default" @@ -12518,6 +13189,11 @@ def main(argv=None): except Exception: pass return 0 + if args.tui: + try: + return tui_chat(agent, theme_name) + finally: + agent.store.close() if args.resume and not args.telegram and not args.scheduler: resume_turn(agent) banner(agent) diff --git a/test_tai.py b/test_tai.py index cdf8c6e..e22f102 100644 --- a/test_tai.py +++ b/test_tai.py @@ -1,4 +1,5 @@ # retoor +import contextlib import io import json import os @@ -2318,6 +2319,60 @@ class MentionTests(unittest.TestCase): self.assertIn(".hidden", tai.complete_files(".", os.getcwd())) +class OrientationTests(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + os.environ["TAI_HOME"] = self.tmp.name + self.workdir = tempfile.TemporaryDirectory() + self.saved_cwd = os.getcwd() + os.chdir(self.workdir.name) + + class FakeArgs: + profile = "t" + yes = True + + self.config = tai.Config(FakeArgs()) + self.store = tai.Store(self.config, tai.Seal(self.config.home, "orient-test-1")) + self.agent = tai.Agent(self.config, self.store, persist=True, quiet=True) + + def tearDown(self): + os.chdir(self.saved_cwd) + self.store.close() + self.workdir.cleanup() + self.tmp.cleanup() + os.environ.pop("TAI_HOME", None) + + def test_block_states_cwd_and_scope(self): + block = tai.orientation_block() + self.assertIn(os.path.realpath(os.getcwd()), block) + self.assertIn("Stay inside it unless the user names another path", block) + self.assertIn("scratch or temp dir", block) + + def test_block_sandbox_variant(self): + block = tai.orientation_block(sandbox=True) + self.assertIn("Sandboxed container", block) + self.assertNotIn(os.path.realpath(os.getcwd()), block) + + def test_apply_system_injects_block(self): + system = self.agent.messages[0]["content"] + self.assertIn("## Working directory", system) + self.assertIn(os.path.realpath(os.getcwd()), system) + + def test_reset_history_keeps_block(self): + self.agent.messages.append({"role": "user", "content": "hi"}) + self.agent.reset_history() + self.assertEqual(len(self.agent.messages), 1) + self.assertIn("## Working directory", self.agent.messages[0]["content"]) + + def test_muse_prompt_carries_block(self): + prompt = tai.muse_prompt(self.agent.messages, []) + self.assertIn(os.path.realpath(os.getcwd()), prompt) + + def test_muse_prompt_forbids_harness_tools(self): + prompt = tai.muse_prompt([{"role": "user", "content": "hi"}], []) + self.assertIn("never invoke assistant or harness tools yourself", prompt) + + class FTSSearchTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() @@ -3913,6 +3968,29 @@ class CliJsonRepairTests(unittest.TestCase): self.assertIn("Never narrate a planned action", rules) +class MuseArgvTests(unittest.TestCase): + def argv(self, session_id=None): + class FakeConfig: + explicit_model = "" + + return tai.muse_argv(FakeConfig(), "s.json", "p.txt", session_id) + + def test_ephemeral_omits_workspace_switch(self): + argv = self.argv(None) + self.assertIn("--no-session-log", argv) + self.assertNotIn("--allow-workspace-switch", argv) + self.assertNotIn("--session-id", argv) + self.assertIn("--disable-shell", argv) + self.assertIn("--disable-write", argv) + + def test_session_keeps_workspace_switch(self): + argv = self.argv("sess-1") + self.assertIn("--allow-workspace-switch", argv) + self.assertIn("--session-id", argv) + self.assertIn("sess-1", argv) + self.assertNotIn("--no-session-log", argv) + + class RetrySummaryTests(unittest.TestCase): def test_empty_errors(self): self.assertEqual(tai.ChatClient.summarize_errors([]), "no details") @@ -5032,6 +5110,382 @@ class TuiCommandTests(unittest.TestCase): self.assertTrue(args.demo_shot) +class TuiThemeTests(unittest.TestCase): + def tearDown(self): + tai.tui_set_theme("dark") + + def test_builtin_registry_complete(self): + self.assertEqual(set(tai.TUI_THEMES), {"dark", "light", "nord", "gruvbox", "ansi"}) + for name, theme in tai.TUI_THEMES.items(): + for role in tai.TUI_THEME_ROLES: + self.assertTrue(theme.color(role), "%s lacks %s" % (name, role)) + self.assertFalse(tai.TUI_THEMES["light"].dark) + self.assertTrue(tai.TUI_THEMES["dark"].dark) + + def test_role_resolves_at_draw(self): + tai.tui_set_theme("dark") + self.assertEqual(tai.TuiStyle(fg="role:accent").sgr(), "\x1b[0;38;2;47;129;247m") + self.assertEqual(tai.TuiStyle(bg="role:bg").sgr(), "\x1b[0;48;2;16;20;24m") + tai.tui_set_theme("light") + self.assertEqual(tai.TuiStyle(fg="role:accent").sgr(), "\x1b[0;38;2;9;105;218m") + + def test_unknown_role_is_empty(self): + self.assertEqual(tai.TuiStyle(fg="role:nope").sgr(), "\x1b[0m") + + def test_raw_colors_pass_through(self): + self.assertEqual(tai.TuiStyle(fg="#ff0000").sgr(), "\x1b[0;38;2;255;0;0m") + self.assertEqual(tai.TuiStyle(fg="cyan").sgr(), "\x1b[0;36m") + + def test_register_validates_roles(self): + with self.assertRaises(ValueError): + tai.tui_register_theme(tai.TuiTheme("broken", True, {"bg": "black"})) + roles = {role: "white" for role in tai.TUI_THEME_ROLES} + tai.tui_register_theme(tai.TuiTheme("custom-1", True, roles)) + try: + tai.tui_set_theme("custom-1") + self.assertEqual(tai.TuiStyle(fg="role:fg").sgr(), "\x1b[0;37m") + finally: + del tai.TUI_THEMES["custom-1"] + + def test_resolve_precedence(self): + self.assertEqual(tai.tui_resolve_theme_name("nord"), "nord") + old = os.environ.get("TAI_THEME") + os.environ["TAI_THEME"] = "gruvbox" + try: + self.assertEqual(tai.tui_resolve_theme_name(None), "gruvbox") + self.assertEqual(tai.tui_resolve_theme_name("light"), "light") + finally: + if old is None: + os.environ.pop("TAI_THEME", None) + else: + os.environ["TAI_THEME"] = old + self.assertEqual(tai.tui_resolve_theme_name(None), "dark") + with self.assertRaises(ValueError) as raised: + tai.tui_resolve_theme_name("nope") + self.assertIn("dark", str(raised.exception)) + + def test_set_theme_redraws(self): + app = tai.TuiApp() + app._need_paint = False + app.set_theme("nord") + self.assertEqual(tai.tui_theme().name, "nord") + self.assertTrue(app._need_paint) + with self.assertRaises(ValueError): + app.set_theme("nope") + + def test_cycle_order(self): + self.assertEqual(tai.tui_cycle_theme_name("dark"), "light") + self.assertEqual(tai.tui_cycle_theme_name("ansi"), "dark") + self.assertEqual(tai.tui_cycle_theme_name("nope"), "dark") + + +class FakeChatChat: + provider_pin = None + model_pin = None + + +class FakeChatStore: + def list_bots(self, profile): + return [{"name": "main", "nicknames": []}, {"name": "coder", "nicknames": []}] + + def load_session(self, profile, bot): + return [] + + +class FakeChatAgent: + profile = "t" + bot = "main" + + def __init__(self): + self.chat = FakeChatChat() + self.store = FakeChatStore() + self.messages = [{"role": "system", "content": "sys"}, + {"role": "user", "content": "hello"}, + {"role": "assistant", "content": "hi there", "tool_calls": []}] + self.turns = [] + + def switch_bot(self, name, silent=False): + self.bot = name + return "switched to bot '%s'" % name + + def run_turn(self, text, capture=False): + self.turns.append(text) + return "echo: %s" % text + + def checkpoint(self): + pass + + +class TuiChatTests(unittest.TestCase): + def tearDown(self): + tai.tui_set_theme("dark") + + def make_chat(self, cols=100, rows=24): + app = tai.TuiApp() + app.rows = rows + app.cols = cols + agent = FakeChatAgent() + root, refs = tai.tui_build_chat(app, agent) + app.mount(root) + refs["replay"]() + return app, agent, root, refs + + def key(self, app, key, char=""): + app.dispatch(tai.TuiKey(key=key, char=char)) + + def type(self, app, text): + for char in text: + self.key(app, char, char) + + def test_sidebar_width_clamps(self): + self.assertEqual(tai.tui_chat_sidebar_w(100), 30) + self.assertEqual(tai.tui_chat_sidebar_w(200), 36) + self.assertEqual(tai.tui_chat_sidebar_w(60), 24) + self.assertEqual(tai.tui_chat_sidebar_w(80), 24) + + def test_layout_and_render(self): + app, _agent, _root, refs = self.make_chat() + self.assertEqual(refs["sidebar_wrap"].w, 30) + self.assertEqual(refs["bots"], ["main", "coder"]) + self.assertIn("t/main", refs["status"].text) + text = app.render_text() + self.assertIn("Bots", text) + self.assertIn("coder", text) + self.assertIn("hello", text) + self.assertIn("Write a message...", text) + self.assertIn("[M] main", text) + self.assertIn("online", text) + + def test_narrow_hides_and_restores_sidebar(self): + app, _agent, root, refs = self.make_chat(cols=100) + self.assertTrue(refs["sidebar_wrap"].visible) + app.cols = 70 + app.dispatch(tai.TuiResize(panel=root, rows=24, cols=70)) + self.assertFalse(refs["sidebar_wrap"].visible) + app.cols = 100 + app.dispatch(tai.TuiResize(panel=root, rows=24, cols=100)) + self.assertTrue(refs["sidebar_wrap"].visible) + + def test_f2_manual_toggle_overrides_auto(self): + app, _agent, root, refs = self.make_chat(cols=100) + refs["box"].focus() + self.key(app, "f2") + self.assertFalse(refs["sidebar_wrap"].visible) + app.dispatch(tai.TuiResize(panel=root, rows=24, cols=100)) + self.assertFalse(refs["sidebar_wrap"].visible) + self.key(app, "f2") + self.assertTrue(refs["sidebar_wrap"].visible) + + def test_f4_cycles_theme(self): + app, _agent, _root, refs = self.make_chat() + refs["box"].focus() + self.key(app, "f4") + self.assertEqual(tai.tui_theme().name, "light") + self.assertIn("theme: light", refs["status"].text) + + def test_enter_sends_and_turn_runs(self): + app, agent, _root, refs = self.make_chat() + refs["box"].focus() + self.type(app, "hi bot") + self.key(app, "enter") + self.assertEqual(refs["pending"], "hi bot") + self.assertEqual(refs["box"].value, "") + self.assertIn("thinking", refs["status"].text) + refs["run_pending"]() + self.assertEqual(agent.turns, ["hi bot"]) + shown = [line for line, _spans in refs["transcript"].lines] + self.assertTrue(any("hi bot" in line for line in shown)) + self.assertTrue(any("echo: hi bot" in line for line in shown)) + self.assertNotIn("thinking", refs["status"].text) + + def test_turn_stdout_is_buried(self): + _app, agent, _root, refs = self.make_chat() + + def noisy(text, capture=False): + print("CARD-JUNK-TO-STDOUT") + agent.turns.append(text) + return "done" + + agent.run_turn = noisy + refs["pending"] = "go" + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + refs["run_pending"]() + self.assertEqual(buf.getvalue(), "") + shown = [line for line, _spans in refs["transcript"].lines] + self.assertTrue(any("done" in line for line in shown)) + + def test_send_ignores_empty_and_busy(self): + _app, _agent, _root, refs = self.make_chat() + refs["do_send"](" ") + self.assertIsNone(refs["pending"]) + refs["pending"] = "one" + refs["do_send"]("two") + self.assertEqual(refs["pending"], "one") + + def test_newline_keys_insert_in_send_mode(self): + app, _agent, _root, refs = self.make_chat() + refs["box"].focus() + self.key(app, "alt+enter", "\n") + self.key(app, "shift+enter", "") + self.assertEqual(len(refs["box"].lines), 3) + self.assertIsNone(refs["pending"]) + + def test_completion_enter_accepts_instead_of_send(self): + app, _agent, _root, refs = self.make_chat() + refs["box"].focus() + self.type(app, "/he") + self.assertIsNotNone(refs["box"].complete_popup) + self.key(app, "enter") + self.assertIsNone(refs["pending"]) + self.assertTrue(refs["box"].value.startswith("/help")) + + def test_max_chars_truncates(self): + _app, _agent, _root, refs = self.make_chat() + refs["box"].insert("x" * 2005) + self.assertEqual(len(refs["box"].value), 2000) + + def test_slash_help_and_quit(self): + app, agent, _root, refs = self.make_chat() + refs["do_send"]("/help") + shown = "\n".join(line for line, _style in refs["transcript"].lines) + self.assertIn("this text", shown) + self.assertEqual(agent.turns, []) + refs["do_send"]("/quit") + self.assertFalse(app._running) + + def test_bot_switch_keeps_drafts(self): + app, agent, _root, refs = self.make_chat() + refs["box"].focus() + self.type(app, "draft-1") + refs["sidebar"].choose(1) + self.assertEqual(agent.bot, "coder") + self.assertEqual(refs["box"].value, "") + self.assertEqual(refs["head_name"].text, "[C] coder") + refs["sidebar"].choose(0) + self.assertEqual(agent.bot, "main") + self.assertEqual(refs["box"].value, "draft-1") + + def test_strip_ansi(self): + self.assertEqual(tai.tui_strip_ansi("\x1b[1;32mok\x1b[0m"), "ok") + self.assertEqual(tai.tui_strip_ansi("plain"), "plain") + + def bubble_styles(self): + plain = tai.TuiStyle() + return {"base": plain, "bubble": plain, "meta": plain, "tick": plain} + + def test_bubble_rows_align(self): + rows = tai.tui_chat_bubble_rows("hi", 60, "out", self.bubble_styles(), "12:00", tai.TUI_CHAT_TICK_READ, True) + text = "".join(span.text for span in rows[0]) + self.assertEqual(len(text), 60) + self.assertTrue(text.startswith(" ")) + self.assertTrue(text.rstrip().endswith("12:00 " + tai.TUI_CHAT_TICK_READ)) + rows = tai.tui_chat_bubble_rows("hi", 60, "in", self.bubble_styles()) + text = "".join(span.text for span in rows[0]) + self.assertTrue(text.startswith(" hi ")) + self.assertTrue(text.endswith(" ")) + + def test_bubble_rows_cap_width(self): + rows = tai.tui_chat_bubble_rows("x" * 100, 60, "in", self.bubble_styles()) + self.assertTrue(len(rows) > 2) + first = "".join(span.text for span in rows[0]) + self.assertEqual(len(first), 60) + self.assertEqual(first.strip(), "x" * 40) + + def test_bubble_rows_tucked_meta_keeps_body(self): + rows = tai.tui_chat_bubble_rows("first line here with padding words second line tail end", 60, "out", + self.bubble_styles(), "12:00", "x") + texts = ["".join(span.text for span in row) for row in rows] + self.assertTrue(len(texts) >= 2) + self.assertTrue(any("first line here" in line for line in texts)) + self.assertTrue(any("tail end" in line and "12:00" in line for line in texts)) + + def test_bubble_rows_narrow_degrade(self): + rows = tai.tui_chat_bubble_rows("hi there", 20, "out", self.bubble_styles(), "12:00", "x") + text = "".join(span.text for span in rows[0]) + self.assertTrue(text.startswith("hi there")) + self.assertIn("12:00", "".join(span.text for span in rows[-1])) + + def test_pill_row_centered(self): + spans = tai.tui_chat_pill_row("Today", 40, tai.TuiStyle(), tai.TuiStyle()) + text = "".join(span.text for span in spans) + self.assertEqual(len(text), 40) + self.assertEqual(text.strip(), "Today") + self.assertTrue(text.startswith(" ")) + + def test_ticks_settle_on_reply(self): + app, agent, _root, refs = self.make_chat() + refs["do_send"]("hi bot") + shown = " ".join(line for line, _spans in refs["transcript"].lines) + self.assertIn(tai.TUI_CHAT_TICK_SEND, shown) + self.assertNotIn(tai.TUI_CHAT_TICK_READ, shown) + self.assertEqual(refs["head_status"].text, "typing...") + refs["run_pending"]() + shown = " ".join(line for line, _spans in refs["transcript"].lines) + self.assertIn(tai.TUI_CHAT_TICK_READ, shown) + self.assertNotIn(tai.TUI_CHAT_TICK_SEND, shown) + self.assertEqual(refs["head_status"].text, "online") + + def test_date_pill_on_empty_history(self): + app = tai.TuiApp() + app.rows = 24 + app.cols = 100 + agent = FakeChatAgent() + agent.messages = [{"role": "system", "content": "sys"}] + _root, refs = tai.tui_build_chat(app, agent) + app.mount(_root) + refs["replay"]() + shown = " ".join(line for line, _spans in refs["transcript"].lines) + import datetime as datetime_mod + now = datetime_mod.datetime.now() + self.assertIn("%s %d" % (now.strftime("%B"), now.day), shown) + + def test_chat_list_two_line_rows(self): + app, _agent, _root, refs = self.make_chat() + sidebar = refs["sidebar"] + rows = sidebar.content_rows() + texts = ["".join(span.text for span in row) for row in rows] + self.assertIn("main", texts[0]) + self.assertIn("hi there", texts[1]) + self.assertIn("coder", texts[2]) + refs["box"].focus() + self.type(app, "draft-1") + sidebar.choose(1) + rows = sidebar.content_rows() + texts = ["".join(span.text for span in row) for row in rows] + self.assertIn("Draft:", texts[1]) + + def test_chat_list_click_maps_pairs(self): + _app, agent, _root, refs = self.make_chat() + sidebar = refs["sidebar"] + event = tai.TuiClick(panel=sidebar, x=sidebar.ax + 2, y=sidebar.ay + 2, pressed=True) + sidebar.on_click(event) + self.assertEqual(agent.bot, "coder") + event = tai.TuiClick(panel=sidebar, x=sidebar.ax + 2, y=sidebar.ay + 0, pressed=True) + sidebar.on_click(event) + self.assertEqual(agent.bot, "main") + + def test_send_button_press_sends(self): + _app, _agent, root, refs = self.make_chat() + refs["box"].focus() + refs["box"].insert("via button") + root.find("send").on_press(None) + self.assertEqual(refs["pending"], "via button") + + def test_telegram_roles_registered(self): + self.assertEqual(len(tai.TUI_THEME_ROLES), 22) + for role in ("bubble_in", "bubble_out", "bubble_fg", "meta_in", "meta_out", + "tick_read", "service_bg", "service_fg", "unread", "unread_muted"): + self.assertIn(role, tai.TUI_THEME_ROLES) + tai.tui_set_theme("dark") + self.assertEqual(tai.TuiStyle(bg="role:bubble_out").sgr(), "\x1b[0;48;2;43;82;120m") + + def test_parser_flags(self): + args = tai.build_parser().parse_args(["--tui", "--theme", "nord"]) + self.assertTrue(args.tui) + self.assertEqual(args.theme, "nord") + + class EmbeddedStringsTests(unittest.TestCase): def test_box_scripts_compile(self): for name in ("BOX_STT", "BOX_TTS"): diff --git a/tui.md b/tui.md index e1827f3..2f7570f 100644 --- a/tui.md +++ b/tui.md @@ -189,7 +189,10 @@ callbacks; exceptions in callbacks never break the loop. literally with CR/CRLF normalized to LF. `complete(prefix)` wires a `TuiAutocomplete` popup for `/words` and `mentions(prefix)` the same for `@words` (bots, providers, models, files) before the - cursor. + cursor. `send_on_enter=True` with `on_send(value)` turns Enter + into send (an open popup still accepts first); Shift+Enter (kitty + terminals) and Alt+Enter insert a newline instead. `max_chars` + caps the buffer (`TUI_CHAT_INPUT_CAP`, 2000, in the chat scene). - `TuiAutocomplete` - non-focusable `TuiOptions` popup owned by a textbox; typing filters, arrows/home/end/pgup/pgdn move, Enter accepts, Esc dismisses (a second Esc still bubbles); flips above @@ -208,6 +211,66 @@ callbacks; exceptions in callbacks never break the loop. - `TuiLog` - virtualized scrollback; `append(text, style)` follows the tail while pinned; wheel/pgup/pgdn/home/end navigate. +## Themes + +Colors go through named roles, not literals. `TuiTheme(name, dark, +roles)` holds 22 roles: the 12 base roles (`bg`, `surface`, `fg`, +`muted`, `border`, `accent`, `on_accent`, `selection`, `success`, +`warning`, `error`, `info`) plus 10 Telegram roles (`bubble_in`, +`bubble_out`, `bubble_fg`, `meta_in`, `meta_out`, `tick_read`, +`service_bg`, `service_fg`, `unread`, `unread_muted`, with day/night +values from the tdesktop theme files); `TUI_THEMES` is the registry +with five builtins +(`dark`, `light`, `nord`, `gruvbox`, `ansi`); `tui_register_theme()` +adds more (all 12 roles required). Widgets use `fg="role:accent"` +style values, resolved against the current theme at draw time; raw +colors (`#rrggbb`, ANSI names, ints) pass through untouched, and +per-widget styles merge over role styles as before. Unknown roles +render uncolored rather than crashing. + +Selection precedence: `--theme` flag, `TAI_THEME` env var, `dark` +default; an unknown name prints the available list and exits 2. +`App.set_theme(name)` swaps the global theme and redraws everything; +F4 cycles registry order in the chat scene. To change a color, edit +one value in `_tui_builtin_themes()` or register a custom theme. + +## Chat scene (`--tui`) + +`./tai.py --tui` runs the fullscreen chat UI with REPL parity, +styled after the Telegram client: a bots sidebar with two-line rows +(name / snippet or red draft), a conversation header (avatar +initial, name, `online` / `typing...` plus hairline), a message +transcript of aligned bg-fill bubbles (yours right, theirs left, +70% max width, time plus ticks tucked bottom-right inside), a +1-line status bar, and a composer (input plus Send button). Ticks +follow Telegram: clock while sending, single check on the cloud, +blue double check once read; service pills mark the date. Sidebar +selection switches bots with per-bot input drafts; Tab cycles +sidebar, transcript, input, Send. + +Slash commands run inline with output captured into a dim bubble +(`/quit` quits); anything else runs a full agent turn whose reply +lands as an incoming bubble. The transcript keeps a block journal +and replays it on resize, so bubbles reflow instead of freezing at +the old width; below usable width they degrade to full-width rows. + +Keys: Enter sends (Shift+Enter / Alt+Enter newline), F2 toggles the +sidebar, F4 cycles the theme, `i` or Esc jumps to the input, `q` +quits from outside the input. Below 80 columns the sidebar +auto-hides (`TUI_CHAT_NARROW_COLS`); a manual F2 hide/show wins over +the automatic rule until toggled again. + +Turns run inline on the loop via a deferred timer: your message and +a `thinking...` status paint first, then the turn blocks (like the +telegram bot) until the reply lands. A worker thread was considered +and rejected: it would share one sqlite connection across threads, +which sqlite forbids. `ask_user` cannot prompt mid-turn here (stdin +is swapped for a non-tty during the turn, so the tool declines and +the agent decides instead). Approvals cannot prompt mid-turn either +for the same reason, so gated tools are denied unless the session +pre-approved them (`--yes` / `--yolo`); allowlisted read-only +commands still run. + ## Terminal widget notes `spawn()` forks the command onto a pty sized to the widget; resizes @@ -221,10 +284,17 @@ the widget shows a plain error line instead of crashing. - Wide (CJK/emoji) characters count as one column; columns around them misalign. Structured to fix with a width table later. -- No stylesheet language (constructor kwargs instead), only the - key-event subset of the kitty protocol (no release tracking, no - super/hyper/meta, no alternate-key shortcut matching), no true +- The theme layer is role names plus a registry, not a full + stylesheet language (no selectors, no file-based overrides); only + the key-event subset of the kitty protocol (no release tracking, + no super/hyper/meta, no alternate-key shortcut matching), no true opacity blending. +- The chat scene has no markdown-to-styled-run renderer yet + (assistant markdown shows unstyled), no bubble tails, no unread + pills or per-chat times (no honest data source), no attach/voice + or reply-preview (no function behind them), tool calls show as dim + bubbles (no collapsible blocks), no per-token streaming, no + send-history recall. - No per-widget async tasks; blocking work belongs in threads that post back via timers. - The VT parser drops provably-malformed tails past 64KB and caps