@getpaseo/server 0.1.91 → 0.1.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/server/agent/agent-manager.d.ts +12 -4
- package/dist/server/server/agent/agent-manager.js +87 -26
- package/dist/server/server/agent/agent-projections.d.ts +4 -2
- package/dist/server/server/agent/agent-projections.js +8 -28
- package/dist/server/server/agent/agent-sdk-types.d.ts +30 -10
- package/dist/server/server/agent/import-sessions.d.ts +3 -2
- package/dist/server/server/agent/import-sessions.js +23 -55
- package/dist/server/server/agent/provider-registry.js +34 -13
- package/dist/server/server/agent/provider-session-import.d.ts +10 -0
- package/dist/server/server/agent/provider-session-import.js +49 -0
- package/dist/server/server/agent/providers/acp-agent.d.ts +12 -2
- package/dist/server/server/agent/providers/acp-agent.js +78 -36
- package/dist/server/server/agent/providers/claude/agent.d.ts +3 -2
- package/dist/server/server/agent/providers/claude/agent.js +28 -24
- package/dist/server/server/agent/providers/claude/models.js +15 -0
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +3 -2
- package/dist/server/server/agent/providers/codex-app-server-agent.js +20 -21
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +1 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.js +1 -0
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +9 -0
- package/dist/server/server/agent/providers/generic-acp-agent.js +18 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +3 -2
- package/dist/server/server/agent/providers/mock-load-test-agent.js +11 -1
- package/dist/server/server/agent/providers/mock-slow-provider.d.ts +1 -2
- package/dist/server/server/agent/providers/mock-slow-provider.js +0 -3
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +8 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts +3 -2
- package/dist/server/server/agent/providers/opencode-agent.js +60 -32
- package/dist/server/server/agent/providers/pi/agent.d.ts +3 -2
- package/dist/server/server/agent/providers/pi/agent.js +28 -5
- package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +3 -4
- package/dist/server/server/agent/providers/pi/session-descriptor.js +17 -37
- package/dist/server/server/session.js +0 -1
- package/package.json +5 -5
|
@@ -12,6 +12,7 @@ export class CursorACPAgentClient extends GenericACPAgentClient {
|
|
|
12
12
|
env: options.env,
|
|
13
13
|
providerId: options.providerId,
|
|
14
14
|
label: options.label,
|
|
15
|
+
providerParams: options.providerParams,
|
|
15
16
|
// cursor-agent publishes slash commands asynchronously via available_commands_update.
|
|
16
17
|
waitForInitialCommands: true,
|
|
17
18
|
initialCommandsWaitTimeoutMs: CURSOR_INITIAL_COMMANDS_WAIT_TIMEOUT_MS,
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
import { ACPAgentClient } from "./acp-agent.js";
|
|
4
|
+
export declare const GenericACPProviderParamsSchema: z.ZodObject<{
|
|
5
|
+
supportsMcpServers: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
7
|
+
supportsMcpServers: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
9
|
+
supportsMcpServers: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
3
11
|
interface GenericACPAgentClientOptions {
|
|
4
12
|
logger: Logger;
|
|
5
13
|
command: [string, ...string[]];
|
|
6
14
|
env?: Record<string, string>;
|
|
7
15
|
providerId?: string;
|
|
8
16
|
label?: string;
|
|
17
|
+
providerParams?: unknown;
|
|
9
18
|
waitForInitialCommands?: boolean;
|
|
10
19
|
initialCommandsWaitTimeoutMs?: number;
|
|
11
20
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
import { checkProviderLaunchAvailable, resolveProviderLaunch } from "../provider-launch-config.js";
|
|
3
|
-
import { ACPAgentClient, deriveModelDefinitionsFromACP, deriveModesFromACP, } from "./acp-agent.js";
|
|
4
|
+
import { ACPAgentClient, DEFAULT_ACP_CAPABILITIES, deriveModelDefinitionsFromACP, deriveModesFromACP, } from "./acp-agent.js";
|
|
4
5
|
import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, buildBinaryDiagnosticRows, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
|
|
5
6
|
const ACP_DIAGNOSTIC_INITIALIZE_TIMEOUT_MS = 8000;
|
|
6
7
|
const ACP_DIAGNOSTIC_SESSION_TIMEOUT_MS = 8000;
|
|
8
|
+
export const GenericACPProviderParamsSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
supportsMcpServers: z.boolean().optional(),
|
|
11
|
+
})
|
|
12
|
+
.passthrough();
|
|
7
13
|
export class GenericACPAgentClient extends ACPAgentClient {
|
|
8
14
|
constructor(options) {
|
|
9
15
|
super({
|
|
@@ -13,6 +19,7 @@ export class GenericACPAgentClient extends ACPAgentClient {
|
|
|
13
19
|
env: options.env,
|
|
14
20
|
},
|
|
15
21
|
defaultCommand: options.command,
|
|
22
|
+
capabilities: buildGenericACPCapabilities(options),
|
|
16
23
|
waitForInitialCommands: options.waitForInitialCommands,
|
|
17
24
|
initialCommandsWaitTimeoutMs: options.initialCommandsWaitTimeoutMs,
|
|
18
25
|
});
|
|
@@ -128,6 +135,16 @@ export class GenericACPAgentClient extends ACPAgentClient {
|
|
|
128
135
|
}
|
|
129
136
|
}
|
|
130
137
|
}
|
|
138
|
+
function buildGenericACPCapabilities(options) {
|
|
139
|
+
const params = parseGenericACPProviderParams(options.providerParams);
|
|
140
|
+
return {
|
|
141
|
+
...DEFAULT_ACP_CAPABILITIES,
|
|
142
|
+
supportsMcpServers: params.supportsMcpServers ?? DEFAULT_ACP_CAPABILITIES.supportsMcpServers,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function parseGenericACPProviderParams(params) {
|
|
146
|
+
return GenericACPProviderParamsSchema.parse(params ?? {});
|
|
147
|
+
}
|
|
131
148
|
function formatProviderName(label, providerId) {
|
|
132
149
|
if (label) {
|
|
133
150
|
return `${label} (ACP)`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
import type { AgentCapabilityFlags, AgentClient, AgentFeature, AgentLaunchContext, AgentMode, AgentModelDefinition, AgentPersistenceHandle, AgentPermissionRequest, AgentPermissionResponse, AgentPermissionResult, AgentPromptInput, AgentProvider, AgentRunOptions, AgentRunResult, AgentRuntimeInfo, AgentSession, AgentSessionConfig, AgentStreamEvent,
|
|
2
|
+
import type { AgentCapabilityFlags, AgentClient, AgentFeature, AgentLaunchContext, AgentMode, AgentModelDefinition, AgentPersistenceHandle, AgentPermissionRequest, AgentPermissionResponse, AgentPermissionResult, AgentPromptInput, AgentProvider, AgentRunOptions, AgentRunResult, AgentRuntimeInfo, AgentSession, AgentSessionConfig, AgentStreamEvent, ImportableProviderSession, ImportProviderSessionContext, ImportProviderSessionInput, ListModesOptions, ListModelsOptions } from "../agent-sdk-types.js";
|
|
3
3
|
export declare const MOCK_LOAD_TEST_PROVIDER_ID = "mock";
|
|
4
4
|
export declare const MOCK_LOAD_TEST_DEFAULT_MODEL_ID = "five-minute-stream";
|
|
5
5
|
export declare class MockLoadTestAgentClient implements AgentClient {
|
|
@@ -11,7 +11,8 @@ export declare class MockLoadTestAgentClient implements AgentClient {
|
|
|
11
11
|
resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, _launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
12
12
|
listModels(_options: ListModelsOptions): Promise<AgentModelDefinition[]>;
|
|
13
13
|
listModes(_options: ListModesOptions): Promise<AgentMode[]>;
|
|
14
|
-
|
|
14
|
+
listImportableSessions(): Promise<ImportableProviderSession[]>;
|
|
15
|
+
importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../agent-sdk-types.js").ImportedProviderSession>;
|
|
15
16
|
isAvailable(): Promise<boolean>;
|
|
16
17
|
getDiagnostic(): Promise<{
|
|
17
18
|
diagnostic: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { importSessionFromPersistence } from "../provider-session-import.js";
|
|
2
3
|
import { getAgentProviderDefinition } from "@getpaseo/protocol/provider-manifest";
|
|
3
4
|
export const MOCK_LOAD_TEST_PROVIDER_ID = "mock";
|
|
4
5
|
export const MOCK_LOAD_TEST_DEFAULT_MODEL_ID = "five-minute-stream";
|
|
@@ -8,6 +9,7 @@ const MOCK_LOAD_TEST_INTERVAL_MS = 40;
|
|
|
8
9
|
const CAPABILITIES = {
|
|
9
10
|
supportsStreaming: true,
|
|
10
11
|
supportsSessionPersistence: true,
|
|
12
|
+
supportsSessionListing: true,
|
|
11
13
|
supportsDynamicModes: false,
|
|
12
14
|
supportsMcpServers: false,
|
|
13
15
|
supportsReasoningStream: true,
|
|
@@ -308,9 +310,17 @@ export class MockLoadTestAgentClient {
|
|
|
308
310
|
async listModes(_options) {
|
|
309
311
|
return getAgentProviderDefinition(MOCK_LOAD_TEST_PROVIDER_ID).modes;
|
|
310
312
|
}
|
|
311
|
-
async
|
|
313
|
+
async listImportableSessions() {
|
|
312
314
|
return [];
|
|
313
315
|
}
|
|
316
|
+
async importSession(input, context) {
|
|
317
|
+
return importSessionFromPersistence({
|
|
318
|
+
provider: MOCK_LOAD_TEST_PROVIDER_ID,
|
|
319
|
+
request: input,
|
|
320
|
+
context,
|
|
321
|
+
resumeSession: this.resumeSession.bind(this),
|
|
322
|
+
});
|
|
323
|
+
}
|
|
314
324
|
async isAvailable() {
|
|
315
325
|
return true;
|
|
316
326
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentCapabilityFlags, AgentClient, AgentLaunchContext, AgentMode, AgentModelDefinition, AgentPersistenceHandle, AgentProvider, AgentSession, AgentSessionConfig, ListModelsOptions, ListModesOptions
|
|
1
|
+
import type { AgentCapabilityFlags, AgentClient, AgentLaunchContext, AgentMode, AgentModelDefinition, AgentPersistenceHandle, AgentProvider, AgentSession, AgentSessionConfig, ListModelsOptions, ListModesOptions } from "../agent-sdk-types.js";
|
|
2
2
|
export declare const MOCK_SLOW_PROVIDER_ID = "mock-slow";
|
|
3
3
|
export declare class MockSlowProviderClient implements AgentClient {
|
|
4
4
|
readonly provider: AgentProvider;
|
|
@@ -6,7 +6,6 @@ export declare class MockSlowProviderClient implements AgentClient {
|
|
|
6
6
|
isAvailable(): Promise<boolean>;
|
|
7
7
|
listModels(_options: ListModelsOptions): Promise<AgentModelDefinition[]>;
|
|
8
8
|
listModes(_options: ListModesOptions): Promise<AgentMode[]>;
|
|
9
|
-
listPersistedAgents(_options?: ListPersistedAgentsOptions): Promise<PersistedAgentDescriptor[]>;
|
|
10
9
|
getDiagnostic(): Promise<{
|
|
11
10
|
diagnostic: string;
|
|
12
11
|
}>;
|
|
@@ -27,9 +27,6 @@ export class MockSlowProviderClient {
|
|
|
27
27
|
listModes(_options) {
|
|
28
28
|
return neverResolves();
|
|
29
29
|
}
|
|
30
|
-
async listPersistedAgents(_options) {
|
|
31
|
-
return [];
|
|
32
|
-
}
|
|
33
30
|
async getDiagnostic() {
|
|
34
31
|
return {
|
|
35
32
|
diagnostic: "Mock slow provider: dev-only. listModels() never resolves so the snapshot manager will time out.",
|
|
@@ -51,6 +51,7 @@ export declare class TestOpenCodeClient {
|
|
|
51
51
|
sessionCommand: unknown[];
|
|
52
52
|
sessionCreate: unknown[];
|
|
53
53
|
sessionDelete: unknown[];
|
|
54
|
+
sessionGet: unknown[];
|
|
54
55
|
sessionMessages: unknown[];
|
|
55
56
|
sessionPromptAsync: unknown[];
|
|
56
57
|
sessionSummarize: unknown[];
|
|
@@ -73,6 +74,7 @@ export declare class TestOpenCodeClient {
|
|
|
73
74
|
sessionCommandResponse: OpenCodeResponse;
|
|
74
75
|
sessionCreateResponse: OpenCodeResponse;
|
|
75
76
|
sessionDeleteResponse: OpenCodeResponse;
|
|
77
|
+
sessionGetResponse: OpenCodeResponse;
|
|
76
78
|
sessionMessagesResponse: OpenCodeResponse;
|
|
77
79
|
sessionPromptAsyncEvents: unknown[];
|
|
78
80
|
sessionPromptAsyncResponse: OpenCodeResponse;
|
|
@@ -46,6 +46,7 @@ export class TestOpenCodeClient {
|
|
|
46
46
|
sessionCommand: [],
|
|
47
47
|
sessionCreate: [],
|
|
48
48
|
sessionDelete: [],
|
|
49
|
+
sessionGet: [],
|
|
49
50
|
sessionMessages: [],
|
|
50
51
|
sessionPromptAsync: [],
|
|
51
52
|
sessionSummarize: [],
|
|
@@ -67,6 +68,9 @@ export class TestOpenCodeClient {
|
|
|
67
68
|
this.sessionCommandResponse = {};
|
|
68
69
|
this.sessionCreateResponse = { data: { id: "session-1" } };
|
|
69
70
|
this.sessionDeleteResponse = {};
|
|
71
|
+
this.sessionGetResponse = {
|
|
72
|
+
data: { id: "session-1", directory: "/workspace/repo", title: null },
|
|
73
|
+
};
|
|
70
74
|
this.sessionMessagesResponse = { data: [] };
|
|
71
75
|
this.sessionPromptAsyncEvents = [idleEvent()];
|
|
72
76
|
this.sessionPromptAsyncResponse = {};
|
|
@@ -170,6 +174,10 @@ export class TestOpenCodeClient {
|
|
|
170
174
|
this.calls.sessionDelete.push(parameters);
|
|
171
175
|
return this.sessionDeleteResponse;
|
|
172
176
|
},
|
|
177
|
+
get: async (parameters) => {
|
|
178
|
+
this.calls.sessionGet.push(parameters);
|
|
179
|
+
return this.sessionGetResponse;
|
|
180
|
+
},
|
|
173
181
|
messages: async (parameters) => {
|
|
174
182
|
this.calls.sessionMessages.push(parameters);
|
|
175
183
|
return this.sessionMessagesResponse;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AssistantMessage as OpenCodeAssistantMessage, type Event as OpenCodeEvent, type FilePartInput as OpenCodeFilePartInput, type Message as OpenCodeMessage, type OpencodeClient, type Part as OpenCodePart, type TextPartInput as OpenCodeTextPartInput } from "@opencode-ai/sdk/v2/client";
|
|
2
2
|
import type { Logger } from "pino";
|
|
3
|
-
import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentTimelineItem, type AgentUsage, type
|
|
3
|
+
import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentTimelineItem, type AgentUsage, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ResolveAgentCreateConfigInput, type ResolveAgentCreateConfigResult, type ListModelsOptions, type ListModesOptions, type ToolCallTimelineItem } from "../agent-sdk-types.js";
|
|
4
4
|
import { isDefaultAgentCreateConfigUnattended } from "../create-agent-mode.js";
|
|
5
5
|
import { type ProviderRuntimeSettings } from "../provider-launch-config.js";
|
|
6
6
|
import { type OpenCodeRuntime } from "./opencode/runtime.js";
|
|
@@ -120,7 +120,8 @@ export declare class OpenCodeAgentClient implements AgentClient {
|
|
|
120
120
|
listModes(options: ListModesOptions): Promise<AgentMode[]>;
|
|
121
121
|
listCommands(config: AgentSessionConfig): Promise<AgentSlashCommand[]>;
|
|
122
122
|
listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
|
|
123
|
-
|
|
123
|
+
listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
|
|
124
|
+
importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../agent-sdk-types.js").ImportedProviderSession>;
|
|
124
125
|
isAvailable(): Promise<boolean>;
|
|
125
126
|
shutdown(): Promise<void>;
|
|
126
127
|
getDiagnostic(): Promise<{
|
|
@@ -3,6 +3,7 @@ import { createPathEquivalenceMatcher } from "../../../utils/path.js";
|
|
|
3
3
|
import pLimit from "p-limit";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { getAgentStreamEventTurnId, } from "../agent-sdk-types.js";
|
|
6
|
+
import { importSessionFromPersistence } from "../provider-session-import.js";
|
|
6
7
|
import { isDefaultAgentCreateConfigUnattended, resolveDefaultAgentCreateConfig, } from "../create-agent-mode.js";
|
|
7
8
|
import { checkProviderLaunchAvailable, createProviderEnvSpec, resolveProviderLaunch, } from "../provider-launch-config.js";
|
|
8
9
|
import { withTimeout } from "../../../utils/promise-timeout.js";
|
|
@@ -20,6 +21,7 @@ import { revertOpenCodeConversationAndFiles } from "./opencode/rewind.js";
|
|
|
20
21
|
const OPENCODE_CAPABILITIES = {
|
|
21
22
|
supportsStreaming: true,
|
|
22
23
|
supportsSessionPersistence: true,
|
|
24
|
+
supportsSessionListing: true,
|
|
23
25
|
supportsDynamicModes: true,
|
|
24
26
|
supportsMcpServers: true,
|
|
25
27
|
supportsReasoningStream: true,
|
|
@@ -135,8 +137,18 @@ const OPENCODE_PROVIDER_LIST_TIMEOUT_MS = 30000;
|
|
|
135
137
|
const OPENCODE_METADATA_CONCURRENCY = 4;
|
|
136
138
|
const openCodeMetadataLimit = pLimit(OPENCODE_METADATA_CONCURRENCY);
|
|
137
139
|
const OPENCODE_HANDLED_BUILTIN_SLASH_COMMANDS = [
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
+
{
|
|
141
|
+
name: "compact",
|
|
142
|
+
description: "Compact the current session",
|
|
143
|
+
argumentHint: "",
|
|
144
|
+
kind: "command",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "summarize",
|
|
148
|
+
description: "Compact the current session",
|
|
149
|
+
argumentHint: "",
|
|
150
|
+
kind: "command",
|
|
151
|
+
},
|
|
140
152
|
];
|
|
141
153
|
const OPENCODE_HEADERS_TIMEOUT_TOKENS = [
|
|
142
154
|
"headers timeout",
|
|
@@ -616,7 +628,7 @@ function buildOpenCodeUserTimelineText(prompt) {
|
|
|
616
628
|
.filter((text) => text.trim().length > 0)
|
|
617
629
|
.join("\n");
|
|
618
630
|
}
|
|
619
|
-
async function
|
|
631
|
+
async function collectOpenCodeImportableSessionsFromSdk(client, options) {
|
|
620
632
|
const limit = options?.limit ?? OPENCODE_PERSISTED_SESSION_LIMIT;
|
|
621
633
|
const sessionListLimit = options?.cwd ? Math.max(limit, OPENCODE_PERSISTED_SESSION_LIMIT) : limit;
|
|
622
634
|
const response = await client.experimental.session.list({
|
|
@@ -627,39 +639,19 @@ async function collectOpenCodePersistedAgentsFromSdk(client, options) {
|
|
|
627
639
|
if (response.error) {
|
|
628
640
|
throw new Error(`Failed to list OpenCode sessions: ${JSON.stringify(response.error)}`);
|
|
629
641
|
}
|
|
630
|
-
const sessions = response.data ?? [];
|
|
631
642
|
const matchesCwd = options?.cwd ? createPathEquivalenceMatcher(options.cwd) : null;
|
|
632
|
-
|
|
643
|
+
return (response.data ?? [])
|
|
633
644
|
.filter((session) => !matchesCwd || matchesCwd(session.directory))
|
|
634
645
|
.sort((left, right) => getOpenCodeSessionTimestamp(right) - getOpenCodeSessionTimestamp(left))
|
|
635
|
-
.slice(0, limit)
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
async function buildOpenCodePersistedAgentDescriptor(client, session) {
|
|
639
|
-
const messages = await readOpenCodeSessionMessagesFromSdk(client, session);
|
|
640
|
-
const timeline = buildOpenCodeSessionTimeline(messages);
|
|
641
|
-
const modeId = resolveOpenCodePersistedSessionModeId(session, messages);
|
|
642
|
-
const model = resolveOpenCodePersistedSessionModel(session, messages);
|
|
643
|
-
return {
|
|
644
|
-
provider: "opencode",
|
|
645
|
-
sessionId: session.id,
|
|
646
|
+
.slice(0, limit)
|
|
647
|
+
.map((session) => ({
|
|
648
|
+
providerHandleId: session.id,
|
|
646
649
|
cwd: session.directory,
|
|
647
650
|
title: normalizeOpenCodeSessionTitle(session.title),
|
|
651
|
+
firstPromptPreview: null,
|
|
652
|
+
lastPromptPreview: null,
|
|
648
653
|
lastActivityAt: new Date(getOpenCodeSessionTimestamp(session)),
|
|
649
|
-
|
|
650
|
-
provider: "opencode",
|
|
651
|
-
sessionId: session.id,
|
|
652
|
-
nativeHandle: session.id,
|
|
653
|
-
metadata: {
|
|
654
|
-
provider: "opencode",
|
|
655
|
-
cwd: session.directory,
|
|
656
|
-
title: normalizeOpenCodeSessionTitle(session.title),
|
|
657
|
-
...(modeId ? { modeId } : {}),
|
|
658
|
-
...(model ? { model } : {}),
|
|
659
|
-
},
|
|
660
|
-
},
|
|
661
|
-
timeline,
|
|
662
|
-
};
|
|
654
|
+
}));
|
|
663
655
|
}
|
|
664
656
|
function normalizeOpenCodeSessionTitle(title) {
|
|
665
657
|
const normalized = title?.trim();
|
|
@@ -1033,7 +1025,7 @@ export class OpenCodeAgentClient {
|
|
|
1033
1025
|
async listFeatures(config) {
|
|
1034
1026
|
return [buildOpenCodeAutoAcceptFeature(this.assertConfig(config))];
|
|
1035
1027
|
}
|
|
1036
|
-
async
|
|
1028
|
+
async listImportableSessions(options) {
|
|
1037
1029
|
const acquisition = await this.runtime.acquireServer({ force: false });
|
|
1038
1030
|
const { url } = acquisition.server;
|
|
1039
1031
|
const client = this.runtime.createClient({
|
|
@@ -1041,7 +1033,42 @@ export class OpenCodeAgentClient {
|
|
|
1041
1033
|
directory: options?.cwd ?? "",
|
|
1042
1034
|
});
|
|
1043
1035
|
try {
|
|
1044
|
-
return await
|
|
1036
|
+
return await collectOpenCodeImportableSessionsFromSdk(client, options);
|
|
1037
|
+
}
|
|
1038
|
+
finally {
|
|
1039
|
+
acquisition.release();
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
async importSession(input, context) {
|
|
1043
|
+
const acquisition = await this.runtime.acquireServer({ force: false });
|
|
1044
|
+
const { url } = acquisition.server;
|
|
1045
|
+
const client = this.runtime.createClient({
|
|
1046
|
+
baseUrl: url,
|
|
1047
|
+
directory: input.cwd,
|
|
1048
|
+
});
|
|
1049
|
+
try {
|
|
1050
|
+
const sessionResponse = await client.session.get({
|
|
1051
|
+
sessionID: input.providerHandleId,
|
|
1052
|
+
directory: input.cwd,
|
|
1053
|
+
});
|
|
1054
|
+
if (sessionResponse.error || !sessionResponse.data) {
|
|
1055
|
+
throw new Error(`Failed to load OpenCode session ${input.providerHandleId}`);
|
|
1056
|
+
}
|
|
1057
|
+
const session = sessionResponse.data;
|
|
1058
|
+
const messages = await readOpenCodeSessionMessagesFromSdk(client, session);
|
|
1059
|
+
const modeId = resolveOpenCodePersistedSessionModeId(session, messages);
|
|
1060
|
+
const model = resolveOpenCodePersistedSessionModel(session, messages);
|
|
1061
|
+
return await importSessionFromPersistence({
|
|
1062
|
+
provider: "opencode",
|
|
1063
|
+
request: input,
|
|
1064
|
+
context,
|
|
1065
|
+
resumeSession: this.resumeSession.bind(this),
|
|
1066
|
+
config: {
|
|
1067
|
+
title: normalizeOpenCodeSessionTitle(session.title) ?? undefined,
|
|
1068
|
+
...(modeId ? { modeId } : {}),
|
|
1069
|
+
...(model ? { model } : {}),
|
|
1070
|
+
},
|
|
1071
|
+
});
|
|
1045
1072
|
}
|
|
1046
1073
|
finally {
|
|
1047
1074
|
acquisition.release();
|
|
@@ -1179,6 +1206,7 @@ async function listOpenCodeCommandsFromSdk(client, directory) {
|
|
|
1179
1206
|
name: cmd.name,
|
|
1180
1207
|
description: cmd.description ?? "",
|
|
1181
1208
|
argumentHint: cmd.hints?.length ? cmd.hints.join(" ") : "",
|
|
1209
|
+
kind: cmd.source === "skill" ? "skill" : "command",
|
|
1182
1210
|
});
|
|
1183
1211
|
}
|
|
1184
1212
|
return Array.from(commandsByName.values());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { type AgentCapabilityFlags, type AgentClient, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type
|
|
3
|
+
import { type AgentCapabilityFlags, type AgentClient, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ListModesOptions, type ListModelsOptions } from "../../agent-sdk-types.js";
|
|
4
4
|
import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
|
|
5
5
|
import type { PiRuntime, PiRuntimeSession } from "./runtime.js";
|
|
6
6
|
import type { PiSessionState } from "./rpc-types.js";
|
|
@@ -118,7 +118,8 @@ export declare class PiRpcAgentClient implements AgentClient {
|
|
|
118
118
|
resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, _launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
119
119
|
listModels(options: ListModelsOptions): Promise<AgentModelDefinition[]>;
|
|
120
120
|
listModes(_options: ListModesOptions): Promise<AgentMode[]>;
|
|
121
|
-
|
|
121
|
+
listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
|
|
122
|
+
importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../agent-sdk-types.js").ImportedProviderSession>;
|
|
122
123
|
isAvailable(): Promise<boolean>;
|
|
123
124
|
getDiagnostic(): Promise<{
|
|
124
125
|
diagnostic: string;
|
|
@@ -3,6 +3,7 @@ import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
+
import { importSessionFromPersistence } from "../../provider-session-import.js";
|
|
6
7
|
import { runProviderTurn } from "../provider-runner.js";
|
|
7
8
|
import { checkProviderLaunchAvailable, resolveProviderLaunch, } from "../../provider-launch-config.js";
|
|
8
9
|
import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
|
|
@@ -11,7 +12,7 @@ import { buildBinaryDiagnosticRows, formatDiagnosticStatus, formatProviderDiagno
|
|
|
11
12
|
import { getUserMessageText, streamPiHistory, } from "./history-mapper.js";
|
|
12
13
|
import { PiCliRuntime } from "./cli-runtime.js";
|
|
13
14
|
import { revertPiConversation } from "./rewind.js";
|
|
14
|
-
import {
|
|
15
|
+
import { listPiImportableSessions } from "./session-descriptor.js";
|
|
15
16
|
import { mapToolDetail, parseToolArgs, parseToolResult, resolveToolCallName, } from "./tool-call-mapper.js";
|
|
16
17
|
const PI_PROVIDER = "pi";
|
|
17
18
|
const DEFAULT_PI_THINKING_LEVEL = "medium";
|
|
@@ -35,16 +36,25 @@ const PI_HANDLED_BUILTIN_SLASH_COMMANDS = [
|
|
|
35
36
|
name: "compact",
|
|
36
37
|
description: "Manually compact the session context",
|
|
37
38
|
argumentHint: "[instructions]",
|
|
39
|
+
kind: "command",
|
|
38
40
|
},
|
|
39
41
|
{
|
|
40
42
|
name: "autocompact",
|
|
41
43
|
description: "Toggle automatic context compaction",
|
|
42
44
|
argumentHint: "[on|off|toggle]",
|
|
45
|
+
kind: "command",
|
|
43
46
|
},
|
|
44
47
|
];
|
|
48
|
+
function mapPiCommandKind(source) {
|
|
49
|
+
if (source === "skill") {
|
|
50
|
+
return "skill";
|
|
51
|
+
}
|
|
52
|
+
return "command";
|
|
53
|
+
}
|
|
45
54
|
const PI_CAPABILITIES = {
|
|
46
55
|
supportsStreaming: true,
|
|
47
56
|
supportsSessionPersistence: true,
|
|
57
|
+
supportsSessionListing: true,
|
|
48
58
|
supportsDynamicModes: true,
|
|
49
59
|
supportsMcpServers: false,
|
|
50
60
|
supportsReasoningStream: true,
|
|
@@ -62,7 +72,12 @@ const PI_THINKING_OPTIONS = [
|
|
|
62
72
|
{ id: "xhigh", label: "XHigh", description: "Maximum reasoning" },
|
|
63
73
|
];
|
|
64
74
|
function normalizePiModelLabel(label) {
|
|
65
|
-
|
|
75
|
+
const normalizedLabel = label.trim().replace(/[_\s]+/g, " ");
|
|
76
|
+
const vendorSeparatorIndex = normalizedLabel.indexOf(": ");
|
|
77
|
+
if (vendorSeparatorIndex === -1) {
|
|
78
|
+
return normalizedLabel;
|
|
79
|
+
}
|
|
80
|
+
return normalizedLabel.slice(vendorSeparatorIndex + 2).trim();
|
|
66
81
|
}
|
|
67
82
|
export function transformPiModels(models) {
|
|
68
83
|
return models.map((model) => {
|
|
@@ -863,6 +878,7 @@ export class PiRpcAgentSession {
|
|
|
863
878
|
name: command.name,
|
|
864
879
|
description: command.description ?? command.source,
|
|
865
880
|
argumentHint: knownCommand?.argumentHint ?? "",
|
|
881
|
+
kind: mapPiCommandKind(command.source),
|
|
866
882
|
});
|
|
867
883
|
}
|
|
868
884
|
return [...mappedCommands.values()];
|
|
@@ -1533,14 +1549,21 @@ export class PiRpcAgentClient {
|
|
|
1533
1549
|
async listModes(_options) {
|
|
1534
1550
|
return [];
|
|
1535
1551
|
}
|
|
1536
|
-
async
|
|
1537
|
-
return await
|
|
1552
|
+
async listImportableSessions(options) {
|
|
1553
|
+
return await listPiImportableSessions({
|
|
1538
1554
|
...options,
|
|
1539
|
-
provider: PI_PROVIDER,
|
|
1540
1555
|
sessionDir: this.providerParams.sessionDir,
|
|
1541
1556
|
runtimeSettings: this.runtimeSettings,
|
|
1542
1557
|
});
|
|
1543
1558
|
}
|
|
1559
|
+
async importSession(input, context) {
|
|
1560
|
+
return importSessionFromPersistence({
|
|
1561
|
+
provider: PI_PROVIDER,
|
|
1562
|
+
request: input,
|
|
1563
|
+
context,
|
|
1564
|
+
resumeSession: this.resumeSession.bind(this),
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1544
1567
|
async isAvailable() {
|
|
1545
1568
|
const launch = await this.resolvePiLaunch();
|
|
1546
1569
|
const availability = await checkProviderLaunchAvailable(launch);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ImportableProviderSession, ListImportableSessionsOptions } from "../../agent-sdk-types.js";
|
|
2
2
|
import type { ProviderRuntimeSettings } from "../../provider-launch-config.js";
|
|
3
|
-
interface PiSessionDescriptorOptions extends
|
|
4
|
-
provider?: string;
|
|
3
|
+
interface PiSessionDescriptorOptions extends ListImportableSessionsOptions {
|
|
5
4
|
sessionDir?: string;
|
|
6
5
|
runtimeSettings?: ProviderRuntimeSettings;
|
|
7
6
|
env?: NodeJS.ProcessEnv;
|
|
8
7
|
homeDir?: string;
|
|
9
8
|
}
|
|
10
|
-
export declare function
|
|
9
|
+
export declare function listPiImportableSessions(options?: PiSessionDescriptorOptions): Promise<ImportableProviderSession[]>;
|
|
11
10
|
export {};
|
|
12
11
|
//# sourceMappingURL=session-descriptor.d.ts.map
|
|
@@ -2,29 +2,27 @@ import { open, readdir, readFile, stat } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createRealpathAwarePathMatcher } from "../../../../utils/path.js";
|
|
5
|
-
const PI_PROVIDER = "pi";
|
|
6
5
|
const PI_CONFIG_DIR_NAME = ".pi";
|
|
7
6
|
const PI_AGENT_DIR_ENV = "PI_CODING_AGENT_DIR";
|
|
8
7
|
const PI_SESSION_DIR_ENV = "PI_CODING_AGENT_SESSION_DIR";
|
|
9
8
|
const HEAD_BYTES = 64 * 1024;
|
|
10
9
|
const TAIL_BYTES = 256 * 1024;
|
|
11
10
|
const FULL_SCAN_LINE_LIMIT = 2000;
|
|
12
|
-
export async function
|
|
13
|
-
const provider = options.provider ?? PI_PROVIDER;
|
|
11
|
+
export async function listPiImportableSessions(options = {}) {
|
|
14
12
|
const sessionsDir = await resolvePiSessionsDir(options);
|
|
15
13
|
const files = await walkJsonlFiles(sessionsDir);
|
|
16
14
|
const matchesCwd = options.cwd ? createRealpathAwarePathMatcher(options.cwd) : null;
|
|
17
15
|
const limit = options.limit ?? 20;
|
|
18
|
-
const
|
|
16
|
+
const sessions = [];
|
|
19
17
|
for (const file of files) {
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
18
|
+
const session = await readPiImportableSession(file);
|
|
19
|
+
if (!session)
|
|
22
20
|
continue;
|
|
23
|
-
if (matchesCwd && !matchesCwd(
|
|
21
|
+
if (matchesCwd && !matchesCwd(session.cwd))
|
|
24
22
|
continue;
|
|
25
|
-
|
|
23
|
+
sessions.push(session);
|
|
26
24
|
}
|
|
27
|
-
return
|
|
25
|
+
return sessions
|
|
28
26
|
.sort((left, right) => right.lastActivityAt.getTime() - left.lastActivityAt.getTime())
|
|
29
27
|
.slice(0, limit);
|
|
30
28
|
}
|
|
@@ -104,7 +102,7 @@ async function walkJsonlFiles(root) {
|
|
|
104
102
|
}));
|
|
105
103
|
return files.flat();
|
|
106
104
|
}
|
|
107
|
-
async function
|
|
105
|
+
async function readPiImportableSession(filePath) {
|
|
108
106
|
const firstLine = await readFirstLine(filePath);
|
|
109
107
|
if (!firstLine)
|
|
110
108
|
return null;
|
|
@@ -116,27 +114,13 @@ async function readPiSessionDescriptor(filePath, provider) {
|
|
|
116
114
|
const headInfo = await scanSessionHead(filePath);
|
|
117
115
|
const title = tailInfo.title ?? headInfo.title ?? headInfo.firstUserMessage;
|
|
118
116
|
const lastActivityAt = tailInfo.lastActivityAt ?? (await readFileMtime(filePath)) ?? header.createdAt ?? new Date(0);
|
|
119
|
-
const timeline = buildPreviewTimeline({
|
|
120
|
-
firstUserMessage: headInfo.firstUserMessage,
|
|
121
|
-
lastUserMessage: tailInfo.lastUserMessage,
|
|
122
|
-
});
|
|
123
|
-
const persistence = {
|
|
124
|
-
provider,
|
|
125
|
-
sessionId: header.sessionId,
|
|
126
|
-
nativeHandle: filePath,
|
|
127
|
-
metadata: {
|
|
128
|
-
provider,
|
|
129
|
-
cwd: header.cwd,
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
117
|
return {
|
|
133
|
-
|
|
134
|
-
sessionId: header.sessionId,
|
|
118
|
+
providerHandleId: filePath,
|
|
135
119
|
cwd: header.cwd,
|
|
136
120
|
title,
|
|
121
|
+
firstPromptPreview: normalizePromptPreview(headInfo.firstUserMessage),
|
|
122
|
+
lastPromptPreview: normalizePromptPreview(tailInfo.lastUserMessage ?? headInfo.firstUserMessage),
|
|
137
123
|
lastActivityAt,
|
|
138
|
-
persistence,
|
|
139
|
-
timeline,
|
|
140
124
|
};
|
|
141
125
|
}
|
|
142
126
|
async function readFirstLine(filePath) {
|
|
@@ -254,16 +238,6 @@ async function scanSessionHead(filePath) {
|
|
|
254
238
|
}
|
|
255
239
|
return { title, firstUserMessage };
|
|
256
240
|
}
|
|
257
|
-
function buildPreviewTimeline(input) {
|
|
258
|
-
const items = [];
|
|
259
|
-
if (input.firstUserMessage) {
|
|
260
|
-
items.push({ type: "user_message", text: input.firstUserMessage });
|
|
261
|
-
}
|
|
262
|
-
if (input.lastUserMessage && input.lastUserMessage !== input.firstUserMessage) {
|
|
263
|
-
items.push({ type: "user_message", text: input.lastUserMessage });
|
|
264
|
-
}
|
|
265
|
-
return items;
|
|
266
|
-
}
|
|
267
241
|
function parseJsonRecord(line) {
|
|
268
242
|
if (!line)
|
|
269
243
|
return null;
|
|
@@ -281,6 +255,12 @@ function isRecord(value) {
|
|
|
281
255
|
function readNonEmptyString(value) {
|
|
282
256
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
283
257
|
}
|
|
258
|
+
function normalizePromptPreview(text) {
|
|
259
|
+
const normalized = text?.trim().replace(/\s+/g, " ") ?? "";
|
|
260
|
+
if (!normalized)
|
|
261
|
+
return null;
|
|
262
|
+
return normalized.length > 160 ? normalized.slice(0, 160) : normalized;
|
|
263
|
+
}
|
|
284
264
|
function parseDate(value) {
|
|
285
265
|
if (typeof value !== "string" && typeof value !== "number") {
|
|
286
266
|
return null;
|
|
@@ -2269,7 +2269,6 @@ export class Session {
|
|
|
2269
2269
|
logger: this.sessionLogger,
|
|
2270
2270
|
});
|
|
2271
2271
|
await this.registerWorkspaceForImportedAgent(snapshot.cwd);
|
|
2272
|
-
await this.forwardAgentUpdate(snapshot);
|
|
2273
2272
|
const agentPayload = await this.buildAgentPayload(snapshot);
|
|
2274
2273
|
this.emit({
|
|
2275
2274
|
type: "status",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.93",
|
|
4
4
|
"description": "Paseo backend server",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/server",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@agentclientprotocol/sdk": "^0.17.1",
|
|
61
61
|
"@anthropic-ai/claude-agent-sdk": "^0.2.133",
|
|
62
|
-
"@getpaseo/client": "0.1.
|
|
63
|
-
"@getpaseo/highlight": "0.1.
|
|
64
|
-
"@getpaseo/protocol": "0.1.
|
|
65
|
-
"@getpaseo/relay": "0.1.
|
|
62
|
+
"@getpaseo/client": "0.1.93",
|
|
63
|
+
"@getpaseo/highlight": "0.1.93",
|
|
64
|
+
"@getpaseo/protocol": "0.1.93",
|
|
65
|
+
"@getpaseo/relay": "0.1.93",
|
|
66
66
|
"@isaacs/ttlcache": "^2.1.4",
|
|
67
67
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
68
68
|
"@opencode-ai/sdk": "1.14.46",
|