Skip to content

Commit d488113

Browse files
Automattclaude
andcommitted
Merge upstream/master into origin/master (resolve conflicts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2 parents 35836aa + 671a8ae commit d488113

173 files changed

Lines changed: 24845 additions & 1640 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@paperclipai/shared": minor
3+
---
4+
5+
Add support for Pi local adapter in constants and onboarding UI.

.github/workflows/ci.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
push:
8+
branches:
9+
- master
10+
11+
concurrency:
12+
group: ci-${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
verify:
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 20
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Setup pnpm
25+
uses: pnpm/action-setup@v4
26+
with:
27+
version: 9.15.4
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version: 20
33+
cache: pnpm
34+
35+
- name: Install dependencies
36+
run: pnpm install --frozen-lockfile
37+
38+
- name: Typecheck
39+
run: pnpm -r typecheck
40+
41+
- name: Run tests
42+
run: pnpm test:run
43+
44+
- name: Build
45+
run: pnpm build

CONTRIBUTING.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Contributing Guide
2+
3+
Thanks for wanting to contribute!
4+
5+
We really appreciate both small fixes and thoughtful larger changes.
6+
7+
## Two Paths to Get Your Pull Request Accepted
8+
9+
### Path 1: Small, Focused Changes (Fastest way to get merged)
10+
- Pick **one** clear thing to fix/improve
11+
- Touch the **smallest possible number of files**
12+
- Make sure the change is very targeted and easy to review
13+
- All automated checks pass (including Greptile comments)
14+
- No new lint/test failures
15+
16+
These almost always get merged quickly when they're clean.
17+
18+
### Path 2: Bigger or Impactful Changes
19+
- **First** talk about it in Discord → #dev channel
20+
→ Describe what you're trying to solve
21+
→ Share rough ideas / approach
22+
- Once there's rough agreement, build it
23+
- In your PR include:
24+
- Before / After screenshots (or short video if UI/behavior change)
25+
- Clear description of what & why
26+
- Proof it works (manual testing notes)
27+
- All tests passing
28+
- All Greptile + other PR comments addressed
29+
30+
PRs that follow this path are **much** more likely to be accepted, even when they're large.
31+
32+
## General Rules (both paths)
33+
- Write clear commit messages
34+
- Keep PR title + description meaningful
35+
- One PR = one logical change (unless it's a small related group)
36+
- Run tests locally first
37+
- Be kind in discussions 😄
38+
39+
Questions? Just ask in #dev — we're happy to help.
40+
41+
Happy hacking!

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:20-bookworm-slim AS base
1+
FROM node:lts-trixie-slim AS base
22
RUN apt-get update \
33
&& apt-get install -y --no-install-recommends ca-certificates curl git openssh-client \
44
&& rm -rf /var/lib/apt/lists/*
@@ -26,6 +26,7 @@ COPY --from=deps /app /app
2626
COPY . .
2727
RUN pnpm --filter @paperclipai/ui... build
2828
RUN pnpm --filter @paperclipai/server... build
29+
RUN test -f server/dist/index.js || (echo "ERROR: server build output missing" && exit 1)
2930

3031
FROM base AS production
3132
WORKDIR /app
@@ -42,7 +43,7 @@ ENV NODE_ENV=production \
4243
PAPERCLIP_HOME=/paperclip \
4344
PAPERCLIP_INSTANCE_ID=default \
4445
PAPERCLIP_CONFIG=/paperclip/instances/default/config.json \
45-
PAPERCLIP_DEPLOYMENT_MODE=local_trusted \
46+
PAPERCLIP_DEPLOYMENT_MODE=authenticated \
4647
PAPERCLIP_DEPLOYMENT_EXPOSURE=private
4748

4849
RUN mkdir -p /paperclip && chown -R paperclip:paperclip /paperclip /app

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Paperclip AI
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ By default, agents run on scheduled heartbeats and event-based triggers (task as
218218
## Development
219219

220220
```bash
221-
pnpm dev # Full dev (API + UI)
221+
pnpm dev # Full dev (API + UI, watch mode)
222+
pnpm dev:once # Full dev without file watching
222223
pnpm dev:server # Server only
223224
pnpm build # Build all
224225
pnpm typecheck # Type checking

cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"@paperclipai/adapter-codex-local": "workspace:*",
3939
"@paperclipai/adapter-cursor-local": "workspace:*",
4040
"@paperclipai/adapter-opencode-local": "workspace:*",
41+
"@paperclipai/adapter-pi-local": "workspace:*",
4142
"@paperclipai/adapter-openclaw": "workspace:*",
4243
"@paperclipai/adapter-utils": "workspace:*",
4344
"@paperclipai/db": "workspace:*",

cli/src/adapters/registry.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { printClaudeStreamEvent } from "@paperclipai/adapter-claude-local/cli";
33
import { printCodexStreamEvent } from "@paperclipai/adapter-codex-local/cli";
44
import { printCursorStreamEvent } from "@paperclipai/adapter-cursor-local/cli";
55
import { printOpenCodeStreamEvent } from "@paperclipai/adapter-opencode-local/cli";
6+
import { printPiStreamEvent } from "@paperclipai/adapter-pi-local/cli";
67
import { printOpenClawStreamEvent } from "@paperclipai/adapter-openclaw/cli";
78
import { processCLIAdapter } from "./process/index.js";
89
import { httpCLIAdapter } from "./http/index.js";
@@ -17,11 +18,16 @@ const codexLocalCLIAdapter: CLIAdapterModule = {
1718
formatStdoutEvent: printCodexStreamEvent,
1819
};
1920

20-
const opencodeLocalCLIAdapter: CLIAdapterModule = {
21+
const openCodeLocalCLIAdapter: CLIAdapterModule = {
2122
type: "opencode_local",
2223
formatStdoutEvent: printOpenCodeStreamEvent,
2324
};
2425

26+
const piLocalCLIAdapter: CLIAdapterModule = {
27+
type: "pi_local",
28+
formatStdoutEvent: printPiStreamEvent,
29+
};
30+
2531
const cursorLocalCLIAdapter: CLIAdapterModule = {
2632
type: "cursor",
2733
formatStdoutEvent: printCursorStreamEvent,
@@ -33,7 +39,7 @@ const openclawCLIAdapter: CLIAdapterModule = {
3339
};
3440

3541
const adaptersByType = new Map<string, CLIAdapterModule>(
36-
[claudeLocalCLIAdapter, codexLocalCLIAdapter, opencodeLocalCLIAdapter, cursorLocalCLIAdapter, openclawCLIAdapter, processCLIAdapter, httpCLIAdapter].map((a) => [a.type, a]),
42+
[claudeLocalCLIAdapter, codexLocalCLIAdapter, openCodeLocalCLIAdapter, piLocalCLIAdapter, cursorLocalCLIAdapter, openclawCLIAdapter, processCLIAdapter, httpCLIAdapter].map((a) => [a.type, a]),
3743
);
3844

3945
export function getCLIAdapter(type: string): CLIAdapterModule {

cli/src/commands/auth-bootstrap-ceo.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ function resolveDbUrl(configPath?: string) {
2828

2929
function resolveBaseUrl(configPath?: string, explicitBaseUrl?: string) {
3030
if (explicitBaseUrl) return explicitBaseUrl.replace(/\/+$/, "");
31+
const fromEnv =
32+
process.env.PAPERCLIP_PUBLIC_URL ??
33+
process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ??
34+
process.env.BETTER_AUTH_URL ??
35+
process.env.BETTER_AUTH_BASE_URL;
36+
if (fromEnv?.trim()) return fromEnv.trim().replace(/\/+$/, "");
3137
const config = readConfig(configPath);
3238
if (config?.auth.baseUrlMode === "explicit" && config.auth.publicBaseUrl) {
3339
return config.auth.publicBaseUrl.replace(/\/+$/, "");

cli/src/commands/env.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,29 @@ function collectDeploymentEnvRows(config: PaperclipConfig | null, configPath: st
118118
const dbUrl = process.env.DATABASE_URL ?? config?.database?.connectionString ?? "";
119119
const databaseMode = config?.database?.mode ?? "embedded-postgres";
120120
const dbUrlSource: EnvSource = process.env.DATABASE_URL ? "env" : config?.database?.connectionString ? "config" : "missing";
121+
const publicUrl =
122+
process.env.PAPERCLIP_PUBLIC_URL ??
123+
process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ??
124+
process.env.BETTER_AUTH_URL ??
125+
process.env.BETTER_AUTH_BASE_URL ??
126+
config?.auth?.publicBaseUrl ??
127+
"";
128+
const publicUrlSource: EnvSource =
129+
process.env.PAPERCLIP_PUBLIC_URL
130+
? "env"
131+
: process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL || process.env.BETTER_AUTH_URL || process.env.BETTER_AUTH_BASE_URL
132+
? "env"
133+
: config?.auth?.publicBaseUrl
134+
? "config"
135+
: "missing";
136+
let trustedOriginsDefault = "";
137+
if (publicUrl) {
138+
try {
139+
trustedOriginsDefault = new URL(publicUrl).origin;
140+
} catch {
141+
trustedOriginsDefault = "";
142+
}
143+
}
121144

122145
const heartbeatInterval = process.env.HEARTBEAT_SCHEDULER_INTERVAL_MS ?? DEFAULT_HEARTBEAT_SCHEDULER_INTERVAL_MS;
123146
const heartbeatEnabled = process.env.HEARTBEAT_SCHEDULER_ENABLED ?? "true";
@@ -192,6 +215,24 @@ function collectDeploymentEnvRows(config: PaperclipConfig | null, configPath: st
192215
required: false,
193216
note: "HTTP listen port",
194217
},
218+
{
219+
key: "PAPERCLIP_PUBLIC_URL",
220+
value: publicUrl,
221+
source: publicUrlSource,
222+
required: false,
223+
note: "Canonical public URL for auth/callback/invite origin wiring",
224+
},
225+
{
226+
key: "BETTER_AUTH_TRUSTED_ORIGINS",
227+
value: process.env.BETTER_AUTH_TRUSTED_ORIGINS ?? trustedOriginsDefault,
228+
source: process.env.BETTER_AUTH_TRUSTED_ORIGINS
229+
? "env"
230+
: trustedOriginsDefault
231+
? "default"
232+
: "missing",
233+
required: false,
234+
note: "Comma-separated auth origin allowlist (auto-derived from PAPERCLIP_PUBLIC_URL when possible)",
235+
},
195236
{
196237
key: "PAPERCLIP_AGENT_JWT_TTL_SECONDS",
197238
value: process.env.PAPERCLIP_AGENT_JWT_TTL_SECONDS ?? DEFAULT_AGENT_JWT_TTL_SECONDS,

0 commit comments

Comments
 (0)