@getpaseo/server 0.1.91-beta.2 → 0.1.92
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/scripts/supervisor.js +21 -0
- package/dist/server/server/agent/agent-manager.d.ts +13 -5
- package/dist/server/server/agent/agent-manager.js +110 -74
- 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/prompt-attachments.js +8 -0
- package/dist/server/server/agent/provider-registry.d.ts +0 -1
- package/dist/server/server/agent/provider-registry.js +55 -16
- 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/codex-app-server-agent.d.ts +3 -2
- package/dist/server/server/agent/providers/codex-app-server-agent.js +29 -26
- 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 +3 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +12 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts +18 -3
- package/dist/server/server/agent/providers/opencode-agent.js +135 -36
- package/dist/server/server/agent/providers/pi/agent.d.ts +25 -2
- package/dist/server/server/agent/providers/pi/agent.js +243 -14
- package/dist/server/server/agent/providers/pi/cli-runtime.js +9 -0
- package/dist/server/server/agent/providers/pi/rpc-types.d.ts +9 -0
- package/dist/server/server/agent/providers/pi/runtime.d.ts +2 -0
- package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +11 -0
- package/dist/server/server/agent/providers/pi/session-descriptor.js +284 -0
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +8 -0
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +22 -0
- package/dist/server/server/agent/runtime-mcp-config.d.ts +8 -0
- package/dist/server/server/agent/runtime-mcp-config.js +50 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +2 -2
- package/dist/server/server/daemon-worker.js +84 -1
- package/dist/server/server/file-upload/index.d.ts +27 -0
- package/dist/server/server/file-upload/index.js +158 -0
- package/dist/server/server/loop-service.d.ts +12 -12
- package/dist/server/server/persisted-config.d.ts +8 -0
- package/dist/server/server/persisted-config.js +1 -1
- package/dist/server/server/persistence-hooks.js +6 -4
- package/dist/server/server/session.d.ts +5 -2
- package/dist/server/server/session.js +20 -3
- package/dist/server/server/speech/providers/local/runtime.js +1 -0
- package/dist/server/server/speech/providers/local/worker-client.d.ts +14 -1
- package/dist/server/server/speech/providers/local/worker-client.js +169 -7
- package/dist/server/server/websocket-server.d.ts +2 -0
- package/dist/server/server/websocket-server.js +20 -7
- package/dist/server/server/workspace-registry.d.ts +4 -4
- package/dist/src/server/persisted-config.js +1 -1
- package/package.json +5 -5
|
@@ -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,9 +74,11 @@ 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;
|
|
81
|
+
sessionSummarizeEvents: unknown[];
|
|
79
82
|
sessionSummarizeResponse: OpenCodeResponse;
|
|
80
83
|
sessionUpdateResponse: OpenCodeResponse;
|
|
81
84
|
private readonly queuedEventStream;
|
|
@@ -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,9 +68,13 @@ 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 = {};
|
|
77
|
+
this.sessionSummarizeEvents = [idleEvent()];
|
|
73
78
|
this.sessionSummarizeResponse = { data: {} };
|
|
74
79
|
this.sessionUpdateResponse = {};
|
|
75
80
|
this.queuedEventStream = createQueuedEventStream();
|
|
@@ -169,6 +174,10 @@ export class TestOpenCodeClient {
|
|
|
169
174
|
this.calls.sessionDelete.push(parameters);
|
|
170
175
|
return this.sessionDeleteResponse;
|
|
171
176
|
},
|
|
177
|
+
get: async (parameters) => {
|
|
178
|
+
this.calls.sessionGet.push(parameters);
|
|
179
|
+
return this.sessionGetResponse;
|
|
180
|
+
},
|
|
172
181
|
messages: async (parameters) => {
|
|
173
182
|
this.calls.sessionMessages.push(parameters);
|
|
174
183
|
return this.sessionMessagesResponse;
|
|
@@ -182,6 +191,9 @@ export class TestOpenCodeClient {
|
|
|
182
191
|
},
|
|
183
192
|
summarize: async (parameters) => {
|
|
184
193
|
this.calls.sessionSummarize.push(parameters);
|
|
194
|
+
for (const event of this.sessionSummarizeEvents) {
|
|
195
|
+
this.emitEvent(event);
|
|
196
|
+
}
|
|
185
197
|
return this.sessionSummarizeResponse;
|
|
186
198
|
},
|
|
187
199
|
update: async (parameters) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type AssistantMessage as OpenCodeAssistantMessage, type Event as OpenCodeEvent, type FilePartInput as OpenCodeFilePartInput, type OpencodeClient, type TextPartInput as OpenCodeTextPartInput } from "@opencode-ai/sdk/v2/client";
|
|
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 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";
|
|
@@ -10,6 +10,10 @@ type OpenCodeAgentConfig = AgentSessionConfig & {
|
|
|
10
10
|
provider: "opencode";
|
|
11
11
|
};
|
|
12
12
|
type OpenCodeMessageRole = "user" | "assistant";
|
|
13
|
+
interface OpenCodeSessionMessage {
|
|
14
|
+
info: OpenCodeMessage;
|
|
15
|
+
parts: OpenCodePart[];
|
|
16
|
+
}
|
|
13
17
|
declare function reconcileOpenCodeSessionClose(params: {
|
|
14
18
|
client: Pick<OpencodeClient, "session">;
|
|
15
19
|
sessionId: string;
|
|
@@ -79,8 +83,10 @@ declare function mergeOpenCodeStepFinishUsage(usage: AgentUsage, part: {
|
|
|
79
83
|
}): void;
|
|
80
84
|
declare function hasNormalizedOpenCodeUsage(usage: AgentUsage): boolean;
|
|
81
85
|
declare function buildOpenCodePromptParts(prompt: AgentPromptInput): Array<OpenCodeTextPartInput | OpenCodeFilePartInput>;
|
|
86
|
+
declare function buildOpenCodeSessionTimeline(messages: ReadonlyArray<OpenCodeSessionMessage>): AgentTimelineItem[];
|
|
82
87
|
export declare const __openCodeInternals: {
|
|
83
88
|
buildOpenCodePromptParts: typeof buildOpenCodePromptParts;
|
|
89
|
+
buildOpenCodeSessionTimeline: typeof buildOpenCodeSessionTimeline;
|
|
84
90
|
buildOpenCodeModelContextWindowLookup: typeof buildOpenCodeModelContextWindowLookup;
|
|
85
91
|
buildOpenCodeModelDefinition: typeof buildOpenCodeModelDefinition;
|
|
86
92
|
buildOpenCodeModelLookupKey: typeof buildOpenCodeModelLookupKey;
|
|
@@ -114,7 +120,8 @@ export declare class OpenCodeAgentClient implements AgentClient {
|
|
|
114
120
|
listModes(options: ListModesOptions): Promise<AgentMode[]>;
|
|
115
121
|
listCommands(config: AgentSessionConfig): Promise<AgentSlashCommand[]>;
|
|
116
122
|
listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
|
|
117
|
-
|
|
123
|
+
listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
|
|
124
|
+
importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../agent-sdk-types.js").ImportedProviderSession>;
|
|
118
125
|
isAvailable(): Promise<boolean>;
|
|
119
126
|
shutdown(): Promise<void>;
|
|
120
127
|
getDiagnostic(): Promise<{
|
|
@@ -133,6 +140,11 @@ export interface OpenCodeEventTranslationState {
|
|
|
133
140
|
sessionTotalCostUsd?: number;
|
|
134
141
|
streamedPartKeys: Set<string>;
|
|
135
142
|
emittedStructuredMessageIds: Set<string>;
|
|
143
|
+
compactionSummaryMessageIds: Set<string>;
|
|
144
|
+
emittedCompactionPartIds: Set<string>;
|
|
145
|
+
suppressAssistantMessagesUntilIdle?: {
|
|
146
|
+
active: boolean;
|
|
147
|
+
};
|
|
136
148
|
/** Tracks the type of each part by ID, learned from message.part.updated events. */
|
|
137
149
|
partTypes: Map<string, string>;
|
|
138
150
|
subAgentsByCallId?: Map<string, OpenCodeSubAgentActivityState>;
|
|
@@ -186,6 +198,9 @@ declare class OpenCodeAgentSession implements AgentSession {
|
|
|
186
198
|
private streamedPartKeys;
|
|
187
199
|
/** Tracks assistant messages already emitted from structured payloads. */
|
|
188
200
|
private emittedStructuredMessageIds;
|
|
201
|
+
private compactionSummaryMessageIds;
|
|
202
|
+
private emittedCompactionPartIds;
|
|
203
|
+
private suppressAssistantMessagesUntilIdle;
|
|
189
204
|
/** Tracks the type of each part by ID, learned from message.part.updated events. */
|
|
190
205
|
private partTypes;
|
|
191
206
|
private availableModesCache;
|
|
@@ -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();
|
|
@@ -728,6 +720,13 @@ function buildOpenCodeReplayPartTimelineEvent(params) {
|
|
|
728
720
|
part,
|
|
729
721
|
});
|
|
730
722
|
}
|
|
723
|
+
function isOpenCodeCompactionSummaryMessage(message) {
|
|
724
|
+
return (message.role === "assistant" &&
|
|
725
|
+
(message.summary === true || message.agent === "compaction" || message.mode === "compaction"));
|
|
726
|
+
}
|
|
727
|
+
function findOpenCodeCompactionPart(message) {
|
|
728
|
+
return message.parts.find((part) => part.type === "compaction");
|
|
729
|
+
}
|
|
731
730
|
async function readOpenCodeSessionMessagesFromSdk(client, session) {
|
|
732
731
|
const response = await client.session.messages({
|
|
733
732
|
sessionID: session.id,
|
|
@@ -739,7 +738,24 @@ async function readOpenCodeSessionMessagesFromSdk(client, session) {
|
|
|
739
738
|
return filterOpenCodeRevertedMessages(response.data, session.revert);
|
|
740
739
|
}
|
|
741
740
|
function buildOpenCodeSessionTimeline(messages) {
|
|
742
|
-
|
|
741
|
+
const timeline = [];
|
|
742
|
+
let hideNextAssistantAfterCompaction = false;
|
|
743
|
+
for (const message of messages) {
|
|
744
|
+
const compactionPart = findOpenCodeCompactionPart(message);
|
|
745
|
+
if (message.info.role === "assistant" && hideNextAssistantAfterCompaction) {
|
|
746
|
+
hideNextAssistantAfterCompaction = false;
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
if (message.info.role === "user" && !compactionPart) {
|
|
750
|
+
hideNextAssistantAfterCompaction = false;
|
|
751
|
+
}
|
|
752
|
+
timeline.push(...buildOpenCodeReplayTimelineEvents(message).map((event) => event.item));
|
|
753
|
+
if (message.info.role === "user" && compactionPart) {
|
|
754
|
+
timeline.push(createCompactionTimelineItem("completed", compactionPart.auto ? "auto" : "manual"));
|
|
755
|
+
hideNextAssistantAfterCompaction = true;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return timeline;
|
|
743
759
|
}
|
|
744
760
|
function filterOpenCodeRevertedMessages(messages, revert) {
|
|
745
761
|
if (!revert?.messageID || revert.partID) {
|
|
@@ -778,6 +794,9 @@ function readOpenCodeMessageModel(message) {
|
|
|
778
794
|
}
|
|
779
795
|
function buildOpenCodeReplayTimelineEvents(message) {
|
|
780
796
|
const { info, parts } = message;
|
|
797
|
+
if (isOpenCodeCompactionSummaryMessage(info)) {
|
|
798
|
+
return [];
|
|
799
|
+
}
|
|
781
800
|
if (info.role === "user") {
|
|
782
801
|
const text = parts
|
|
783
802
|
.filter((part) => part.type === "text")
|
|
@@ -816,6 +835,7 @@ function buildOpenCodeReplayTimelineEvents(message) {
|
|
|
816
835
|
}
|
|
817
836
|
export const __openCodeInternals = {
|
|
818
837
|
buildOpenCodePromptParts,
|
|
838
|
+
buildOpenCodeSessionTimeline,
|
|
819
839
|
buildOpenCodeModelContextWindowLookup,
|
|
820
840
|
buildOpenCodeModelDefinition,
|
|
821
841
|
buildOpenCodeModelLookupKey,
|
|
@@ -1005,7 +1025,7 @@ export class OpenCodeAgentClient {
|
|
|
1005
1025
|
async listFeatures(config) {
|
|
1006
1026
|
return [buildOpenCodeAutoAcceptFeature(this.assertConfig(config))];
|
|
1007
1027
|
}
|
|
1008
|
-
async
|
|
1028
|
+
async listImportableSessions(options) {
|
|
1009
1029
|
const acquisition = await this.runtime.acquireServer({ force: false });
|
|
1010
1030
|
const { url } = acquisition.server;
|
|
1011
1031
|
const client = this.runtime.createClient({
|
|
@@ -1013,7 +1033,42 @@ export class OpenCodeAgentClient {
|
|
|
1013
1033
|
directory: options?.cwd ?? "",
|
|
1014
1034
|
});
|
|
1015
1035
|
try {
|
|
1016
|
-
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
|
+
});
|
|
1017
1072
|
}
|
|
1018
1073
|
finally {
|
|
1019
1074
|
acquisition.release();
|
|
@@ -1151,6 +1206,7 @@ async function listOpenCodeCommandsFromSdk(client, directory) {
|
|
|
1151
1206
|
name: cmd.name,
|
|
1152
1207
|
description: cmd.description ?? "",
|
|
1153
1208
|
argumentHint: cmd.hints?.length ? cmd.hints.join(" ") : "",
|
|
1209
|
+
kind: cmd.source === "skill" ? "skill" : "command",
|
|
1154
1210
|
});
|
|
1155
1211
|
}
|
|
1156
1212
|
return Array.from(commandsByName.values());
|
|
@@ -1370,6 +1426,11 @@ export function translateOpenCodeEvent(event, state) {
|
|
|
1370
1426
|
function resetOpenCodeTurnTrackingState(state) {
|
|
1371
1427
|
state.streamedPartKeys.clear();
|
|
1372
1428
|
state.partTypes.clear();
|
|
1429
|
+
state.compactionSummaryMessageIds.clear();
|
|
1430
|
+
state.emittedCompactionPartIds.clear();
|
|
1431
|
+
if (state.suppressAssistantMessagesUntilIdle) {
|
|
1432
|
+
state.suppressAssistantMessagesUntilIdle.active = false;
|
|
1433
|
+
}
|
|
1373
1434
|
}
|
|
1374
1435
|
function getOpenCodeSubAgentMaps(state) {
|
|
1375
1436
|
state.subAgentsByCallId ?? (state.subAgentsByCallId = new Map());
|
|
@@ -1592,6 +1653,14 @@ function appendOpenCodeMessageUpdated(event, state, events) {
|
|
|
1592
1653
|
if (info.role !== "assistant") {
|
|
1593
1654
|
return;
|
|
1594
1655
|
}
|
|
1656
|
+
if (state.suppressAssistantMessagesUntilIdle?.active) {
|
|
1657
|
+
state.compactionSummaryMessageIds.add(info.id);
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
if (isOpenCodeCompactionSummaryMessage(info)) {
|
|
1661
|
+
state.compactionSummaryMessageIds.add(info.id);
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1595
1664
|
const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
|
|
1596
1665
|
if (modelLookupKey) {
|
|
1597
1666
|
const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
|
|
@@ -1638,6 +1707,13 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1638
1707
|
}
|
|
1639
1708
|
const messageRole = state.messageRoles.get(part.messageID);
|
|
1640
1709
|
state.partTypes.set(part.id, part.type);
|
|
1710
|
+
if (state.compactionSummaryMessageIds.has(part.messageID)) {
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
if (shouldSuppressOpenCodeAssistantPart(part, messageRole, state)) {
|
|
1714
|
+
state.compactionSummaryMessageIds.add(part.messageID);
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1641
1717
|
if (part.type === "text") {
|
|
1642
1718
|
appendOpenCodeTextPart(part, messageRole, state, events);
|
|
1643
1719
|
return;
|
|
@@ -1654,6 +1730,10 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1654
1730
|
return;
|
|
1655
1731
|
}
|
|
1656
1732
|
if (part.type === "compaction") {
|
|
1733
|
+
if (state.emittedCompactionPartIds.has(part.id)) {
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
state.emittedCompactionPartIds.add(part.id);
|
|
1657
1737
|
events.push({
|
|
1658
1738
|
type: "timeline",
|
|
1659
1739
|
provider: "opencode",
|
|
@@ -1678,6 +1758,11 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1678
1758
|
}
|
|
1679
1759
|
}
|
|
1680
1760
|
}
|
|
1761
|
+
function shouldSuppressOpenCodeAssistantPart(part, messageRole, state) {
|
|
1762
|
+
return (state.suppressAssistantMessagesUntilIdle?.active === true &&
|
|
1763
|
+
part.type === "text" &&
|
|
1764
|
+
messageRole !== "user");
|
|
1765
|
+
}
|
|
1681
1766
|
function appendOpenCodeTextPart(part, messageRole, state, events) {
|
|
1682
1767
|
if (messageRole === "user") {
|
|
1683
1768
|
return;
|
|
@@ -1724,6 +1809,9 @@ function appendOpenCodeMessagePartDelta(event, state, events) {
|
|
|
1724
1809
|
const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
|
|
1725
1810
|
const knownPartType = partID ? state.partTypes.get(partID) : undefined;
|
|
1726
1811
|
const isReasoning = knownPartType === "reasoning" || field === "reasoning";
|
|
1812
|
+
if (messageID && state.compactionSummaryMessageIds.has(messageID)) {
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1727
1815
|
if (isReasoning) {
|
|
1728
1816
|
if (partID) {
|
|
1729
1817
|
state.streamedPartKeys.add(`reasoning:${partID}`);
|
|
@@ -1741,6 +1829,10 @@ function appendOpenCodeMessagePartDelta(event, state, events) {
|
|
|
1741
1829
|
if (messageRole === "user") {
|
|
1742
1830
|
return;
|
|
1743
1831
|
}
|
|
1832
|
+
if (messageID && state.suppressAssistantMessagesUntilIdle?.active === true) {
|
|
1833
|
+
state.compactionSummaryMessageIds.add(messageID);
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1744
1836
|
if (partID) {
|
|
1745
1837
|
state.streamedPartKeys.add(`text:${partID}`);
|
|
1746
1838
|
}
|
|
@@ -1938,6 +2030,9 @@ class OpenCodeAgentSession {
|
|
|
1938
2030
|
this.streamedPartKeys = new Set();
|
|
1939
2031
|
/** Tracks assistant messages already emitted from structured payloads. */
|
|
1940
2032
|
this.emittedStructuredMessageIds = new Set();
|
|
2033
|
+
this.compactionSummaryMessageIds = new Set();
|
|
2034
|
+
this.emittedCompactionPartIds = new Set();
|
|
2035
|
+
this.suppressAssistantMessagesUntilIdle = { active: false };
|
|
1941
2036
|
/** Tracks the type of each part by ID, learned from message.part.updated events. */
|
|
1942
2037
|
this.partTypes = new Map();
|
|
1943
2038
|
this.availableModesCache = null;
|
|
@@ -2069,6 +2164,7 @@ class OpenCodeAgentSession {
|
|
|
2069
2164
|
this.accumulatedUsage = contextWindowMaxTokens !== undefined ? { contextWindowMaxTokens } : {};
|
|
2070
2165
|
const parts = buildOpenCodePromptParts(prompt);
|
|
2071
2166
|
this.pendingUserMessageText = buildOpenCodeUserTimelineText(prompt);
|
|
2167
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2072
2168
|
const model = this.parseModel(this.config.model);
|
|
2073
2169
|
const thinkingOptionId = this.config.thinkingOptionId;
|
|
2074
2170
|
const effectiveVariant = thinkingOptionId ?? undefined;
|
|
@@ -2088,6 +2184,7 @@ class OpenCodeAgentSession {
|
|
|
2088
2184
|
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
|
2089
2185
|
if (slashCommand) {
|
|
2090
2186
|
if (slashCommand.commandName === "compact" || slashCommand.commandName === "summarize") {
|
|
2187
|
+
this.suppressAssistantMessagesUntilIdle.active = true;
|
|
2091
2188
|
void this.client.session
|
|
2092
2189
|
.summarize({
|
|
2093
2190
|
sessionID: this.sessionId,
|
|
@@ -2096,18 +2193,17 @@ class OpenCodeAgentSession {
|
|
|
2096
2193
|
})
|
|
2097
2194
|
.then((response) => {
|
|
2098
2195
|
if (response.error) {
|
|
2196
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2099
2197
|
this.finishForegroundTurn({
|
|
2100
2198
|
type: "turn_failed",
|
|
2101
2199
|
provider: "opencode",
|
|
2102
2200
|
error: toDiagnosticErrorMessage(response.error),
|
|
2103
2201
|
}, turnId);
|
|
2104
2202
|
}
|
|
2105
|
-
else {
|
|
2106
|
-
this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
|
|
2107
|
-
}
|
|
2108
2203
|
return;
|
|
2109
2204
|
})
|
|
2110
2205
|
.catch((error) => {
|
|
2206
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2111
2207
|
this.finishForegroundTurn({
|
|
2112
2208
|
type: "turn_failed",
|
|
2113
2209
|
provider: "opencode",
|
|
@@ -2710,6 +2806,9 @@ class OpenCodeAgentSession {
|
|
|
2710
2806
|
sessionTotalCostUsd: this.sessionTotalCostUsd,
|
|
2711
2807
|
streamedPartKeys: this.streamedPartKeys,
|
|
2712
2808
|
emittedStructuredMessageIds: this.emittedStructuredMessageIds,
|
|
2809
|
+
compactionSummaryMessageIds: this.compactionSummaryMessageIds,
|
|
2810
|
+
emittedCompactionPartIds: this.emittedCompactionPartIds,
|
|
2811
|
+
suppressAssistantMessagesUntilIdle: this.suppressAssistantMessagesUntilIdle,
|
|
2713
2812
|
partTypes: this.partTypes,
|
|
2714
2813
|
subAgentsByCallId: this.subAgentsByCallId,
|
|
2715
2814
|
subAgentCallIdByChildSessionId: this.subAgentCallIdByChildSessionId,
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
import {
|
|
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 ImportableProviderSession, type ImportProviderSessionContext, type ImportProviderSessionInput, type ListImportableSessionsOptions, type ListModesOptions, type ListModelsOptions } from "../../agent-sdk-types.js";
|
|
3
4
|
import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
|
|
4
5
|
import type { PiRuntime, PiRuntimeSession } from "./runtime.js";
|
|
5
6
|
import type { PiSessionState } from "./rpc-types.js";
|
|
7
|
+
export declare const PiProviderParamsSchema: z.ZodObject<{
|
|
8
|
+
sessionDir: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strict", z.ZodTypeAny, {
|
|
10
|
+
sessionDir?: string | undefined;
|
|
11
|
+
}, {
|
|
12
|
+
sessionDir?: string | undefined;
|
|
13
|
+
}>;
|
|
6
14
|
interface PiRpcAgentClientOptions {
|
|
7
15
|
logger: Logger;
|
|
8
16
|
runtimeSettings?: ProviderRuntimeSettings;
|
|
17
|
+
providerParams?: unknown;
|
|
9
18
|
runtime?: PiRuntime;
|
|
10
19
|
}
|
|
11
20
|
interface StartTurnResult {
|
|
@@ -35,6 +44,9 @@ export declare class PiRpcAgentSession implements AgentSession {
|
|
|
35
44
|
private readonly seenUserEntryIds;
|
|
36
45
|
private readonly pendingUserMessages;
|
|
37
46
|
private readonly pendingExtensionResults;
|
|
47
|
+
private outOfBandCompactionEmit;
|
|
48
|
+
private outOfBandCompactionStarted;
|
|
49
|
+
private outOfBandCompactionCompleted;
|
|
38
50
|
private state;
|
|
39
51
|
private closed;
|
|
40
52
|
constructor(options: PiRpcAgentSessionOptions);
|
|
@@ -60,10 +72,18 @@ export declare class PiRpcAgentSession implements AgentSession {
|
|
|
60
72
|
private runPiTreeExtensionCommand;
|
|
61
73
|
close(): Promise<void>;
|
|
62
74
|
listCommands(): Promise<AgentSlashCommand[]>;
|
|
75
|
+
tryHandleOutOfBand(prompt: AgentPromptInput): {
|
|
76
|
+
run(ctx: {
|
|
77
|
+
emit: (event: AgentStreamEvent) => void;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
} | null;
|
|
63
80
|
setModel(modelId: string | null): Promise<void>;
|
|
64
81
|
setThinkingOption(thinkingOptionId: string | null): Promise<void>;
|
|
65
82
|
private emit;
|
|
66
83
|
private currentTurnIdForEvent;
|
|
84
|
+
private parseSlashCommandInput;
|
|
85
|
+
private executeCompactCommand;
|
|
86
|
+
private executeAutoCompactCommand;
|
|
67
87
|
private requestEntryCapture;
|
|
68
88
|
private waitForExtensionResult;
|
|
69
89
|
private resolveExtensionResult;
|
|
@@ -78,6 +98,7 @@ export declare class PiRpcAgentSession implements AgentSession {
|
|
|
78
98
|
private handleRuntimeEvent;
|
|
79
99
|
private handleProcessExit;
|
|
80
100
|
private handleSessionEvent;
|
|
101
|
+
private emitCompactionTimeline;
|
|
81
102
|
private handleMessageUpdate;
|
|
82
103
|
private handleMessageEnd;
|
|
83
104
|
private emitToolCallEvent;
|
|
@@ -90,13 +111,15 @@ export declare class PiRpcAgentClient implements AgentClient {
|
|
|
90
111
|
readonly capabilities: AgentCapabilityFlags;
|
|
91
112
|
private readonly logger;
|
|
92
113
|
private readonly runtimeSettings?;
|
|
114
|
+
private readonly providerParams;
|
|
93
115
|
private readonly runtime;
|
|
94
116
|
constructor(options: PiRpcAgentClientOptions);
|
|
95
117
|
createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
96
118
|
resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, _launchContext?: AgentLaunchContext): Promise<AgentSession>;
|
|
97
119
|
listModels(options: ListModelsOptions): Promise<AgentModelDefinition[]>;
|
|
98
120
|
listModes(_options: ListModesOptions): Promise<AgentMode[]>;
|
|
99
|
-
|
|
121
|
+
listImportableSessions(options?: ListImportableSessionsOptions): Promise<ImportableProviderSession[]>;
|
|
122
|
+
importSession(input: ImportProviderSessionInput, context: ImportProviderSessionContext): Promise<import("../../agent-sdk-types.js").ImportedProviderSession>;
|
|
100
123
|
isAvailable(): Promise<boolean>;
|
|
101
124
|
getDiagnostic(): Promise<{
|
|
102
125
|
diagnostic: string;
|