@mariozechner/pi-coding-agent is deprecated in favor of @earendil-works/pi-coding-agent (github.com/earendil-works/pi). Import Type from @earendil-works/pi-ai instead of @sinclair/typebox, which the new ecosystem replaces with plain typebox. Upgrading to 0.80.6 also resolves all 31 open Dependabot alerts from the old package's transitive dev dependencies.
81 lines
4.0 KiB
Markdown
81 lines
4.0 KiB
Markdown
# pi-perplexity
|
|
|
|
## Stack
|
|
|
|
- TypeScript extension for `@earendil-works/pi-coding-agent`; loaded directly via jiti, no build artifact.
|
|
- Node >=18.14.1 runtime APIs only: `fetch`, `crypto.randomUUID()`, `Buffer.from(..., "base64url")`, `Intl`.
|
|
- Pi-bundled packages live in `peerDependencies` with `"*"`: `@earendil-works/pi-tui`, `@earendil-works/pi-ai`. `Type` is re-exported by `@earendil-works/pi-ai`; do not depend on `typebox` directly.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
npm run typecheck
|
|
npm test
|
|
node --no-deprecation --import ./node_modules/@earendil-works/pi-coding-agent/node_modules/jiti/lib/jiti-register.mjs --input-type=module -e "import('./src/index.ts').then((m)=>{ const entry = m.default?.default ?? m.default; if (typeof entry !== 'function') throw new Error('default export missing'); })"
|
|
```
|
|
|
|
## File-Scoped Commands
|
|
|
|
| Task | Command |
|
|
|------|---------|
|
|
| Single test file | `npm run test:build && node --test --experimental-test-module-mocks ".tmp-test/test/search/stream.test.js"` |
|
|
| Live E2E opt-in | `PI_PERPLEXITY_E2E=1 npm test` |
|
|
|
|
## Structure
|
|
|
|
- `src/index.ts` — extension entry and `perplexity_search` tool definition.
|
|
- `src/auth/` — JWT extraction, email OTP login, token storage.
|
|
- `src/search/` — Perplexity SSE request, stream merge, result formatting, models.
|
|
- `src/render/` — TUI renderers for tool calls and results.
|
|
- `src/commands/` — slash commands such as login/config.
|
|
- `test/` — automated Node test suite; `.tmp-test/` is generated by `npm run test:build`.
|
|
- `local_tests/` — manual/debug scripts and captured dumps; do not treat as automated coverage.
|
|
- `docs/design-decisions.md` — rationale for non-obvious behavior.
|
|
|
|
## Extension Conventions
|
|
|
|
- Entry point exports a default factory from `src/index.ts`.
|
|
- Tool name is `perplexity_search`.
|
|
- Tool `execute` signature is `(toolCallId, params, signal, onUpdate, ctx)`.
|
|
- Tool results use `{ content: [{ type: "text", text }], details: { ... } }`.
|
|
- String enum params use `StringEnum` from `@earendil-works/pi-ai`; `Type.Union([Type.Literal(...)])` breaks Google models.
|
|
- Stream/API types stay loose: all reverse-engineered event fields are optional.
|
|
|
|
## Perplexity Protocol Gotchas
|
|
|
|
- Endpoint: `POST https://www.perplexity.ai/rest/sse/perplexity_ask`.
|
|
- Required Perplexity constants live in `src/constants.ts`.
|
|
- Searches default to `is_incognito: true` to avoid polluting user history.
|
|
- The response is `data:` JSON lines with `[DONE]`, not a fully standard SSE stream.
|
|
- Events are incremental snapshots: shallow-merge top level, merge blocks by `intended_usage`, splice markdown via `chunk_starting_offset`, accumulate sources.
|
|
- Completion is `event.final === true` or `event.status === "COMPLETED"`.
|
|
- Answer extraction order: markdown blocks → `ask_text` blocks → event text.
|
|
- Source extraction order: `web_results` block → `sources_list`; deduplicate by URL.
|
|
|
|
## Auth Gotchas
|
|
|
|
- Auth tries macOS app token first via `defaults read ai.perplexity.mac authToken`, unless `PI_AUTH_NO_BORROW=1`.
|
|
- Email OTP fallback uses `ctx.ui.input()`.
|
|
- Tokens are stored at `~/.config/pi-perplexity/auth.json` with mode `0600`.
|
|
- Stored tokens have no expiry tracking; `loadToken()` returns any cached token and expiry surfaces as 401/403 at request time.
|
|
- AUTH errors preserve the cached token; users explicitly clear/re-auth with `/perplexity-login --force`.
|
|
|
|
## Boundaries
|
|
|
|
### Always
|
|
|
|
- Pass `AbortSignal` through to network calls.
|
|
- Return user-readable error text from tool execution instead of throwing raw errors.
|
|
- Keep runtime dependency-free; use platform APIs for HTTP, SSE parsing, JWT decoding, and UUIDs.
|
|
|
|
### Ask First
|
|
|
|
- Changing Perplexity request headers, model IDs, or auth flow behavior.
|
|
- Adding package dependencies or generated build artifacts.
|
|
- Deleting captured local test dumps or token-related files.
|
|
|
|
### Never
|
|
|
|
- Never commit secrets, credentials, `.env`, cached auth tokens, or live Perplexity response dumps containing private data.
|
|
- Never clear cached auth automatically on transient 401/403 responses.
|