Java/Spring implementation inspired by open-source pi-mono (TypeScript).
Goal: help Java teams adopt pi-mono ideas without TypeScript barriers.
Many teams run Java/Spring in production but want pi-mono’s lightweight agent loop, session model, and tool orchestration.
本项目聚焦“技术服务业务”:
- 为 Java/Spring 项目提供可落地的 pi-mono 风格实现;
- 降低 TS 语言门槛带来的学习和接入成本;
- 给自研 Agent / LangGraph / 对话平台提供可参考的工程实现(即使不直接使用本项目)。
- Spring Boot starter (
pi-starter) for low-friction integration. - Typed core abstractions (
LLMProvider,ChatRequest,SessionNode). - Session tree + JSONL persistence for reproducible conversation traces.
- Built-in tool framework with permission boundaries (
read/write/system).
- A compact reference of runtime concerns:
- model routing + fallback,
- session persistence,
- tool invocation controls,
- starter-based embedding into business apps.
- Can be used as architecture reference even if you keep your own runtime.
Reference upstream: earendil-works/pi
Latest checked release: v0.80.3 (2026-06-30).
Latest checked main branch also includes post-release coding-agent/AI fixes through 2026-07-06 such as OpenAI Responses max-output-token floor clamping, Cloudflare 524 retry classification, OpenAI Codex WebSocket connection rotation, DS4 context-overflow detection, split-turn compaction summary serialization, delayed Copilot device-code token polling, entry renderers, short session entry ids from generated id random tails, model metadata cleanup, stricter bash timeout validation, sequential question-tool execution metadata, Bedrock Claude 5 prompt caching, and Codex SSE transport updates.
| Area | Upstream TS (pi-mono) |
This Java repo | Alignment |
|---|---|---|---|
| Core model/provider abstraction | packages/ai, packages/agent |
pi-core, pi-llm (gpt-5.5 default, model-resolution helpers, request-scoped OpenAI/Anthropic/Bedrock auth/options, Azure Foundry endpoint normalization, HTTP error response bodies, retryable provider errors, GitHub Copilot OAuth device-flow client foundation, OAuth device-code polling interval handling, OpenAI output-token floor clamping, OpenAI-compatible HTTP 524 retry classification, OpenAI-compatible DS4 context-overflow classification, OpenAI image_url, Anthropic image, and Bedrock image attachment content parts, OpenAI/Anthropic/Bedrock non-streaming tool-use metadata and provider-native tool-result blocks, Anthropic/Bedrock thinking content metadata, Anthropic Messages API with Claude 5 thinking, Anthropic-compatible + Bedrock Claude Sonnet 5 catalogs and SigV4-signed non-streaming Bedrock invoke payloads) |
Partially aligned |
| Session tree + JSONL persistence | packages/agent session storage, reasoning usage metadata, invalid-session overwrite protection, session_info_changed notification, split-turn compaction summary serialization |
pi-session (restore/resume/fork/import/export, nested usage/reasoning token metadata, invalid non-empty JSONL overwrite protection, deterministic startup session ids, rename metadata event source, bounded non-streaming tool result continuation, serialized split-turn summary orchestration) |
Mostly aligned for Java use |
| Tool runtime | built-in read/write/edit/bash/grep/find/ls, BMP image handling |
pi-tools (read/write/edit/bash/find/grep/ls, BMP-to-PNG payloads in read, strict 1-60s bash timeout validation, sequential executionMode tool metadata, session-level multi-round tool-call execution into TOOL_RESULT) |
Partially aligned |
| CLI agent workflow | packages/coding-agent |
pi-cli (--no-session, --session-id, @file attachment expansion, improved session/model/resource commands) |
Partially aligned |
| Context files, prompts, skills | coding-agent resource loader |
pi-cli (AGENTS.md/CLAUDE.md, .pi/prompts, .pi/skills, .agents/skills, prompt expansion, basic /skill:name) |
Partially aligned |
| CLI settings | settings.json (outputPad, externalEditor) |
pi-cli (outputPad for user/assistant/thinking lines, /edit via configured externalEditor) |
Partially aligned |
| Project trust | coding-agent trust manager |
pi-cli (/trust, trust-aware local resource loading) |
Partially aligned |
| RPC session inspection | rpc-entry, get_entries, get_tree, entry renderers, tail-derived short entry ids |
pi-cli --rpc JSONL (get_entries, get_tree, rendered entry summaries, shortId from full-id random tails) |
Minimally aligned |
| TUI / extension / package ecosystem | packages/tui, coding-agent extensions, themes, packages |
documented gap | Not aligned yet |
Detailed notes: docs/capability-comparison.md
- Better fit for Spring-centric production systems.
- Strong static typing and mature enterprise ops ecosystem.
- Easier embedding into existing Java services.
- Faster upstream feature evolution.
- Richer existing UX/tooling in original project.
- Better choice if your stack is already Node.js-first.
# 1) Build
mvn clean compile
# 2) Session restore/resume/fork tests
mvn -pl pi-session -am test -Dtest=SessionPersistenceUnitTest
# 3) Spring integration smoke test
cd spring-test-example
mvn spring-boot:run
# Expect: "所有Spring集成测试通过!"
# 4) CLI smoke test (optional)
cd ..
printf "help\n/session\n/models\n/resources\nexit\n" | mvn -pl pi-cli -DskipTests exec:javaQuickstart docs:
- 中文: docs/quickstart.zh-CN.md
- English: docs/quickstart.en.md
- Bilingual entry docs (README + Quickstart CN/EN)
- Fast verification path (
compile+spring-test-example) - Capability alignment snapshot vs upstream TS pi-mono
- Evidence section with runnable commands and sample results
- Reproducible smoke benchmark script and result template
- More comprehensive benchmark suite (cross-machine, cross-JDK, repeated runs)
- Remove
System.exit(0)from test sample runner and stabilizemvn test - Restore saved JSONL sessions and expose resume/tree/fork/import/export CLI commands
- Preserve nested usage metadata such as
usage.reasoningTokensacross JSONL save/load - Serialize split-turn compaction summary requests so single-concurrency providers are not called concurrently
- Support deterministic startup session ids with
--session-idand ephemeral runs with--no-session - Reject overwriting non-empty invalid JSONL session files
- Discover context files, prompt templates, and skills in the CLI startup path
- Gate project-local prompt/skill resources behind a
/trustdecision - Expand trusted prompt templates and inject basic
/skill:nameinstructions into CLI conversations - Expose minimal
--rpcJSONL session inspection forget_entriesandget_tree - Include rendered titles/plain-text/Markdown summaries in RPC
get_entriesoutput - Expose tail-derived
shortIdfields in RPC session entries and tree nodes - Resolve preferred LLM providers by model id and skip unavailable defaults
- Expose model-resolution helpers for available model catalogs and exact model-to-provider lookup
- Add OAuth device-code polling helper and a minimal GitHub Copilot device-flow client that delay the first token poll and honor server-provided
slow_downintervals - Align OpenAI default model to
gpt-5.5and normalize Azure Foundry/OpenAI base URLs - Honor request-scoped OpenAI API key,
OPENAI_API_KEYenv override, model, temperature, and max-token options - Parse OpenAI token usage metadata including reasoning tokens
- Preserve provider HTTP response bodies in OpenAI error messages
- Retry OpenAI provider errors whose response body explicitly asks callers to retry
- Retry OpenAI-compatible HTTP 524 timeout responses
- Clamp OpenAI request output tokens below the provider minimum to 16
- Classify OpenAI-compatible DS4 context-overflow errors from provider response bodies
- Surface incomplete OpenAI responses when output stops at the token limit
- Convert CLI image attachments into OpenAI non-streaming
image_urlcontent parts - Send OpenAI non-streaming tool schemas and parse
tool_callsinto assistant message metadata - Add Anthropic-compatible Claude Sonnet 5 provider catalog entry
- Send non-streaming Anthropic Messages API requests with Claude Sonnet 5 thinking payloads and parse text/usage/thinking responses
- Honor request-scoped Anthropic API key and
ANTHROPIC_API_KEYenv override - Convert CLI image attachments into Anthropic non-streaming image content blocks
- Send Anthropic non-streaming tool schemas and parse
tool_useblocks into assistant message metadata - Mark exported Java tool schemas with sequential
executionMode - Execute non-streaming provider
toolCallsthrough Java tools, append provider-nativeTOOL_RESULTpayloads, and continue bounded multi-round provider turns - Send SigV4-signed non-streaming Bedrock Anthropic invoke requests, including Claude Sonnet 5 thinking and prompt-cache payload blocks, and parse text/usage/thinking responses
- Convert CLI image attachments into Bedrock non-streaming image content blocks
- Send Bedrock non-streaming tool schemas and parse
tool_useblocks into assistant message metadata - Resolve Bedrock credentials from explicit properties, a selected AWS shared credentials profile, or AWS environment variables
- Honor request-scoped Bedrock AWS env credentials (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, optionalAWS_SESSION_TOKEN) or scoped profile credentials (AWS_PROFILE, optionalAWS_SHARED_CREDENTIALS_FILE) for SigV4 signing - Load CLI
settings.json, applyoutputPadto user/assistant/thinking lines, and compose with configuredexternalEditorthrough/edit - Emit Java-side
session_info_changedmetadata events on session rename - Reject non-positive and oversized bash timeouts instead of silently clamping
- Detect BMP files in
readand convert them to PNG data URLs - Expand CLI
@filereferences into attached file blocks before sending messages
Latest local verification sample:
mvn -pl pi-session -am test -Dtest=SessionPersistenceUnitTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (session save/restore/load/fork, nested usage/reasoning token metadata, invalid non-empty session overwrite protection, deterministic session id,session_info_changedrename event, sequential toolexecutionModemetadata, and bounded multi-round non-streaming tool-call execution/TOOL_RESULTcontinuation tests).mvn -pl pi-session -am test -Dtest=SessionCompactionServiceTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (split-turn compaction summary requests are serialized before merging history and turn-prefix summaries).mvn -pl pi-tools -am test -Dtest=BashToolTest,ReadFileToolTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (bash timeout validation and BMP-to-PNGreadtests).mvn -pl pi-cli -am test -Dtest=PiResourceLoaderTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (resource discovery tests).mvn -pl pi-cli -am test -Dtest=PiTrustManagerTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (project trust tests).mvn -pl pi-cli -am test -Dtest=PiResourceCommandResolverTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (prompt template and basic skill invocation tests).mvn -pl pi-cli -am test -Dtest=PiFileReferenceResolverTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (CLI@fileattachment expansion, including BMP-to-PNG payloads).mvn -pl pi-cli -am test -Dtest=PiRpcCommandHandlerTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (minimal RPCget_entries/get_treetests, including rendered entry summaries and tail-derivedshortIdfields).mvn -pl pi-cli -am test -Dtest=PiCliStartupOptionsTest,PiCliSettingsLoaderTest,PiCliOutputFormatterTest,PiExternalEditorTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (CLI startup args, settings loading, user/assistant/thinking output padding, and external editor command runner tests).mvn -pl pi-llm -am test -Dtest=GitHubCopilotOAuthClientTest,OAuthDeviceCodePollerTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (GitHub Copilot OAuth device-flow startup, delayed first token poll, RFC +5sslow_down, and server-providedslow_downinterval handling through a deterministic fake transport).mvn -pl pi-llm -am test -Dtest=LLMProviderManagerTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (model-id provider resolution, unavailable default-provider skip, available model catalog, and exact model-to-provider helper tests).mvn -pl pi-llm -am test -Dtest=OpenAIClientTest,OpenAIConfigTest,OpenAILLMProviderTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (OpenAI HTTP error body, retryable provider errors, HTTP 524 timeout retry classification, DS4 context-overflow classification, request output-token floor clamping, default model, request-scoped API key/env/model/options, Azure Foundry endpoint, response content parsing, usage/reasoning token metadata, incomplete output-length response, OpenAI image attachment content parts, non-streaming tool schema request, andtool_callsmetadata parsing tests).mvn -pl pi-llm -am test -Dtest=AnthropicClientTest,AnthropicConfigTest,AnthropicLLMProviderTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (Anthropic-compatible Claude Sonnet 5 catalog, request-scoped API key/env auth, Messages API request headers/body, Claude 5 thinking payload, image attachment content blocks, non-streaming tool schema request without internal execution metadata leakage,tool_usemetadata parsing, provider-nativetool_resultcontent blocks, HTTP error body, response content, thinking content, and usage metadata tests).mvn -pl pi-llm -am test -Dtest=BedrockClientTest,BedrockConfigTest,BedrockLLMProviderTest -Dsurefire.failIfNoSpecifiedTests=false -Djava.version=17: pass (Bedrock Claude Sonnet 5 catalog, SigV4 signing from explicit, shared-profile, environment, request-scoped AWS credentials, or request-scoped AWS profile credentials, non-streaming invoke payload, Claude 5 thinking payload, prompt-cache block, image attachment content blocks, non-streaming tool schema request without internal execution metadata leakage,tool_usemetadata parsing, provider-nativetool_resultcontent blocks, HTTP error body, response content, thinking content, usage, and region metadata tests).printf "help\n/resources\n/prompts\n/skills\n/session\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 exec:java: pass (resource command smoke).printf "help\n/resources\n/trust\n/resources\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 -Dpi.trust.file=target/trust-smoke.txt exec:java: pass (trust command smoke).- From
target/pi-cli-resource-smokewith a local.pi/prompts/review.mdand.pi/skills/deploy/SKILL.mdfixture,printf "/resources\n/trust\n/prompts\n/skills\n/review target=api focus=security\n/skill:deploy release service\nexit\n" | mvn -f ../../pom.xml -pl pi-cli -DskipTests -Djava.version=17 -Dpi.trust.file=trust-final.txt exec:java: pass (trusted prompt/skill command smoke). - From
target/pi-cli-settings-smokewith a local.pi/settings.jsonfixture,printf "/settings\n/trust\n/settings\nhello settings\nexit\n" | mvn -f ../../pom.xml -pl pi-cli -DskipTests -Djava.version=17 -Dpi.trust.file=trust-settings.txt exec:java: pass (trusted settings andoutputPadsmoke). - From
target/pi-cli-edit-smokewith a fake external editor script in trusted.pi/settings.json,printf "/trust\n/edit\nexit\n" | mvn -f ../../pom.xml -pl pi-cli -DskipTests -Djava.version=17 -Dpi.trust.file=trust-edit.txt exec:java: pass after installing updated local snapshots (/editsends the editor-written message). printf '{"id":1,"method":"get_tree"}\n' | mvn -pl pi-cli -DskipTests -Djava.version=17 -Dexec.args=--rpc exec:java: pass (minimal JSONL RPC tree smoke).printf "/session\n/save\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 -Dexec.args="--no-session --session-id stable-cache-id" exec:java: pass after installing updated local snapshots (deterministic ephemeral startup session id and disabled persistence smoke).printf "/rename Roadmap Review\n/session\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 exec:java: pass after installing updated local snapshots (CLI rename emitssession_info_changedand shows the session name).printf "/models\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 -Dpi.llm.anthropic.enabled=true -Dpi.llm.anthropic.api-key=test-key exec:java: pass after installing updatedpi-core/pi-llmartifacts (Anthropic-compatible catalog smoke).printf "/models\nexit\n" | mvn -pl pi-cli -DskipTests -Djava.version=17 -Dpi.llm.bedrock.enabled=true -Dpi.llm.bedrock.region=us-west-2 exec:java: pass after installing updatedpi-core/pi-llmartifacts (Bedrock catalog smoke).
Bedrock runtime credential notes:
- Explicit Spring properties:
pi.llm.bedrock.access-key-id,pi.llm.bedrock.secret-access-key, and optionalpi.llm.bedrock.session-token. - Shared profile fallback:
pi.llm.bedrock.profileorAWS_PROFILE, withpi.llm.bedrock.credentials-fileorAWS_SHARED_CREDENTIALS_FILE; otherwise~/.aws/credentials. - Environment fallback:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionalAWS_SESSION_TOKEN. - Per-request
ChatOptions.env()override: eitherAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionalAWS_SESSION_TOKEN; orAWS_PROFILEwith optionalAWS_SHARED_CREDENTIALS_FILE. - Do not commit real AWS keys; use environment or secret-managed configuration for real runtime calls.
mvn -f spring-test-example/pom.xml spring-boot:run: pass.- Spring sample startup log:
Started SpringTestApplication in 0.661 seconds(single-machine sample, non-benchmark-lab). - Reproducible smoke benchmark:
./scripts/benchmark_smoke.sh- result template:
benchmarks/RESULTS_TEMPLATE.md - latest sample report:
benchmarks/benchmark-latest.md
- result template:
Known testing caveat:
- This repo targets Java 21+. If the local machine only has JDK 17, use
-Djava.version=17only as a compatibility smoke check, not as the canonical release gate. - On JDK 24+, you may still see Mockito attach warnings in test logs.
spring-test-exampletest resources already force a non-inline mock maker to keepmvn testrunnable.
pi-core/ core contracts and models
pi-llm/ provider implementations and routing
pi-session/ session tree and persistence
pi-tools/ tool definitions and permissions
pi-cli/ CLI entrypoint
pi-starter/ Spring Boot auto-configuration
example-project/ sample integration app
spring-test-example/ quick verification app
MIT