Commit graph

23 commits

Author SHA1 Message Date
Mario Zechner
6977bc73ca Fix snake border alignment using visibleWidth for proper ANSI length calculation 2025-12-30 22:42:20 +01:00
Mario Zechner
b47151a04f Snake: add full border frame and pause/resume with session persistence
- Full box border around title, game area, and instructions
- ESC pauses and saves state to session via pi.appendEntry()
- Resume shows 'PAUSED - press any key to continue'
- Q quits and clears saved state
- High score persists across games
2025-12-30 22:42:20 +01:00
Mario Zechner
5ae33defd3 Fix snake velocity: render cells as 2 chars wide for square aspect
Terminal cells are ~2:1 aspect ratio, so movement appeared faster
vertically. Now each game cell is 2 characters wide.
2025-12-30 22:42:19 +01:00
Mario Zechner
516c0ea8bc Improve snake game visuals
- Rounded box corners (╭╮╰╯)
- Better characters: ● head, ○ body, ◆ food, · empty
- Colored title with emoji
- Dimmed borders and help text
- Bold highlights for score and controls
2025-12-30 22:42:19 +01:00
Mario Zechner
818196d2c3 Add immediate flag to hook commands for non-queued execution
Commands with immediate: true run right away even during streaming.
Used for UI-only commands like /snake that don't interact with LLM.
2025-12-30 22:42:19 +01:00
Mario Zechner
165fb58b39 Fix snake.ts: use key helpers from pi-tui for ESC and arrow keys 2025-12-30 22:42:19 +01:00
Mario Zechner
14ad8d6228 Add ui.custom() for custom hook components with keyboard focus
- Add custom() to HookUIContext: returns { close, requestRender }
- Component receives keyboard input via handleInput()
- CustomMessageComponent default rendering now limits to 5 lines when collapsed
- Add snake.ts example hook with /snake command
2025-12-30 22:42:19 +01:00
Mario Zechner
29fec7848e Move exec to HookAPI, sessionManager/modelRegistry to HookEventContext
Breaking changes:
- HookEventContext now has sessionManager and modelRegistry (moved from SessionEventBase)
- HookAPI now has exec() method (moved from HookEventContext/HookCommandContext)
- HookRunner constructor takes sessionManager and modelRegistry as required params
- Session events no longer include sessionManager/modelRegistry fields

Hook code migration:
- event.sessionManager -> ctx.sessionManager
- event.modelRegistry -> ctx.modelRegistry
- ctx.exec() -> pi.exec()

Updated:
- src/core/hooks/types.ts - type changes
- src/core/hooks/runner.ts - constructor, createContext
- src/core/hooks/loader.ts - add exec to HookAPI
- src/core/sdk.ts - pass sessionManager/modelRegistry to HookRunner
- src/core/agent-session.ts - remove sessionManager/modelRegistry from events
- src/modes/* - remove setSessionFile calls, update events
- examples/hooks/* - update to new API
2025-12-30 22:42:19 +01:00
Mario Zechner
ba185b0571 Hook API: replace send() with sendMessage(), add appendEntry() and registerCommand()
Breaking changes to Hook API:
- pi.send(text, attachments?) replaced with pi.sendMessage(message, triggerTurn?)
  - Creates CustomMessageEntry instead of user messages
  - Properly handles queuing during streaming via agent loop
  - Supports optional turn triggering when idle
- New pi.appendEntry(customType, data?) for hook state persistence
- New pi.registerCommand(name, options) for custom slash commands
- Handler types renamed: SendHandler -> SendMessageHandler, new AppendEntryHandler

Implementation:
- AgentSession.sendHookMessage() handles all three cases:
  - Streaming: queues message with _hookData marker, agent loop processes it
  - Not streaming + triggerTurn: appends to state/session, calls agent.continue()
  - Not streaming + no trigger: appends to state/session only
- message_end handler routes based on _hookData presence to correct persistence
- HookRunner gains getRegisteredCommands() and getCommand() methods

New types: HookMessage<T>, RegisteredCommand, CommandContext
2025-12-30 22:42:18 +01:00
Mario Zechner
9bba388ec5 Refactor SessionEventBase to pass sessionManager and modelRegistry
Breaking changes to hook types:
- SessionEventBase now passes sessionManager and modelRegistry directly
- before_compact: passes preparation, previousCompactions (newest first)
- before_switch: has targetSessionFile; switch: has previousSessionFile
- Removed resolveApiKey (use modelRegistry.getApiKey())
- getSessionFile() returns string | undefined for in-memory sessions

Updated:
- All session event emissions in agent-session.ts
- Hook examples (custom-compaction.ts, auto-commit-on-exit.ts, confirm-destructive.ts)
- Tests (compaction-hooks.test.ts, compaction-hooks-example.test.ts)
- export-html.ts guards for in-memory sessions
2025-12-30 22:42:18 +01:00
Mario Zechner
251fea752c Fix API key priority and compaction bugs
- getEnvApiKey: ANTHROPIC_OAUTH_TOKEN now takes precedence over ANTHROPIC_API_KEY
- findCutPoint: Stop scan-backwards loop at session header (was decrementing past it causing null preparation)
- generateSummary/generateTurnPrefixSummary: Throw on stopReason=error instead of returning empty string
- Test files: Fix API key priority order, use keepRecentTokens=1 for small test conversations
2025-12-30 22:42:17 +01:00
Mario Zechner
c58d5f20a4 Session tree structure with id/parentId linking
- Add TreeNode base type with id, parentId, timestamp
- Add *Content types for clean input/output separation
- Entry types are now TreeNode & *Content intersections
- SessionManager assigns id/parentId on save, tracks leafId
- Add migrateSessionEntries() for v1 to v2 conversion
- Migration runs on load, rewrites file
- buildSessionContext() uses tree traversal from leaf
- Compaction returns CompactionResult (content only)
- Hooks return compaction content, not full entries
- Add firstKeptEntryId to before_compact hook event
- Update mom package for tree fields
- Better error messages for compaction failures
2025-12-30 22:42:17 +01:00
Mario Zechner
454ea1d36a Rename /clear to /new, update hook events to before_new/new
Closes #305 - took direct rename approach instead of alias system

Thanks @mitsuhiko for the nudge!
2025-12-25 04:15:10 +01:00
Mario Zechner
54018b6cc0 Refactor OAuth/API key handling: AuthStorage and ModelRegistry
- Add AuthStorage class for credential storage (auth.json)
- Add ModelRegistry class for model management with API key resolution
- Add discoverAuthStorage() and discoverModels() discovery functions
- Add migration from legacy oauth.json and settings.json apiKeys to auth.json
- Remove configureOAuthStorage, defaultGetApiKey, findModel, discoverAvailableModels
- Remove apiKeys from Settings type and SettingsManager methods
- Rename getOAuthPath to getAuthPath
- Update SDK, examples, docs, tests, and mom package

Fixes #296
2025-12-25 03:48:36 +01:00
Mario Zechner
030788140a WIP: Remove global state from pi-ai OAuth/API key handling
- Remove setApiKey, resolveApiKey, and global apiKeys Map from stream.ts
- Rename getApiKey to getApiKeyFromEnv (only checks env vars)
- Remove OAuth storage layer (storage.ts deleted)
- OAuth login/refresh functions now return credentials instead of saving
- getOAuthApiKey/refreshOAuthToken now take credentials as params
- Add test/oauth.ts helper for ai package tests
- Simplify root npm run check (single biome + tsgo pass)
- Remove redundant check scripts from most packages
- Add web-ui and coding-agent examples to biome/tsgo includes

coding-agent still has compile errors - needs refactoring for new API
2025-12-25 01:01:03 +01:00
Mario Zechner
705ba5d4f2 Improve compaction hooks: add signal, no timeout, SessionManager cleanup, docs 2025-12-24 13:54:05 +01:00
Mario Zechner
403faafdbe Add previousSummary to before_compact hook event 2025-12-24 12:47:12 +01:00
Mario Zechner
d9a542763a Improve before_compact hook: add messagesToKeep, replace apiKey with resolveApiKey 2025-12-24 12:41:22 +01:00
Mario Zechner
e4283294c8 Update full-compaction example to use resolveApiKey 2025-12-24 12:30:00 +01:00
Mario Zechner
5aa53ded11 Add full-compaction hook example 2025-12-24 12:25:36 +01:00
Mario Zechner
42d7d9d9b6 Add before/after session events with cancellation support
- Merge branch event into session with before_branch/branch reasons
- Add before_switch, before_clear, shutdown reasons
- before_* events can be cancelled with { cancel: true }
- Update RPC commands to return cancelled status
- Add shutdown event on process exit
- New example hooks: confirm-destructive, dirty-repo-guard, auto-commit-on-exit

fixes #278
2025-12-22 18:18:38 +01:00
Mario Zechner
0ef73ad1dc Add file-trigger hook example 2025-12-17 16:06:30 +01:00
Mario Zechner
e7097d911a Custom tools with session lifecycle, examples for hooks and tools
- Custom tools: TypeScript modules that extend pi with new tools
  - Custom TUI rendering via renderCall/renderResult
  - User interaction via pi.ui (select, confirm, input, notify)
  - Session lifecycle via onSession callback for state reconstruction
  - Examples: todo.ts, question.ts, hello.ts

- Hook examples: permission-gate, git-checkpoint, protected-paths

- Session lifecycle centralized in AgentSession
  - Works across all modes (interactive, print, RPC)
  - Unified session event for hooks (replaces session_start/session_switch)

- Box component added to pi-tui

- Examples bundled in npm and binary releases

Fixes #190
2025-12-17 16:03:23 +01:00