Commit graph

66 commits

Author SHA1 Message Date
Mario Zechner
04a93bad8f fix(ai,agent,coding-agent,durable): client identity follow-ups
- ClientAttribution is { name, url, categories? } with required name and url, so
  OpenRouter always gets an HTTP-Referer. identity.ts maps the fields to each
  provider's headers; NVIDIA gets the name with its first letter upper-cased.
  attribution: null turns it off. PI_ATTRIBUTION is pi's, including the
  cli-agent category; agent-core, durable, and the coding agent use it.
- Categories are a string array, joined for OpenRouter.
- withClientIdentity() is a typed wrapper instead of a Proxy and keeps a
  MutableModels mutable. Durable no longer caches wrappers in a WeakMap.
- The Codex originator stays pi; login agentName no longer follows attribution.
- Models and the coding agent's ModelRuntime add x-opencode-session for custom
  providers pointing at OpenCode, replacing the coding agent's transformHeaders.
2026-10-21 11:18:16 +00:00
Armin Ronacher
adc5fa9f80 feat(ai,agent,coding-agent): move client identity and provider attribution into pi-ai
pi-ai gets a ClientIdentity request option and createModels() default that choose the User-Agent (detailed with version, short, or custom) and provider attribution headers for OpenRouter, NVIDIA NIM, and OpenCode. Attribution is off by default in pi-ai and on by default in pi-agent-core and pi-durable (HarnessOptions.identity). pi-coding-agent sets its identity from the telemetry setting instead of adding headers itself.
2026-10-21 11:17:02 +00:00
David Brailovsky
002fc83852
feat: expose provider stream events to extensions (#9901)
Add onProviderStreamEvent through pi-ai and agent core, and surface
provider_stream_event to coding-agent extensions.

Closes #9784
2026-09-23 16:03:30 +02:00
Mario Zechner
466db0fecd feat: add canonical session context boundaries
Make SessionManager projections authoritative for provider requests, add append-only context edits and actionable turn boundaries, and preserve existing queue scheduling during continuation and recovery.
2026-09-21 16:59:20 +02:00
Armin Ronacher
9e05370b29
Mid conversation system messages (#9548)
This change makes system prompt text and tool changes part of the transcript rather than silently rewriting its starting conditions. This lets Pi record when instructions changed or tools became available, restore that state after resuming or navigating branches, and preserve cached prompt prefixes where the upstream supports it.
2026-09-16 15:54:07 +02:00
Vegard Stikbakke
3a0b9a3eee Revert "feat(agent): expose provider context construction"
This reverts commit 2509b5c037.
2026-08-19 09:53:15 +02:00
Vegard Stikbakke
2509b5c037 feat(agent): expose provider context construction 2026-08-18 09:34:47 +02:00
wesleyzhangwq
1532c99943
fix(agent): reject reset during active runs (#7717) 2026-08-06 17:12:25 +02:00
yaogangqiang
0f5286d8ab
feat(agent): expose shouldStopAfterTurn on Agent (#7367) 2026-08-03 14:01:16 +02:00
Mario Zechner
b9e5c5d941 fix(agent): restore streamFn extension compatibility
Keep streamFn required for typed callers while preserving the legacy runtime fallback for extensions that omit it.\n\nfixes #6915
2026-07-21 18:37:07 +02:00
Mario Zechner
1235c0ec64 fix(agent): decouple agent streams from compat
closes #6851
2026-07-20 17:54:36 +02:00
Mario Zechner
fd6659dd5d fix(coding-agent): preserve run prompt during tool refresh
closes #6162
2026-06-30 14:08:48 +02:00
Mat
e547bb9f41
fix(coding-agent): refresh session state before next turn 2026-06-30 13:56:04 +02:00
Mario Zechner
8a0903ebf2 feat(ai): compat entrypoint, core-only root barrel (phase 5)
The root barrel is now core-only and side-effect free: types,
createModels/createProvider, auth substrate, lazyStream/lazyApi, faux,
utils. Generated catalogs, api-registry, env-api-keys, images, global
stream functions, and per-API lazy wrappers leave the root.

New @earendil-works/pi-ai/compat preserves the old surface verbatim as
a strict superset of the root: api-dispatch stream/complete with env
key injection, the builtin registration side effect (skip-if-present so
it cannot clobber earlier overrides), deprecated getModel/getModels/
getProviders aliases of the new getBuiltin* reads in providers/all,
lazy api wrappers + setBedrockProviderModule, and image generation.
Compat dies with the coding-agent ModelManager migration.

Packaging: exports map gains ./compat, ./providers/*, ./api/*;
sideEffects array lists only the effectful modules.

Old-global imports across agent/coding-agent/examples and pi-ai tests
switch to /compat (path-only; compat is a superset). The coding-agent
extension loader resolves the pi-ai ROOT specifier to compat, so
existing user extensions using the old global API keep working at
runtime until compat is removed. vitest configs alias /compat to src;
browser smoke imports old globals from /compat.
2026-06-10 21:17:12 +02:00
Armin Ronacher
ae9450dc51 chore(ts): use source import extensions 2026-05-20 00:04:03 +02:00
Mario Zechner
06c6c324d7 chore: enforce erasable TypeScript syntax 2026-05-19 23:15:39 +02:00
Mario Zechner
b7ea82105a refactor(agent): run harness loop directly 2026-05-14 21:33:34 +02:00
Mario Zechner
322759a3f0 refactor(agent): snapshot harness turn state 2026-05-09 23:34:58 +02:00
Mario Zechner
90c017b05b Merge remote-tracking branch 'origin/main' into bigrefactor
# Conflicts:
#	package-lock.json
#	packages/agent/package.json
2026-05-08 13:38:20 +02:00
Mario Zechner
3e5ad67e0f chore: migrate pi packages to earendil works scope 2026-05-07 15:59:42 +02:00
Mario Zechner
617d8b317d refactor(agent): tighten harness environment and resources 2026-05-06 19:41:17 +02:00
Mario Zechner
b8bb2411ff fix(ai): honor codex transport option
closes #4083
2026-05-02 14:14:22 +02:00
Mario Zechner
d131fcd4ba feat(coding-agent): add after_provider_response hook closes #3128 2026-04-16 20:28:08 +02:00
Mario Zechner
9022a5b5ea fix(agent): await subscribed event handlers 2026-03-30 14:13:30 +02:00
Mario Zechner
cbe1a8b732 fix(agent): simplify state API and update consumers fixes #2633 2026-03-30 12:43:34 +02:00
Mario Zechner
7d4faa080d fix: expose abort signal to extensions closes #2660 2026-03-28 22:25:06 +01:00
Mario Zechner
8a8e2a8049 docs(agent): update steering docs for deferred tool execution closes #2330 2026-03-18 03:49:30 +01:00
Mario Zechner
63ac2df24d fix(coding-agent): sync tool hooks with agent event processing closes #2113 2026-03-14 03:10:04 +01:00
Mario Zechner
a3f05423d9 feat(coding-agent): add provider payload hook 2026-03-07 14:34:28 +01:00
Mario Zechner
a26a9cfabd feat: add configurable transport and codex websocket session caching 2026-02-13 23:41:49 +01:00
Mario Zechner
b050c582a1 fix(agent,coding-agent): resume queued messages after auto-compaction 2026-02-06 11:36:19 +01:00
Mario Zechner
030a61d88c feat: add maxDelayMs setting to cap server-requested retry delays
When a provider (e.g., Google Gemini CLI) requests a retry delay longer
than maxDelayMs (default: 60s), the request fails immediately with an
informative error instead of waiting silently for hours.

The error is then handled by agent-level auto-retry, which shows the
delay to the user and allows aborting with Escape.

- Add maxRetryDelayMs to StreamOptions (packages/ai)
- Add maxRetryDelayMs to AgentOptions (packages/agent)
- Add retry.maxDelayMs to settings (packages/coding-agent)
- Update _isRetryableError to match 'retry delay' errors

fixes #1123
2026-02-01 00:50:41 +01:00
Melih Mucuk
0f27eae77e feat: add thinkingBudgets option to customize token budgets 2026-01-07 15:13:26 +03:00
Mario Zechner
edb0da9611 feat(ai,agent,coding-agent): add sessionId for provider session-based caching
- Add sessionId to StreamOptions for providers that support session-based caching
- OpenAI Codex provider uses sessionId for prompt_cache_key and routing headers
- Agent class now accepts and forwards sessionId to stream functions
- coding-agent passes session ID from SessionManager and updates on session changes
- Update ai package README with table of contents, OpenAI Codex OAuth docs, and env vars table
- Increase Codex instructions cache TTL from 15 minutes to 24 hours
- Add tests for sessionId forwarding in ai and agent packages
2026-01-06 11:08:42 +01:00
Mario Zechner
0b9e3ada0c fix: clean up Codex thinking level handling
- Remove per-thinking-level model variants (gpt-5.2-codex-high, etc.)
- Remove thinkingLevels from Model type
- Provider clamps reasoning effort internally
- Omit reasoning field when thinking is off

fixes #472
2026-01-05 21:58:26 +01:00
Ben Vargas
02b72b49d5 fix: codex thinking handling 2026-01-05 21:55:47 +01:00
Mario Zechner
d0a4c37028 feat(agent): split queue into steer() and followUp() APIs
Breaking change: replaces queueMessage() with two separate methods:
- steer(msg): interrupt mid-run, delivered after current tool execution
- followUp(msg): wait until agent finishes before delivery

Also renames:
- queueMode -> steeringMode/followUpMode
- getQueuedMessages -> getSteeringMessages/getFollowUpMessages

Refs #403
2026-01-03 00:13:25 +01:00
Mario Zechner
5ef3cc90d1 Add guard against concurrent prompt() calls
Agent.prompt() and Agent.continue() now throw if called while already
streaming, preventing race conditions and corrupted state. Use
queueMessage() to queue messages during streaming, or await the
previous call.

AgentSession.prompt() has the same guard with a message directing
users to queueMessage().

Ref #403
2026-01-02 22:02:24 +01:00
Mario Zechner
41af99cccf Support multiple messages in agent.prompt() and agentLoop
- agentLoop now accepts AgentMessage[] instead of single message
- agent.prompt() accepts AgentMessage | AgentMessage[]
- Emits message_start/end for each message in the array
- AgentSession.prompt() builds array with hook message + user message
- TUI now receives events for before_agent_start injected messages
2025-12-30 22:42:22 +01:00
Mario Zechner
4d1936d3df AgentInterface sets default streamFn and getApiKey
- Make Agent.streamFn and Agent.getApiKey public
- AgentInterface sets defaults if not already set
- Example no longer needs to configure these
2025-12-30 22:42:21 +01:00
Mario Zechner
e49e787322 Set isStreaming=false on agent_end event, before emitting to listeners
Was only setting in finally block, after event was emitted.
2025-12-30 22:42:21 +01:00
Mario Zechner
a055fd4481 WIP: Refactor agent package - not compiling
- Renamed AppMessage to AgentMessage throughout
- New agent-loop.ts with AgentLoopContext, AgentLoopConfig
- Removed transport abstraction, Agent now takes streamFn directly
- Extracted streamProxy to proxy.ts utility
- Removed agent-loop from pi-ai (now in agent package)
- Updated consumers (coding-agent, mom) for AgentMessage rename
- Tests updated but some consumers still need migration

Known issues:
- AgentTool, AgentToolResult not exported from pi-ai
- Attachment not exported from pi-agent-core
- ProviderTransport removed but still referenced
- messageTransformer -> convertToLlm migration incomplete
- CustomMessages declaration merging not working properly
2025-12-30 22:42:20 +01:00
Mario Zechner
f7ef44dc38 Fix: transform userMessage in _runAgentLoop before passing to transport
HookMessage (role: hookMessage) was being passed directly to transport
without transformation. Now it's transformed via messageTransformer
which converts it to a proper user message for the LLM.
2025-12-30 22:42:20 +01:00
Mario Zechner
204d27581b Cleanup: unify HookMessage naming and simplify SessionContext
- Rename HookAppMessage to HookMessage, isHookAppMessage to isHookMessage
- Remove entries array from SessionContext (use isHookMessage type guard instead)
- HookMessage.content now accepts string directly (not just array)
- Fix streamMessage type in AgentState (AppMessage, not Message)
- Rename CustomMessageComponent to HookMessageComponent
- Fix test hook to use pi.sendMessage
2025-12-30 22:42:20 +01:00
Mario Zechner
a2515cf43f Wire context event to preprocessor for per-LLM-call execution
- Change from contextTransform (runs once at agent start) to preprocessor
- preprocessor runs before EACH LLM call inside the agent loop
- ContextEvent now uses Message[] (pi-ai format) instead of AppMessage[]
- Deep copy handled by pi-ai preprocessor, not Agent

This enables:
- Pruning rules applied on every turn (not just agent start)
- /prune during long agent loop takes effect immediately
- Compaction can use same transforms (future work)
2025-12-30 22:42:20 +01:00
Mario Zechner
77fe3f1a13 Add context event for non-destructive message modification before LLM calls
- Add contextTransform option to Agent (runs before messageTransformer)
- Deep copy messages before passing to contextTransform (modifications are ephemeral)
- Add ContextEvent and ContextEventResult types
- Add emitContext() to HookRunner (chains multiple handlers)
- Wire up in sdk.ts when creating Agent with hooks

Enables dynamic context pruning: hooks can modify messages sent to LLM
without changing session data. See discussion #330.
2025-12-30 22:42:20 +01:00
Mario Zechner
c1b4d043a8 Remove emitLastMessage from continue(), use prompt(AppMessage) instead
Cleans up the temporary emitLastMessage plumbing since we now use
Agent.prompt(AppMessage) for hook messages instead of appendMessage+continue.

- Remove emitLastMessage parameter from Agent.continue()
- Remove from transport interface and implementations
- Remove from agentLoopContinue()
2025-12-30 22:42:19 +01:00
Mario Zechner
a6322fda59 Add Agent.prompt(AppMessage) overload for custom message types
Instead of using continue() which validates roles, prompt() now accepts
an AppMessage directly. This allows hook messages with role: 'hookMessage'
to trigger proper agent loop with message events.

- Add overloads: prompt(AppMessage) and prompt(string, attachments?)
- sendHookMessage uses prompt(appMessage) instead of appendMessage+continue
2025-12-30 22:42:19 +01:00
Mario Zechner
357bd946c2 Add emitLastMessage flag to agent.continue()
When calling continue() with emitLastMessage=true, the agent loop
emits message_start/message_end events for the last message in context.
This allows messages added outside the loop (e.g., hook messages via
sendHookMessage) to trigger proper TUI rendering.

Changes across packages:
- packages/ai: agentLoopContinue() accepts emitLastMessage parameter
- packages/agent: Agent.continue(), transports updated to pass flag
- packages/coding-agent: sendHookMessage passes true when triggerTurn
2025-12-30 22:42:19 +01:00
Mario Zechner
5a9d844f9a Simplify compaction: remove proactive abort, use Agent.continue() for retry
- Add agentLoopContinue() to pi-ai for resuming from existing context
- Add Agent.continue() method and transport.continue() interface
- Simplify AgentSession compaction to two cases: overflow (auto-retry) and threshold (no retry)
- Remove proactive mid-turn compaction abort
- Merge turn prefix summary into main summary
- Add isCompacting property to AgentSession and RPC state
- Block input during compaction in interactive mode
- Show compaction count on session resume
- Rename RPC.md to rpc.md for consistency

Related to #128
2025-12-09 21:43:49 +01:00