fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
prime-agent AGENTS.md
16 kB
Markdown
at main

Development Rules #

Conversational Style #

  • No fluff or cheerful filler text
  • Keep answers short and concise
  • No emojis in commits, issues, PR comments, or code
  • Technical prose only, be kind but direct (e.g., "Thanks @user" not "Thanks so much @user!")

Code Quality #

  • Read files in full before making wide-ranging changes, before editing files you have not already fully inspected, and when the user asks you to investigate or audit something. Do not rely only on search snippets for broad changes.
  • Don't be too verbose with comments in the code. Only write comments when there is serious ambiguity
  • No any types unless absolutely necessary
  • Check node_modules for external API type definitions instead of guessing
  • NEVER use inline imports - no await import("./foo.js"), no import("pkg").Type in type positions, no dynamic imports for types. Always use standard top-level imports.
  • NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead
  • Always ask before removing functionality or code that appears to be intentional
  • Do not preserve backward compatibility unless the user explicitly asks for it
  • Never hardcode key checks with, eg. matchesKey(keyData, "ctrl+x"). All keybindings must be configurable. Add default to matching object (DEFAULT_EDITOR_KEYBINDINGS or DEFAULT_APP_KEYBINDINGS)
  • NEVER modify packages/ai/src/models.generated.ts directly. Update packages/ai/scripts/generate-models.ts instead.

Commands #

  • After code changes (not documentation changes): npm run check (get full output, no tail). Fix all errors, warnings, and infos before committing.
  • Note: npm run check does not run tests.
  • NEVER run: npm run dev, npm run build, npm test
  • Only run specific tests if user instructs: npx tsx ../../node_modules/vitest/dist/cli.js --run test/specific.test.ts
  • Run tests from the package root, not the repo root.
  • If you create or modify a test file, you MUST run that test file and iterate until it passes.
  • When writing tests, run them, identify issues in either the test or implementation, and iterate until fixed.
  • For packages/coding-agent/test/suite/, use test/suite/harness.ts plus the faux provider. Do not use real provider APIs, real API keys, or paid tokens.

Testing Policy #

  • npm run check:test-policy is required. Never weaken it or add a broad exclusion. A platform exception must use // test-policy: allow <rule> -- <specific reason> immediately above one expression, and CI must run that test on a supported platform.
  • A test must fail when the behavior it covers is broken. Temporarily revert or stub the production behavior to prove the failure. If the test still passes, delete it.
  • Test observable behavior at process boundaries, durable formats, concurrency/ordering, crash recovery, and load. Do not assert a mock's own return value, private implementation steps, or exact rendered copy unless that text is a protocol contract.
  • CI tests must be unconditional and self-contained. Do not use live provider APIs, real credentials, paid tokens, .skip, .skipIf, .runIf, .todo, .only, environment-gated early returns, or optional assertions. Put manual live-provider probes outside the CI test suite.
  • Never use runner retries or retry-to-green wrappers. Every failed attempt counts as a failure. Fix the race or delete the test.
  • Never use a fixed sleep, real-time delay, polling loop, or larger timeout as a readiness signal. Await a concrete event or deferred promise, use a fake clock, or expose the missing completion signal. A timer may only bound failure; it must not make the test pass.
  • Tests using subprocesses, sockets, concurrency, or shared process state must bind port 0, use unique temporary paths, restore environment/cwd/globals/fake timers, and close every resource in finally.
  • Run every modified test file directly. For concurrency, process, timer, or ordering changes, also run the focused suite repeatedly with multiple shuffle seeds. Stop on the first failure; repeated runs are evidence, never retries.
  • A change may not add more lines of test than source. A test-only change must delete at least as many test lines as it adds.
  • Regressions go in the existing suite for the module that broke, with the issue number in the test name. Never create one file per issue. One test file per source module; repeated cases belong in an it.each table.
  • Deleting code deletes its tests. A flaky test is made deterministic or deleted, never skipped or retried.

Daemon Protocol Changes #

  • Classify every daemon command, event, and response-shape change as backward-compatible, capability-gated, or incompatible.
  • Add optional features behind a negotiated server capability. Clients must check the capability before sending the command or depending on the event.
  • Bump DAEMON_PROTOCOL_VERSION for incompatible changes or when startup begins requiring behavior an older daemon cannot provide.
  • Update DAEMON_SCHEMA_REVISION, the command/event compatibility maps, and both new-client/old-daemon and old-client/new-daemon tests for every wire change.
  • Optional daemon metadata and UI features must degrade locally. They must not prevent the agent, session attachment, or interactive startup from working.
  • Never make a new daemon command part of startup without a protocol or capability gate.

GitHub Workflow #

When creating issues:

  • Add pkg:* labels to indicate which package(s) the issue affects
    • Available labels: pkg:agent, pkg:ai, pkg:coding-agent, pkg:tui
  • If an issue spans multiple packages, add all relevant labels

When posting issue/PR comments:

  • Write the full comment to a temp file and use gh issue comment --body-file or gh pr comment --body-file
  • Never pass multi-line markdown directly via --body in shell commands
  • Preview the exact comment text before posting
  • Post exactly one final comment unless the user explicitly asks for multiple comments
  • If a comment is malformed, delete it immediately, then post one corrected comment
  • Keep comments concise, technical, and in the user's tone

When closing issues via commit:

  • Include fixes #<number> or closes #<number> in the commit message
  • This automatically closes the issue when the commit is merged

PR Workflow #

  • Analyze PRs without pulling locally first
  • If the user approves: create a feature branch, pull PR, rebase on main, apply adjustments, commit, merge into main, push, close PR, and leave a comment in the user's tone
  • We work in feature branches until everything is according to the user's requirements. Never merge PRs by yourself.

Testing Prime Agent Interactive Mode with tmux #

To test Prime Agent's TUI in a controlled terminal environment:

# Create tmux session with specific dimensions
tmux new-session -d -s prime-agent-test -x 80 -y 24

# Start Prime Agent from source
tmux send-keys -t prime-agent-test "cd /Users/kevin/pi/prime-agent && ./prime-agent.sh" Enter

# Wait for startup, then capture output
sleep 3 && tmux capture-pane -t prime-agent-test -p

# Send input
tmux send-keys -t prime-agent-test "your prompt here" Enter

# Send special keys
tmux send-keys -t prime-agent-test Escape
tmux send-keys -t prime-agent-test C-o  # ctrl+o

# Cleanup
tmux kill-session -t prime-agent-test

You, yourself, are often running into a tmux session, so be careful when killing tmux sessions. Lots of other processes can be running on different tmux sessions/

Changelog #

Location: packages/<pkg>/.changes/<slug>.md (one fragment file per PR per touched package)

Format #

Do NOT edit packages/*/CHANGELOG.md directly. Instead, add a fragment file packages/<pkg>/.changes/<slug>.md (slug = kebab-case, branch- or ticket-derived, e.g. eng-1234-fix-resize.md) containing exactly the bullet line(s) for the change. Bullets are plain - ... lines with no ### Added / ### Changed / ### Fixed / ### Removed subsections — one bullet per change, written as a short sentence starting with a past-tense verb (Added, Changed, Fixed, Removed). Keep each bullet to one line; describe the user-visible change, not the implementation. The release script folds fragments into the release section of CHANGELOG.md and deletes them.

Example fragment (packages/coding-agent/.changes/eng-1234-effort-command.md):

- Added `/effort` to set the reasoning level, with autocomplete for the levels the current model supports.

Rules #

  • One fragment file per PR per touched package; a fragment may contain multiple bullets
  • NEVER modify already-released version sections in CHANGELOG.md (e.g., ## [0.2.1]) — each is immutable once released
  • Purely internal changes may opt out via the no-changelog PR label

Attribution #

  • Internal changes (from issues): Fixed foo bar ([#123](https://github.com/PrimeIntellect-ai/prime-agent/issues/123))
  • External contributions: Added feature X ([#456](https://github.com/PrimeIntellect-ai/prime-agent/pull/456) by [@username](https://github.com/username))

Adding a New LLM Provider (packages/ai) #

Adding a new provider requires changes across multiple files:

1. Core Types (packages/ai/src/types.ts) #

  • Add API identifier to Api type union (e.g., "bedrock-converse-stream")
  • Create options interface extending StreamOptions
  • Add mapping to ApiOptionsMap
  • Add provider name to KnownProvider type union

2. Provider Implementation (packages/ai/src/providers/) #

Create provider file exporting:

  • stream<Provider>() function returning AssistantMessageEventStream
  • streamSimple<Provider>() for SimpleStreamOptions mapping
  • Provider-specific options interface
  • Message/tool conversion functions
  • Response parsing emitting standardized events (text, tool_call, thinking, usage, stop)

3. Provider Exports and Lazy Registration #

  • Add a package subpath export in packages/ai/package.json pointing at ./dist/providers/<provider>.js
  • Add export type re-exports in packages/ai/src/index.ts for provider option types that should remain available from the root entry
  • Register the provider in packages/ai/src/providers/register-builtins.ts via lazy loader wrappers, do not statically import provider implementation modules there
  • Add credential detection in packages/ai/src/env-api-keys.ts

4. Model Generation (packages/ai/scripts/generate-models.ts) #

  • Add logic to fetch/parse models from provider source
  • Map to standardized Model interface

5. Tests (packages/ai/test/) #

  • Always add the provider to stream.test.ts with at least one representative model, even if it reuses an existing API implementation such as openai-completions.
  • Add the provider to the broader provider matrix where applicable: tokens.test.ts, abort.test.ts, empty.test.ts, context-overflow.test.ts, image-limits.test.ts, unicode-surrogate.test.ts, tool-call-without-result.test.ts, image-tool-result.test.ts, total-tokens.test.ts, cross-provider-handoff.test.ts.
  • For cross-provider-handoff.test.ts, add at least one provider/model pair. If the provider exposes multiple model families (for example GPT and Claude), add at least one pair per family.
  • For non-standard auth, create utility (e.g., bedrock-utils.ts) with credential detection.

6. Coding Agent (packages/coding-agent/) #

  • src/core/model-resolver.ts: Add default model ID to defaultModelPerProvider
  • src/core/provider-display-names.ts: Add API-key login display name so /login and related UI show the provider for built-in API-key auth.
  • src/cli/args.ts: Add env var documentation
  • README.md: Add provider setup instructions
  • docs/providers.md: Add setup instructions, env var, and auth.json key

7. Documentation #

  • packages/ai/README.md: Add to providers table, document options/auth, add env vars
  • packages/ai/.changes/<slug>.md: Add a changelog fragment (see Changelog above)

Releasing #

Lockstep versioning: All packages always share the same version number. Every release updates all packages together.

Version semantics (no major releases):

  • patch: Bug fixes and new features
  • minor: API breaking changes

Steps #

  1. Check fragments: Ensure all changes since last release have fragment files in packages/<pkg>/.changes/

  2. Run release script:

    npm run release:patch    # Fixes and additions
    npm run release:minor    # API breaking changes
    

The script handles: version bump, folding .changes/ fragments into the release section, commit, tag, and publish.

CRITICAL Git Rules for Parallel Agents CRITICAL #

Multiple agents may work on different files in the same worktree simultaneously. You MUST follow these rules:

Committing #

  • ONLY commit files YOU changed in THIS session
  • Always use the pre-imported Python git skill functions (git.status(), git.add(...), git.commit(...), git.log(...), git.diff(...)) instead of shelling out to bash
  • ALWAYS include fixes #<number> or closes #<number> in the commit message when there is a related issue or PR
  • NEVER use git.add_all() or git add . - these sweep up changes from other agents
  • ALWAYS pass specific file paths: git.add("path/to/file")
  • Before committing, run git.status() and verify you are only staging YOUR files
  • Track which files you created/modified/deleted during the session
  • It is always fine to include packages/ai/src/models.generated.ts in a commit alongside the actual files you want to commit

Forbidden Git Operations #

These commands can destroy other agents' work:

  • git reset --hard - destroys uncommitted changes
  • git checkout . - destroys uncommitted changes
  • git clean -fd - deletes untracked files
  • git stash - stashes ALL changes including other agents' work
  • git add -A / git add . - stages other agents' uncommitted work
  • git revert - never add a revert commit; drop the commit instead (see below)
  • git commit --no-verify - bypasses required checks and is never allowed

Rewriting Instead of Reverting #

This repository is dawn's fork (origin = knot.gaze.systems), so a commit that should not exist is dropped, never reverted. Never leave a Revert "..." commit in the history.

  • Drop commits from the tip: git reset --soft <target> moves the branch tip and leaves the index and worktree alone, so the tree you want is already staged; recommit it as one commit.
  • Replay the commits you keep onto a new base: git rebase --onto <new-base> <old-base>. It needs a clean worktree, so with other agents' uncommitted edits in the tree, prefer git reset --soft plus one commit.
  • Fetch first, then git push --force-with-lease. Only rewrite commits you are dropping yourself: never force-push over commits you did not author or that someone else pushed since your fetch.
  • The rewritten review is the tree, not the commit count: verify with git rev-parse <old>^{tree} <new>^{tree} that dropping commits changed no file.

Safe Workflow #

# 1. Check status first
git.status()

# 2. Add ONLY your specific files
git.add("packages/ai/src/providers/transform-messages.ts")
git.add("packages/ai/.changes/eng-1234-fix-resize.md")

# 3. Commit
git.commit("fix(ai): description")

# 4. Push (pull first if needed, but NEVER reset/checkout)
git.pull(rebase=True)
git.push()

If Rebase Conflicts Occur #

  • Resolve conflicts in YOUR files only
  • If conflict is in a file you didn't modify, abort and ask the user
  • NEVER force push over another agent's commits; --force-with-lease after a fetch is the only allowed rewrite of main