Publish the TypeScript SDK and integration guides (#3141)
* feat(client): publish the TypeScript SDK surface Make the high-level client API usable for external integrations and document complete agent, workspace, provider, event, and recipe flows. * fix(client): correlate provider snapshots by daemon cwd Return the daemon's canonical snapshot identity so waitForReady can match updates for relative, tilde, and otherwise non-canonical paths without duplicating filesystem rules in the SDK. * test(server): make snapshot cwd assertion portable * fix(client): gate canonical provider snapshot waits Older daemons do not expose the canonical snapshot identity needed to correlate workspace updates safely. Require the advertised capability and fail with an update-host message instead of guessing across workspaces.
This commit is contained in:
@@ -6,13 +6,16 @@ These examples use only the public SDK root:
|
||||
import { createPaseoClient, type PaseoClient } from "@getpaseo/client";
|
||||
```
|
||||
|
||||
Pass the daemon WebSocket URL into the exported functions. In worktree dev, read it
|
||||
Each example takes the daemon WebSocket URL as an argument. In worktree dev, read it
|
||||
from the portless banner or `portless get daemon`; for the desktop-managed daemon,
|
||||
use the URL for that daemon.
|
||||
|
||||
- `workspaces.ts` covers creating, opening, refetching, and archiving a workspace.
|
||||
- `agents-and-providers.ts` covers creating agents and choosing providers with `client.providers.*`.
|
||||
- `quickstart.ts` runs one agent and prints its reply. It is a standalone script with the URL at the top; the rest export functions.
|
||||
- `workspaces.ts` covers creating a fresh workspace, opening by directory, refreshing, and archiving.
|
||||
- `agents-and-providers.ts` covers provider discovery, creating agents, and waiting for turns.
|
||||
- `events-and-timeline.ts` covers subscribing to workspace, agent, and timeline events, plus refetching a timeline page.
|
||||
- `issue-to-agent.ts` turns an issue record into a visible Paseo workspace and agent.
|
||||
- `parallel-review.ts` launches several reviewers concurrently and cleans them up.
|
||||
- `provider-settings.ts` covers provider settings that are currently daemon config-backed.
|
||||
|
||||
Provider profiles, provider env vars, custom binaries, and additional models are still raw daemon config behavior. The SDK exposes them through `client.config.get()` and `client.config.patch()` until first-class provider settings RPCs exist.
|
||||
|
||||
@@ -14,13 +14,11 @@ export async function createCodexAgent(url: string, cwd: string): Promise<string
|
||||
|
||||
const agent = await client.agents.create({
|
||||
config: {
|
||||
...client.providers.codex({
|
||||
model: "gpt-5.2",
|
||||
modeId: "full-auto",
|
||||
}),
|
||||
cwd,
|
||||
provider: "codex/gpt-5.5",
|
||||
modeId: "full-access",
|
||||
},
|
||||
initialPrompt: "Inspect this repository and summarize the next useful task.",
|
||||
cwd,
|
||||
prompt: "Inspect this repository and summarize the next useful task.",
|
||||
});
|
||||
|
||||
return agent.id;
|
||||
@@ -35,18 +33,18 @@ export async function chooseProviderFromSnapshot(url: string, cwd: string): Prom
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
const snapshot = await client.providers.snapshot({ cwd });
|
||||
const snapshot = await client.providers.waitForReady({ cwd });
|
||||
const readyProvider = snapshot.entries.find((provider) => provider.status === "ready");
|
||||
const providerConfig = readyProvider
|
||||
? client.providers.config(readyProvider.provider)
|
||||
: client.providers.claude();
|
||||
const model =
|
||||
readyProvider?.models?.find((candidate) => candidate.isDefault) ?? readyProvider?.models?.[0];
|
||||
if (!readyProvider || !model) throw new Error("No provider model is ready");
|
||||
|
||||
const agent = await client.agents.create({
|
||||
config: {
|
||||
...providerConfig,
|
||||
cwd,
|
||||
provider: `${readyProvider.provider}/${model.id}`,
|
||||
},
|
||||
initialPrompt: "Start with a quick repository map.",
|
||||
cwd,
|
||||
prompt: "Start with a quick repository map.",
|
||||
});
|
||||
|
||||
return agent.id;
|
||||
@@ -54,3 +52,16 @@ export async function chooseProviderFromSnapshot(url: string, cwd: string): Prom
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
export async function runFollowUp(url: string, agentId: string): Promise<string | null> {
|
||||
const client = createClient(url);
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
const result = await client.agents.ref(agentId).run("Summarize your progress and next step.");
|
||||
if (result.status !== "idle") throw new Error(result.error ?? result.status);
|
||||
return result.lastMessage;
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createPaseoClient, type PaseoClient } from "@getpaseo/client";
|
||||
|
||||
interface Issue {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
repositoryPath: string;
|
||||
}
|
||||
|
||||
export async function startIssue(client: PaseoClient, issue: Issue) {
|
||||
const workspace = await client.workspaces.open(issue.repositoryPath);
|
||||
const agent = await workspace.agents.create({
|
||||
config: {
|
||||
provider: "codex/gpt-5.5",
|
||||
},
|
||||
title: issue.title,
|
||||
labels: {
|
||||
"issue-provider": "my-tracker",
|
||||
"issue-id": issue.id,
|
||||
},
|
||||
prompt: [
|
||||
`Implement issue ${issue.id}: ${issue.title}`,
|
||||
"",
|
||||
issue.description,
|
||||
"",
|
||||
"Run focused tests and summarize the result.",
|
||||
].join("\n"),
|
||||
});
|
||||
|
||||
return { workspaceId: workspace.id, agentId: agent.id };
|
||||
}
|
||||
|
||||
export function createClient(url: string): PaseoClient {
|
||||
return createPaseoClient({ url });
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { PaseoAgentHandle, PaseoClient } from "@getpaseo/client";
|
||||
|
||||
export async function reviewInParallel(client: PaseoClient, cwd: string): Promise<string[]> {
|
||||
const agents: PaseoAgentHandle[] = [];
|
||||
|
||||
try {
|
||||
agents.push(
|
||||
...(await Promise.all([
|
||||
client.agents.create({
|
||||
config: {
|
||||
provider: "codex/gpt-5.5",
|
||||
},
|
||||
cwd,
|
||||
title: "Correctness review",
|
||||
prompt: "Review the current diff for correctness and missed edge cases.",
|
||||
}),
|
||||
client.agents.create({
|
||||
config: {
|
||||
provider: "claude/claude-sonnet-5",
|
||||
},
|
||||
cwd,
|
||||
title: "Security review",
|
||||
prompt: "Review the current diff for security and unsafe input handling.",
|
||||
}),
|
||||
])),
|
||||
);
|
||||
|
||||
const results = await Promise.all(agents.map((agent) => agent.waitForFinish()));
|
||||
|
||||
return results.map((result) => {
|
||||
if (result.status !== "idle") throw new Error(result.error ?? result.status);
|
||||
return result.lastMessage ?? "";
|
||||
});
|
||||
} finally {
|
||||
await Promise.allSettled(agents.map((agent) => agent.archive()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { createPaseoClient } from "@getpaseo/client";
|
||||
|
||||
const client = createPaseoClient({ url: "ws://127.0.0.1:6767/ws" });
|
||||
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
const agent = await client.agents.create({
|
||||
config: {
|
||||
provider: "codex/gpt-5.5",
|
||||
},
|
||||
cwd: process.cwd(),
|
||||
prompt: "Inspect this repository and name the next useful task.",
|
||||
});
|
||||
|
||||
const result = await agent.waitForFinish();
|
||||
if (result.status !== "idle") {
|
||||
throw new Error(result.error ?? `Agent stopped with status: ${result.status}`);
|
||||
}
|
||||
|
||||
console.log(result.lastMessage);
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
@@ -12,18 +12,14 @@ export async function createOpenAndArchiveWorkspace(url: string, cwd: string): P
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
const created = await client.workspaces.create(cwd);
|
||||
if (!created.workspace) {
|
||||
throw new Error(created.error ?? "Workspace creation failed");
|
||||
}
|
||||
|
||||
const created = await client.workspaces.create({
|
||||
source: { kind: "directory", path: cwd },
|
||||
title: "Fresh SDK workspace",
|
||||
});
|
||||
const opened = await client.workspaces.open(cwd);
|
||||
if (!opened.workspace) {
|
||||
throw new Error(opened.error ?? "Workspace open failed");
|
||||
}
|
||||
|
||||
await opened.workspace.refetch();
|
||||
await opened.workspace.archive();
|
||||
await opened.refresh();
|
||||
await created.archive();
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user