Commit log

4f52797 handoff: Fix countdown and extract model helper

Click to expand commit body
Cancel the countdown on any terminal input, not just "editable" keys.
Arrow keys and other navigation are escape sequences that
isEditableInput() explicitly rejected, so navigating the handoff draft
didn't stop the auto-submit timer.

Extract parseAndSetModel() into model-utils.ts to deduplicate the
model-parsing logic shared between the agent_end handler in index.ts and
the /handoff command. The shared helper also wraps pi.setModel() in
try/catch, surfacing failures as user-visible warnings instead of
unhandled promise rejections.

Amolith created

4586179 handoff: Add countdown to tool-path handoff

Click to expand commit body
The tool-path handoff (agent calling the handoff tool) bypassed the
pause-to-edit countdown and sent the prompt immediately via
sendUserMessage. Replace that with setEditorText + startCountdown so
both paths give the user a 10-second window to review and edit the
handoff draft before it's submitted.

Set editor text before awaiting setModel to avoid a race where slow
model setup could clobber user edits.

Amolith created

d4d6d81 Rename pi-personality to pi-personas

Click to expand commit body
Rename the package directory, npm package name, slash command, on-disk
paths, XML tags, and all internal references from "personality" /
"personalities" to "persona" / "personas".

Amolith created

068d222 Pin peer dependency version ranges

Click to expand commit body
All four packages used "*" for their pi SDK and typebox peer
dependencies, which accepts any version including ones with breaking API
changes.

Pin to >=0.65.0 for the pi packages (pi-ai, pi-coding-agent, pi-tui)
since the current code relies on APIs introduced in that release
(session_start event, AgentToolResult.details, SessionManager.open). Pin
typebox to >=0.34.0 as the Type.Object/Array/String/Optional API is
stable across the 0.34.x line.

Amolith created

1830f58 answer: Split into focused modules

Click to expand commit body
Break the 776-line single file into four modules along natural
boundaries:

- prompt.ts: extraction system prompt, few-shot examples, tool schema,
and shared types (ExtractedQuestion, ExtractionResult)
- extract.ts: model resolution, tool call parsing, XML escaping
- QnAComponent.ts: full interactive TUI component
- index.ts: command/shortcut registration and extraction orchestration

No behavioral changes.

Amolith created

12ee4a2 handoff: Split into focused modules

Click to expand commit body
Break the 905-line single file into six modules along natural
boundaries:

- session-paths.ts: path utilities (getSessionsRoot,
getFallbackSessionsRoot, normalizeSessionPath, sessionPathAllowed)
- session-analysis.ts: extractCandidateFiles, extractLoadedSkills,
resolveExtractionModel
- handoff-extraction.ts: extraction prompts, tool schema,
extractHandoffContext, assembleHandoffDraft
- session-query-tool.ts: session_query tool registration
- handoff-tool.ts: handoff tool registration
- handoff-command.ts: /handoff command registration
- index.ts: wiring, event handlers, shared state, countdown logic

No behavioral changes. Each module has a narrow interface with the rest
of the system — shared state is threaded through callbacks rather than
module-level globals.

Amolith created

48b9d1d answer: Escape XML and guard abort race

Click to expand commit body
Escape <, >, and & in question text, user answers, and notes before
embedding them in pseudo-XML tags. Without this, literal angle brackets
in content could confuse model parsing of the <qna> block.

Wrap the done() callback in a finished-flag guard so only the first
completion takes effect. The loader.onAbort handler and the in-flight
extraction promise could both call done() on user cancellation,
producing a double-completion race.

Amolith created

f83b5aa handoff: Fix session_query signal and path checks

Click to expand commit body
The signal guard `if (!signal || signal.aborted)` treated a missing
signal as cancelled, preventing session_query from running when the SDK
passes no AbortSignal. Change to `if (signal?.aborted)` so only an
actually-aborted signal triggers cancellation.

sessionPathAllowed() returned true when sessionsRoot was undefined,
allowing any absolute path to pass validation. Flip the default to false
so queries fail closed when the sessions root cannot be determined.

Amolith created

a099639 questionnaire: Guard empty options and dedup IDs

Click to expand commit body
When a question has no options and allowOther is false, the opts array
is empty but optionIndex is 0. Accessing opts[0].isOther crashes with a
TypeError on undefined. Add an early return when the selected option
does not exist.

Deduplicate question IDs at normalization time by appending _2, _3, etc.
to collisions. Duplicate IDs caused answer map overwrites where only the
last answer for a given ID survived.

Amolith created

b7bb81c personality: Harden filesystem ops

Click to expand commit body
Wrap all filesystem calls (readdirSync, readFileSync, writeFileSync,
unlinkSync) in try/catch with graceful fallbacks — return empty/null
instead of crashing the extension.

Validate the persisted personality name against listPersonalities()
before loading it. A tampered persistence file containing a path like
../../etc/something would previously be passed straight to readFileSync;
now it is rejected if not in the available list.

Amolith created

e3b6594 personality: Lock system prompt at session start

Click to expand commit body
The old code injected a system-reminder custom message every turn after
the first, creating a persisted entry in the session file each time.
Long conversations accumulated dozens of personality blobs, wasting
tokens and cluttering session history.

Lock the personality into the system prompt at session start via the
ephemeral systemPrompt return from before_agent_start (never persisted,
same content each turn so provider cache stays valid). Mid-session
switches queue a single one-shot message instead of touching the system
prompt — once a conversation exists, its system prompt is immutable.

Amolith created

6ec6c7f Update biome schema to match CLI 2.4.10

Click to expand commit body
The $schema URL was pinned to 2.0.0 while the installed biome is 2.4.10,
producing an info diagnostic on every lint run.

Amolith created

8a8ae32 handoff: Align types with pi SDK 0.65.0

Click to expand commit body
Fix ~15 type errors and 3 noExplicitAny lint warnings caused by SDK API
drift in the handoff extension.

- Replace session_switch/session_fork events with session_start (the
old events no longer exist in the SDK); use event.reason to distinguish
switch, resume, and fork
- Cast sessionManager to SessionManager instead of any for newSession()
- Type the context event handler properly instead of casting to any
- Change label from dynamic function to static string
- Add details property to all AgentToolResult returns
- Guard signal-possibly-undefined with optional chaining
- Accept string | undefined for apiKey in extractHandoffContext
- Handle getSessionFile() returning undefined in command handler
- Fix race condition: call newSession() before setting
handoffTimestamp so session_start clears stale values first

Amolith created

bdcf05f handoff: Fix lint in file-pattern extraction

Click to expand commit body
- Remove useless regex escape on closing paren
- Replace while/exec loop with for/matchAll to avoid assignment in
expression and implicit-any let
- Change trailing boundary group from consuming to lookahead so
adjacent files separated by a single space are no longer skipped

Amolith created

dbb71a1 answer: Fix types, lint, and dead code

Click to expand commit body
- Align EditorTheme.selectList with current SelectListTheme API
(selectedPrefix, selectedText, description, scrollInfo, noMatch)
- Replace non-null assertions on ctx.model and lastAssistantText with
captured locals after the early-return guards so closures see narrowed
types
- Add explicit fallback parameter to resolveExtractionModel instead
of asserting ctx.model inside the function
- Convert remaining string concatenations to template literals
- Remove unused private allQuestionsAnswered method

Amolith created

bcf6d2d personality: Use template literal

Click to expand commit body
Replace string concatenation with a template literal to satisfy the
biome useTemplate lint rule.

Amolith created

e8948f0 Remove redundant session query mention

Click to expand commit body
The session-query.ts link already credits the source; no need to list it
again as a change.

Amolith created

5c75985 Use NPM badges instead of linked headers

Click to expand commit body
Code inside markdown headings can't be linked, so replace the linked
header style with plain code headings and shields.io NPM version badges
underneath.

Amolith created

a6cefc4 Add top-level AGENTS.md

Click to expand commit body
Non-discoverable repo conventions: commands, REUSE licensing
requirements, and VCS/commit style expectations.

Amolith created

8af865f Add personality extension

Click to expand commit body
Switchable agent personalities stored as markdown files, injected into
the system prompt. Includes a /personality command for interactive
switching and persistence across sessions.

Licensed under the Unlicense.

Amolith created

a7c1d5f Add questionnaire extension

Click to expand commit body
Multi-question interactive prompts with tab-based navigation, from Mario
Zechner's pi-mono examples. Changes from upstream:

- Added a free-text notes editor (press 'n') available on any tab
- Custom answers and notes are sent as a steering user message so
the model sees them as user content, not just tool results
- Added word wrapping for long question prompts via wrapTextWithAnsi
- Updated tool description to mention the notes feature

Licensed MIT per the upstream.

Amolith created

47f0a7b Add answer extension

Click to expand commit body
Interactive Q&A extraction from assistant responses with a custom TUI
for navigating and answering questions. Based on Armin Ronacher's answer
extension from agent-stuff, with several changes:

- Replaced responseFormat-based extraction with a structured
tool call (extract_questions), which models handle more reliably
- Rewrote the system prompt with detailed few-shot examples
including deduplication and standalone-question rules
- Changed model selection to prefer nemotron-3-super-120b-a12b
instead of codex-mini/haiku
- Added a notes editor (Alt+N) for attaching free-text context
alongside answers
- Added fallback extraction with current model when the preferred
model fails

Licensed Apache-2.0 per the upstream.

Amolith created

c02a009 Add handoff extension

Click to expand commit body
Context-preserving session handoff with LLM-based extraction of relevant
files, skills, and open items. Derived from Petr Baudis' pi-amplike
handoff and session-query extensions, substantially reworked with
structured tool-call extraction, auto-submit countdown, and an
integrated session query tool.

Licensed MIT per the upstream.

Amolith created

d5bb747 Add monorepo scaffold with tooling and REUSE

Click to expand commit body
Bun workspaces monorepo for Pi extensions published under the @amolith
npm scope. Includes:

- Biome for linting and formatting (tabs, double quotes, 120-col)
- TypeScript for type checking (noEmit only, Pi loads .ts via jiti)
- mise tasks as thin wrappers around bun run scripts
- REUSE 3.3 compliance with per-file SPDX headers
- CC0-1.0 for ancillary files, code licenses per-package

Amolith created