Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nix/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ buildNpmPackage rec {

# To update: run `nix build` with lib.fakeHash, copy the `got:` hash.
# CI auto-updates this when package-lock.json changes (see .github/workflows/).
npmDepsHash = "sha256-epuepM6DMEpOfzvPiS6K/qKJqGM89FqdsKHovWi2LS8=";
npmDepsHash = "sha256-Nk6DAnDkXd8KSCmnIDcRoM8V6rHR874PBOovuZFxbfY=";

# Prevent onnxruntime-node's install script from running during automatic
# npm rebuild (it tries to download from api.nuget.org, which fails in the sandbox).
Expand Down
2,844 changes: 2,785 additions & 59 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"@getpaseo/relay": "0.1.48",
"@isaacs/ttlcache": "^2.1.4",
"@modelcontextprotocol/sdk": "^1.20.1",
"@mariozechner/pi-coding-agent": "^0.65.2",
"@opencode-ai/sdk": "1.2.6",
"@sctg/sentencepiece-js": "^1.1.0",
"@xterm/headless": "^6.0.0",
Expand All @@ -81,7 +82,6 @@
"node-pty": "1.2.0-beta.11",
"onnxruntime-node": "^1.23.0",
"openai": "^4.20.0",
"pi-acp": "^0.0.24",
"pino": "^10.2.0",
"pino-pretty": "^13.1.3",
"qrcode": "^1.5.4",
Expand Down
5 changes: 3 additions & 2 deletions packages/server/src/server/agent/provider-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ClaudeAgentClient } from "./providers/claude-agent.js";
import { CodexAppServerAgentClient } from "./providers/codex-app-server-agent.js";
import { OpenCodeAgentClient, OpenCodeServerManager } from "./providers/opencode-agent.js";
import { CopilotACPAgentClient } from "./providers/copilot-acp-agent.js";
import { PiACPAgentClient } from "./providers/pi-acp-agent.js";
import { PiDirectAgentClient } from "./providers/pi-direct-agent.js";

import {
AGENT_PROVIDER_DEFINITIONS,
Expand Down Expand Up @@ -54,7 +54,8 @@ const PROVIDER_CLIENT_FACTORIES: Record<string, ProviderClientFactory> = {
}),
opencode: (logger, runtimeSettings) =>
new OpenCodeAgentClient(logger, runtimeSettings?.opencode),
pi: (logger, runtimeSettings) => new PiACPAgentClient({ logger, runtimeSettings: runtimeSettings?.pi }),
pi: (logger, runtimeSettings) =>
new PiDirectAgentClient({ logger, runtimeSettings: runtimeSettings?.pi }),
};

function getProviderClientFactory(provider: string): ProviderClientFactory {
Expand Down
81 changes: 2 additions & 79 deletions packages/server/src/server/agent/providers/acp-agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
deriveModesFromACP,
mapACPUsage,
} from "./acp-agent.js";
import { transformPiModels, transformPiSessionResponse, wrapPiSession } from "./pi-acp-agent.js";
import { transformPiSessionResponse } from "./pi-acp-agent.js";
import { transformPiModels } from "./pi-direct-agent.js";
import { createTestLogger } from "../../../test-utils/test-logger.js";

function createSession(): ACPAgentSession {
Expand Down Expand Up @@ -526,84 +527,6 @@ describe("ACPAgentSession", () => {
]);
});

test("Pi session wrapper hides synthetic modes and exposes them as thinking", async () => {
const wrapped = wrapPiSession(
{
provider: "pi",
id: "session-1",
capabilities: {
supportsStreaming: true,
supportsSessionPersistence: true,
supportsDynamicModes: true,
supportsMcpServers: false,
supportsReasoningStream: true,
supportsToolInvocations: true,
},
features: [
{
type: "select",
id: "thought_level",
label: "Thinking",
value: "medium",
options: [
{ id: "low", label: "Low" },
{ id: "medium", label: "Medium" },
],
},
],
run: vi.fn(),
startTurn: vi.fn(),
subscribe: vi.fn(() => () => {}),
streamHistory: async function* () {},
getRuntimeInfo: vi.fn(async () => ({
provider: "pi",
sessionId: "session-1",
model: "gpt-4.1-mini",
thinkingOptionId: null,
modeId: "xhigh",
})),
getAvailableModes: vi.fn(async () => [
{ id: "xhigh", label: "xhigh" },
]),
getCurrentMode: vi.fn(async () => "xhigh"),
setMode: vi.fn(),
getPendingPermissions: vi.fn(() => []),
respondToPermission: vi.fn(),
describePersistence: vi.fn(() => null),
interrupt: vi.fn(),
close: vi.fn(),
setThinkingOption: vi.fn(),
},
{
provider: "pi",
cwd: "/tmp/paseo-acp-test",
thinkingOptionId: "medium",
},
);

await expect(wrapped.getAvailableModes()).resolves.toEqual([]);
await expect(wrapped.getCurrentMode()).resolves.toBeNull();
await expect(wrapped.getRuntimeInfo()).resolves.toEqual({
provider: "pi",
sessionId: "session-1",
model: "gpt-4.1-mini",
thinkingOptionId: "xhigh",
modeId: null,
});
expect(wrapped.features).toEqual([
{
type: "select",
id: "thought_level",
label: "Thinking",
value: "xhigh",
options: [
{ id: "low", label: "Low" },
{ id: "medium", label: "Medium" },
],
},
]);
});

test("emits assistant and reasoning chunks as deltas while user chunks stay accumulated", async () => {
const session = createSession();
const events: Array<{ type: string; item?: { type: string; text?: string } }> = [];
Expand Down
13 changes: 10 additions & 3 deletions packages/server/src/server/agent/providers/claude-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ class TimelineAssembler {
runId: string | null,
messageIdHint: string | null,
): AgentTimelineItem[] {
const event = message.event as Record<string, unknown>;
const event = message.event as unknown as Record<string, unknown>;
const eventType = readTrimmedString(event.type);
const streamEventMessageId = this.readMessageIdFromStreamEvent(event) ?? messageIdHint;

Expand Down Expand Up @@ -2002,7 +2002,14 @@ class ClaudeAgentSession implements AgentSession {
private toSdkUserMessage(prompt: AgentPromptInput): SDKUserMessage {
const content: Array<
| { type: "text"; text: string }
| { type: "image"; source: { type: "base64"; media_type: string; data: string } }
| {
type: "image";
source: {
type: "base64";
media_type: "image/jpeg" | "image/png" | "image/gif" | "image/webp";
data: string;
};
}
> = [];
if (Array.isArray(prompt)) {
for (const chunk of prompt) {
Expand All @@ -2013,7 +2020,7 @@ class ClaudeAgentSession implements AgentSession {
type: "image",
source: {
type: "base64",
media_type: chunk.mimeType,
media_type: chunk.mimeType as "image/jpeg" | "image/png" | "image/gif" | "image/webp",
data: chunk.data,
},
});
Expand Down
Loading
Loading