| Age | Commit message (Collapse) | Author |
|
|
|
|
|
Teach provider config and auth resolution about the Codex Responses
dialect, including user-facing `style = "openai_responses"` with
`dialect = "codex"`. Serialize and parse Responses traffic with
provider-specific reasoning replay, assistant phase metadata, and robust
function-call assembly keyed by `output_index` so streamed tool inputs
survive proxy quirks and empty terminal payloads.
Also persist thinking origins and message metadata across sessions, add
the Anthropic interleaved-thinking header switch, write per-session
debug logs, and improve the TUI and scripts for inspecting tool output
and session costs.
|
|
|
|
Collapse the auth schema: infer `type` from keys, replace key/key_env_var with
a single `key` (resolved via substitution), flatten the exchange to flat
`exchange_*` keys, and drop the auth-level headers tables in favor of reusing
the provider's `extra_headers` on the auth HTTP calls. Add `${sibling}` and
`${env:VAR}` substitution over auth values (GitHub Enterprise = set `domain`).
Restore api_key-empty → provider-drop. Update default config, docs, and tests.
|
|
limitation
|
|
Add the OpenAI Responses API wire dialect (openai_responses APIStyle +
OpenAIResponsesConfig), a request serializer (instructions/input items,
flat function tools, reasoning, store:false, include encrypted reasoning),
and a streaming state machine over the typed response.* SSE events mapping
to the shared block model. Wire dispatch, buildProviderConfig, the C-ABI
free switch, and the reasoning selectors. Ship a commented Codex example in
the default config.
Implemented from the Responses API docs + the open-source Codex client and
covered by fixture tests; live verification against a ChatGPT plan is still
required (documented).
|
|
Record resolved open questions (clean break, key_env_var, codex dialect,
file-backed storage), the core/CLI split, verified device-flow specifics for
Copilot and Codex, the Codex Responses-API finding, and verification status.
|
|
Resolve the active provider's auth before each turn via the AuthManager,
rendering an inline device-code prompt when login is needed, and force a
single refresh/exchange retry on a provider auth failure. Wire the manager
through RunOptions from main.zig.
|
|
Add src/auth_manager.zig (turn-time resolution: load→login→refresh→exchange→
build credential, patch live config) and `panto auth status|login|logout`
subcommands with a line-based device-code presenter. Add config_file.loadFromString.
|
|
Implement the device-authorization flow for both dialects (GitHub `token`
direct-poll; Codex `codex` poll→authorization-code→PKCE exchange), refresh_token
grant, Copilot secondary token exchange, JWT exp parsing, Codex account-id
extraction, and pure credential-building/refresh predicates. Adds a Presenter
hook for rendering the device-code prompt. Exported from public.zig.
|
|
Add libpanto http_helper (non-streaming request/response over the global
client, plus dotted-JSON-path readers) and token persistence in auth.zig
(load/save/delete TokenSet under an embedder-chosen auth dir, owner-only
files). Add $PANTO_HOME/auth to the panto_home layout.
|
|
Add provider.mergeHeaders and use it in both the openai_chat and
anthropic_messages providers so config extra_headers ride on the model
request, merged onto the built-in header set.
|
|
Replace provider-level api_key/api_key_env_var with named auth sessions:
providers now reference `auth = "<name>"` and credentials live under
`[auth.<name>]`. Adds the libpanto auth type surface (AuthConfig, TokenSet,
ResolvedCredential), a Header type and provider `extra_headers`, and rewires
the CLI config loader (parse [auth.<name>], require auth=, providers always
survive, eager api_key resolution). Updates the shipped default config.
|
|
|
|
|
|
|
|
|
|
|
|
Remove setFrameTime() method and fps-related rendering from Footer.
Replace with setModel() to display model name with dim styling. Update
all Footer tests accordingly, adjusting line counts and expectations for
new layout with top/bottom rules wrapping content. Remove reverse video
styling from footer.
|
|
|
|
|
|
some libpanto-c coverage expansion was needed
|
|
- FSJSONLStore: don't require `cwd`, instead panto CLI provides it in
the session metadata
- Lua: expose the `SessionStore` interface and the `FSJSONLStore` and
`NullStore` implementations
- C: use idiomatic `const char *` for incoming strings
- C: expose the `FSJSONLStore` and `NullStore` implementations
|
|
|
|
|
|
|
|
output
The root cause was a two-part bug:
1. Engine slot management (tui_engine.zig): The app rebuilds its full
component list on every new transcript entry. The old approach drained
every slot then re-added them all, resetting every component's render
baseline. When earlier content had scrolled into native scrollback
(viewport_top > 0), the engine's viewport-escape rule escalated any
cut above the viewport top to a scrollback-clearing full redraw — the
visible flash on every streamed block while a tool call was expanded.
Fix: replace drain+rebuild with syncComponents(), which reconciles the
live slot list in place by finding the longest common prefix and suffix
(matched by component pointer). Prefix and suffix slots keep their
baselines verbatim; only the changed region in the middle gets new
empty slots. A pure insertion (the dominant case: a new transcript
entry appended just before the pinned input+footer suffix) stays on
the differential path with no clear. A structural change (slot
replaced or removed) sets force_full for correctness.
2. RenderCache dirty signal (tui_component.zig): firstLineChanged()
was returning the retained changed_from diff index even when the cache
was clean. A first-paint store records changed_from == 0, so a clean
but previously-rendered component was pegging the differential cut to
line 0 on every subsequent frame, making unchanged slots above the
insertion point drag the cut all the way up. Fix: when the cache is
clean, firstLineChanged() returns null unconditionally. The recorded
changed_from is now internal render bookkeeping only, not a live
signal.
Additional changes:
- ToolUse.collapsed_tail_lines raised from 5 to 8 lines.
- ToolUse collapsed-view test updated to use 12 output lines and
collapsed_tail_lines symbolically so the numbers self-document.
- tui_app.zig: override-slot test comment and assertion clarified to
reflect that the override owns the slot pointer (not just renders it),
and the SWAPPED-AT-DETAILS render check replaced with a pointer-equality
check.
- lua_event_bridge.zig: minor related fixes.
- New tests: syncComponents middle-insertion no-clear, syncComponents
structural removal forces full, syncComponents override swap; streaming
expanded-tools no-clear regression test in tui_app.
|
|
|
|
|
|
Conversation.addUserMessage now takes a []ContentBlock (symmetric with
addAssistantMessage). Introduce a thin addUserText wrapper in agent.zig
for the plain-text case and update every call site in agent.zig and
anthropic_messages_json.zig accordingly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
determine support for the kitty protocol and then pick output sequences
accordingly.
tested on ghostty (supports kitty) and tmux-in-ghostty (tmux does not
support kitty protocol) with shift+enter as newline.
|
|
Implement TUI Phase 1: a raw-mode terminal, differential render engine,
pinned input box + footer, and component model wired into the libpanto
event stream. Adds foundation modules (theme, key, component, input,
terminal), the render engine, components, and the app loop; removes the
old print CLIRenderer and driveTurn REPL from main.zig.
Also removes scratch status reports (tui-p1/, progress.md) for the now
completed work.
|
|
|
|
|
|
Push the API-shaping we'd done in the public facade down into the internal
types, collapsing the wrappers:
- Stream: rename phase->state, Phase->State; underscore-prefix the internal
fields (_agent/_queue/_response/_start/_persisted/_pending_error). state
is the one intended-public field. public.zig now aliases Stream; run
returns *Stream.
- Agent compaction: pure transform compact()->private _compactInPlace;
compactAndPersist()->compact() (the public name, persists).
- Agent system prompt: addSystemMessage(text,mode) split into
addSystemMessage(text) + setSystemPrompt(text) over a private
_persistSystemMessage.
- UserMessage moved off Agent to module scope.
- Underscore-prefix pure-internal Agent fields: _open_stream_fn,
_auto_compacted, _retry_prng.
The Agent facade is now pure 1:1 forwarders; it stays a wrapper only because
init heap-pins the inner (copyable, move-safe handle) and conversation()/
sessionId() are accessors. Conversation and Stream are plain aliases.
|
|
A facade that forwards every method 1:1 is worse than paring the real type
down to the intended surface and aliasing it. conversation.Conversation's
interface is already the public surface we want (init/deinit, the
add*/replace* builders, and messages/allocator as plain data fields), so
public.zig now aliases it straight through and Agent.conversation() returns
a borrowed *Conversation for in-place surgery. Drops the ConversationData
alias and the pointer-wrapper.
Merged addAssistantMessageWithUsage into addAssistantMessage(blocks, ?usage)
on the real type (separate method deleted), so the alias has the intended
one-method shape; all call sites updated.
Only Agent and Stream remain true facades -- they have genuinely-internal
fields plus API-shaping renames (Stream.phase->state, Phase->State) an alias
can't express.
|
|
Close the gap that forced the CLI to import internal libpanto namespaces,
then delete the transitional re-exports. The CLI now uses only the curated
public surface.
Additions to the public Agent facade:
- init/deinit (heap-pin the inner; the handle is a copyable value).
- addSystemMessage (.append) and setSystemPrompt (.replace).
- compact(override_system_prompt, extra) falling back to the config prompt.
- sessionId() accessor.
CompactionConfig gains compaction_prompt, which owns the compaction system
prompt for both auto-compaction and the explicit compact() default; the
Agent.compaction_system_prompt field is deleted. ConversationData is the
public name for the owned conversation value type (Session.load returns it,
Agent.init adopts it), distinct from the borrowed Conversation handle.
Agent.addSystemMessage/setSystemPrompt are kept on Agent (they persist with
the SystemMode) rather than dropped as the plan first proposed.
|
|
Move the CLI off the internal libpanto module namespaces onto the curated
public API: data-type aliases (Config family, Message/MessageRole/
effectiveSystemBlocks, Event, Pricing/PricingRegistry, the session seam,
FileSystemJSONLStore, ContentBlockType), process lifecycle (panto.init/
deinit), and ResultParts.fromText/fromTextOwned/deinit in place of the
freestanding textResult/ownedTextResult/freeResultParts.
The CLI remains on two flagged internal namespaces, panto.agent and
panto.conversation: it is a deep embedder that drives the loop below the
curated Agent/Conversation facades (system-prompt seeding through the
agent, compaction_system_prompt, the open_stream_fn test seam, standalone
Conversation values, compactAndPersist). These stay re-exported from
public.zig as a documented deep-embedder escape hatch; trimming the
transitional block removed every other internal re-export.
|