Merge remote-tracking branch 'public-gh/master'

* public-gh/master:
  Address PR feedback: keep testEnvironment non-destructive, warn on swallowed errors
  Apply suggestion from @greptile-apps[bot]
  Fix opencode-local adapter: parser, UI, CLI, and environment tests
  Rename Invoke button to Run Heartbeat for clarity
  fixing overhanging recommended text in onboarding
  Add Contributing guide
  feat(pi-local): fix bugs, add RPC mode, improve cost tracking and output handling
  fix(sidebar-badges): include approvals in inbox badge count
  feat: add Pi adapter support to constants and onboarding UI
  Adding support for pi-local
  ci: clarify fail-fast lockfile refresh behavior
  ci: remove unnecessary full-history checkout
  ci: fix pnpm lockfile policy checks
  ci: split workflows and move pnpm lockfile ownership to GitHub Actions
  Add License
  fix: use root option in sendFile to avoid dotfile 500 on SPA refresh

# Conflicts:
#	cli/src/adapters/registry.ts
#	pnpm-lock.yaml
#	server/src/adapters/registry.ts
#	ui/package.json
#	ui/src/adapters/registry.ts
This commit is contained in:
Dotta
2026-03-07 15:18:02 -06:00
44 changed files with 2350 additions and 995 deletions

View File

@@ -0,0 +1,47 @@
import type { AdapterConfigFieldsProps } from "../types";
import {
Field,
DraftInput,
} from "../../components/agent-config-primitives";
import { ChoosePathButton } from "../../components/PathInstructionsModal";
const inputClass =
"w-full rounded-md border border-border px-2.5 py-1.5 bg-transparent outline-none text-sm font-mono placeholder:text-muted-foreground/40";
const instructionsFileHint =
"Absolute path to a markdown file (e.g. AGENTS.md) that defines this agent's behavior. Injected into the system prompt at runtime.";
export function PiLocalConfigFields({
isCreate,
values,
set,
config,
eff,
mark,
}: AdapterConfigFieldsProps) {
return (
<Field label="Agent instructions file" hint={instructionsFileHint}>
<div className="flex items-center gap-2">
<DraftInput
value={
isCreate
? values!.instructionsFilePath ?? ""
: eff(
"adapterConfig",
"instructionsFilePath",
String(config.instructionsFilePath ?? ""),
)
}
onCommit={(v) =>
isCreate
? set!({ instructionsFilePath: v })
: mark("adapterConfig", "instructionsFilePath", v || undefined)
}
immediate
className={inputClass}
placeholder="/absolute/path/to/AGENTS.md"
/>
<ChoosePathButton />
</div>
</Field>
);
}

View File

@@ -0,0 +1,12 @@
import type { UIAdapterModule } from "../types";
import { parsePiStdoutLine } from "@paperclipai/adapter-pi-local/ui";
import { PiLocalConfigFields } from "./config-fields";
import { buildPiLocalConfig } from "@paperclipai/adapter-pi-local/ui";
export const piLocalUIAdapter: UIAdapterModule = {
type: "pi_local",
label: "Pi (local)",
parseStdoutLine: parsePiStdoutLine,
ConfigFields: PiLocalConfigFields,
buildAdapterConfig: buildPiLocalConfig,
};

View File

@@ -3,6 +3,7 @@ import { claudeLocalUIAdapter } from "./claude-local";
import { codexLocalUIAdapter } from "./codex-local";
import { cursorLocalUIAdapter } from "./cursor";
import { openCodeLocalUIAdapter } from "./opencode-local";
import { piLocalUIAdapter } from "./pi-local";
import { openClawUIAdapter } from "./openclaw";
import { openClawGatewayUIAdapter } from "./openclaw-gateway";
import { processUIAdapter } from "./process";
@@ -13,6 +14,7 @@ const adaptersByType = new Map<string, UIAdapterModule>(
claudeLocalUIAdapter,
codexLocalUIAdapter,
openCodeLocalUIAdapter,
piLocalUIAdapter,
cursorLocalUIAdapter,
openClawUIAdapter,
openClawGatewayUIAdapter,

View File

@@ -53,6 +53,7 @@ type AdapterType =
| "claude_local"
| "codex_local"
| "opencode_local"
| "pi_local"
| "cursor"
| "process"
| "http"
@@ -666,6 +667,12 @@ export function OnboardingWizard() {
icon: OpenCodeLogoIcon,
desc: "Local multi-provider agent"
},
{
value: "pi_local" as const,
label: "Pi",
icon: Terminal,
desc: "Local Pi agent"
},
{
value: "openclaw" as const,
label: "OpenClaw",
@@ -730,7 +737,7 @@ export function OnboardingWizard() {
}}
>
{opt.recommended && (
<span className="absolute -top-1.5 -right-1.5 bg-green-500 text-white text-[9px] font-semibold px-1.5 py-0.5 rounded-full leading-none">
<span className="absolute -top-1.5 right-1.5 bg-green-500 text-white text-[9px] font-semibold px-1.5 py-0.5 rounded-full leading-none">
Recommended
</span>
)}
@@ -748,6 +755,7 @@ export function OnboardingWizard() {
{(adapterType === "claude_local" ||
adapterType === "codex_local" ||
adapterType === "opencode_local" ||
adapterType === "pi_local" ||
adapterType === "cursor") && (
<div className="space-y-3">
<div>

View File

@@ -468,7 +468,7 @@ export function AgentDetail() {
disabled={agentAction.isPending || isPendingApproval}
>
<Play className="h-3.5 w-3.5 sm:mr-1" />
<span className="hidden sm:inline">Invoke</span>
<span className="hidden sm:inline">Run Heartbeat</span>
</Button>
{agent.status === "paused" ? (
<Button