@getpaseo/server 0.1.91-beta.1 → 0.1.91
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 +1 -1
- package/dist/server/server/agent/agent-manager.js +23 -48
- package/dist/server/server/agent/agent-sdk-types.d.ts +15 -0
- 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 +22 -4
- package/dist/server/server/agent/provider-snapshot-manager.js +19 -1
- package/dist/server/server/agent/providers/claude/agent.d.ts +5 -2
- package/dist/server/server/agent/providers/claude/agent.js +6 -2
- package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
- package/dist/server/server/agent/providers/claude/models.js +6 -6
- package/dist/server/server/agent/providers/codex-app-server-agent.js +9 -5
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +1 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +4 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts +16 -2
- package/dist/server/server/agent/providers/opencode-agent.js +75 -4
- package/dist/server/server/agent/providers/pi/agent.d.ts +23 -1
- package/dist/server/server/agent/providers/pi/agent.js +219 -13
- 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 +12 -0
- package/dist/server/server/agent/providers/pi/session-descriptor.js +304 -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/auth.js +16 -1
- 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 +11 -0
- package/dist/server/server/persisted-config.js +2 -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 -2
- 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/server/utils/directory-suggestions.js +10 -5
- package/dist/server/utils/worktree.d.ts +4 -0
- package/dist/server/utils/worktree.js +19 -2
- package/dist/src/server/persisted-config.js +2 -1
- package/package.json +5 -5
|
@@ -728,6 +728,13 @@ function buildOpenCodeReplayPartTimelineEvent(params) {
|
|
|
728
728
|
part,
|
|
729
729
|
});
|
|
730
730
|
}
|
|
731
|
+
function isOpenCodeCompactionSummaryMessage(message) {
|
|
732
|
+
return (message.role === "assistant" &&
|
|
733
|
+
(message.summary === true || message.agent === "compaction" || message.mode === "compaction"));
|
|
734
|
+
}
|
|
735
|
+
function findOpenCodeCompactionPart(message) {
|
|
736
|
+
return message.parts.find((part) => part.type === "compaction");
|
|
737
|
+
}
|
|
731
738
|
async function readOpenCodeSessionMessagesFromSdk(client, session) {
|
|
732
739
|
const response = await client.session.messages({
|
|
733
740
|
sessionID: session.id,
|
|
@@ -739,7 +746,24 @@ async function readOpenCodeSessionMessagesFromSdk(client, session) {
|
|
|
739
746
|
return filterOpenCodeRevertedMessages(response.data, session.revert);
|
|
740
747
|
}
|
|
741
748
|
function buildOpenCodeSessionTimeline(messages) {
|
|
742
|
-
|
|
749
|
+
const timeline = [];
|
|
750
|
+
let hideNextAssistantAfterCompaction = false;
|
|
751
|
+
for (const message of messages) {
|
|
752
|
+
const compactionPart = findOpenCodeCompactionPart(message);
|
|
753
|
+
if (message.info.role === "assistant" && hideNextAssistantAfterCompaction) {
|
|
754
|
+
hideNextAssistantAfterCompaction = false;
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
if (message.info.role === "user" && !compactionPart) {
|
|
758
|
+
hideNextAssistantAfterCompaction = false;
|
|
759
|
+
}
|
|
760
|
+
timeline.push(...buildOpenCodeReplayTimelineEvents(message).map((event) => event.item));
|
|
761
|
+
if (message.info.role === "user" && compactionPart) {
|
|
762
|
+
timeline.push(createCompactionTimelineItem("completed", compactionPart.auto ? "auto" : "manual"));
|
|
763
|
+
hideNextAssistantAfterCompaction = true;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return timeline;
|
|
743
767
|
}
|
|
744
768
|
function filterOpenCodeRevertedMessages(messages, revert) {
|
|
745
769
|
if (!revert?.messageID || revert.partID) {
|
|
@@ -778,6 +802,9 @@ function readOpenCodeMessageModel(message) {
|
|
|
778
802
|
}
|
|
779
803
|
function buildOpenCodeReplayTimelineEvents(message) {
|
|
780
804
|
const { info, parts } = message;
|
|
805
|
+
if (isOpenCodeCompactionSummaryMessage(info)) {
|
|
806
|
+
return [];
|
|
807
|
+
}
|
|
781
808
|
if (info.role === "user") {
|
|
782
809
|
const text = parts
|
|
783
810
|
.filter((part) => part.type === "text")
|
|
@@ -816,6 +843,7 @@ function buildOpenCodeReplayTimelineEvents(message) {
|
|
|
816
843
|
}
|
|
817
844
|
export const __openCodeInternals = {
|
|
818
845
|
buildOpenCodePromptParts,
|
|
846
|
+
buildOpenCodeSessionTimeline,
|
|
819
847
|
buildOpenCodeModelContextWindowLookup,
|
|
820
848
|
buildOpenCodeModelDefinition,
|
|
821
849
|
buildOpenCodeModelLookupKey,
|
|
@@ -1370,6 +1398,11 @@ export function translateOpenCodeEvent(event, state) {
|
|
|
1370
1398
|
function resetOpenCodeTurnTrackingState(state) {
|
|
1371
1399
|
state.streamedPartKeys.clear();
|
|
1372
1400
|
state.partTypes.clear();
|
|
1401
|
+
state.compactionSummaryMessageIds.clear();
|
|
1402
|
+
state.emittedCompactionPartIds.clear();
|
|
1403
|
+
if (state.suppressAssistantMessagesUntilIdle) {
|
|
1404
|
+
state.suppressAssistantMessagesUntilIdle.active = false;
|
|
1405
|
+
}
|
|
1373
1406
|
}
|
|
1374
1407
|
function getOpenCodeSubAgentMaps(state) {
|
|
1375
1408
|
state.subAgentsByCallId ?? (state.subAgentsByCallId = new Map());
|
|
@@ -1592,6 +1625,14 @@ function appendOpenCodeMessageUpdated(event, state, events) {
|
|
|
1592
1625
|
if (info.role !== "assistant") {
|
|
1593
1626
|
return;
|
|
1594
1627
|
}
|
|
1628
|
+
if (state.suppressAssistantMessagesUntilIdle?.active) {
|
|
1629
|
+
state.compactionSummaryMessageIds.add(info.id);
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
if (isOpenCodeCompactionSummaryMessage(info)) {
|
|
1633
|
+
state.compactionSummaryMessageIds.add(info.id);
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1595
1636
|
const modelLookupKey = resolveOpenCodeModelLookupKeyFromAssistantMessage(info);
|
|
1596
1637
|
if (modelLookupKey) {
|
|
1597
1638
|
const contextWindowMaxTokens = state.modelContextWindowsByModelKey?.get(modelLookupKey);
|
|
@@ -1638,6 +1679,13 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1638
1679
|
}
|
|
1639
1680
|
const messageRole = state.messageRoles.get(part.messageID);
|
|
1640
1681
|
state.partTypes.set(part.id, part.type);
|
|
1682
|
+
if (state.compactionSummaryMessageIds.has(part.messageID)) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
if (shouldSuppressOpenCodeAssistantPart(part, messageRole, state)) {
|
|
1686
|
+
state.compactionSummaryMessageIds.add(part.messageID);
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1641
1689
|
if (part.type === "text") {
|
|
1642
1690
|
appendOpenCodeTextPart(part, messageRole, state, events);
|
|
1643
1691
|
return;
|
|
@@ -1654,6 +1702,10 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1654
1702
|
return;
|
|
1655
1703
|
}
|
|
1656
1704
|
if (part.type === "compaction") {
|
|
1705
|
+
if (state.emittedCompactionPartIds.has(part.id)) {
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
state.emittedCompactionPartIds.add(part.id);
|
|
1657
1709
|
events.push({
|
|
1658
1710
|
type: "timeline",
|
|
1659
1711
|
provider: "opencode",
|
|
@@ -1678,6 +1730,11 @@ function appendOpenCodeMessagePartUpdated(event, state, events) {
|
|
|
1678
1730
|
}
|
|
1679
1731
|
}
|
|
1680
1732
|
}
|
|
1733
|
+
function shouldSuppressOpenCodeAssistantPart(part, messageRole, state) {
|
|
1734
|
+
return (state.suppressAssistantMessagesUntilIdle?.active === true &&
|
|
1735
|
+
part.type === "text" &&
|
|
1736
|
+
messageRole !== "user");
|
|
1737
|
+
}
|
|
1681
1738
|
function appendOpenCodeTextPart(part, messageRole, state, events) {
|
|
1682
1739
|
if (messageRole === "user") {
|
|
1683
1740
|
return;
|
|
@@ -1724,6 +1781,9 @@ function appendOpenCodeMessagePartDelta(event, state, events) {
|
|
|
1724
1781
|
const messageRole = messageID ? state.messageRoles.get(messageID) : undefined;
|
|
1725
1782
|
const knownPartType = partID ? state.partTypes.get(partID) : undefined;
|
|
1726
1783
|
const isReasoning = knownPartType === "reasoning" || field === "reasoning";
|
|
1784
|
+
if (messageID && state.compactionSummaryMessageIds.has(messageID)) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1727
1787
|
if (isReasoning) {
|
|
1728
1788
|
if (partID) {
|
|
1729
1789
|
state.streamedPartKeys.add(`reasoning:${partID}`);
|
|
@@ -1741,6 +1801,10 @@ function appendOpenCodeMessagePartDelta(event, state, events) {
|
|
|
1741
1801
|
if (messageRole === "user") {
|
|
1742
1802
|
return;
|
|
1743
1803
|
}
|
|
1804
|
+
if (messageID && state.suppressAssistantMessagesUntilIdle?.active === true) {
|
|
1805
|
+
state.compactionSummaryMessageIds.add(messageID);
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1744
1808
|
if (partID) {
|
|
1745
1809
|
state.streamedPartKeys.add(`text:${partID}`);
|
|
1746
1810
|
}
|
|
@@ -1938,6 +2002,9 @@ class OpenCodeAgentSession {
|
|
|
1938
2002
|
this.streamedPartKeys = new Set();
|
|
1939
2003
|
/** Tracks assistant messages already emitted from structured payloads. */
|
|
1940
2004
|
this.emittedStructuredMessageIds = new Set();
|
|
2005
|
+
this.compactionSummaryMessageIds = new Set();
|
|
2006
|
+
this.emittedCompactionPartIds = new Set();
|
|
2007
|
+
this.suppressAssistantMessagesUntilIdle = { active: false };
|
|
1941
2008
|
/** Tracks the type of each part by ID, learned from message.part.updated events. */
|
|
1942
2009
|
this.partTypes = new Map();
|
|
1943
2010
|
this.availableModesCache = null;
|
|
@@ -2069,6 +2136,7 @@ class OpenCodeAgentSession {
|
|
|
2069
2136
|
this.accumulatedUsage = contextWindowMaxTokens !== undefined ? { contextWindowMaxTokens } : {};
|
|
2070
2137
|
const parts = buildOpenCodePromptParts(prompt);
|
|
2071
2138
|
this.pendingUserMessageText = buildOpenCodeUserTimelineText(prompt);
|
|
2139
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2072
2140
|
const model = this.parseModel(this.config.model);
|
|
2073
2141
|
const thinkingOptionId = this.config.thinkingOptionId;
|
|
2074
2142
|
const effectiveVariant = thinkingOptionId ?? undefined;
|
|
@@ -2088,6 +2156,7 @@ class OpenCodeAgentSession {
|
|
|
2088
2156
|
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
|
2089
2157
|
if (slashCommand) {
|
|
2090
2158
|
if (slashCommand.commandName === "compact" || slashCommand.commandName === "summarize") {
|
|
2159
|
+
this.suppressAssistantMessagesUntilIdle.active = true;
|
|
2091
2160
|
void this.client.session
|
|
2092
2161
|
.summarize({
|
|
2093
2162
|
sessionID: this.sessionId,
|
|
@@ -2096,18 +2165,17 @@ class OpenCodeAgentSession {
|
|
|
2096
2165
|
})
|
|
2097
2166
|
.then((response) => {
|
|
2098
2167
|
if (response.error) {
|
|
2168
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2099
2169
|
this.finishForegroundTurn({
|
|
2100
2170
|
type: "turn_failed",
|
|
2101
2171
|
provider: "opencode",
|
|
2102
2172
|
error: toDiagnosticErrorMessage(response.error),
|
|
2103
2173
|
}, turnId);
|
|
2104
2174
|
}
|
|
2105
|
-
else {
|
|
2106
|
-
this.finishForegroundTurn({ type: "turn_completed", provider: "opencode", usage: undefined }, turnId);
|
|
2107
|
-
}
|
|
2108
2175
|
return;
|
|
2109
2176
|
})
|
|
2110
2177
|
.catch((error) => {
|
|
2178
|
+
this.suppressAssistantMessagesUntilIdle.active = false;
|
|
2111
2179
|
this.finishForegroundTurn({
|
|
2112
2180
|
type: "turn_failed",
|
|
2113
2181
|
provider: "opencode",
|
|
@@ -2710,6 +2778,9 @@ class OpenCodeAgentSession {
|
|
|
2710
2778
|
sessionTotalCostUsd: this.sessionTotalCostUsd,
|
|
2711
2779
|
streamedPartKeys: this.streamedPartKeys,
|
|
2712
2780
|
emittedStructuredMessageIds: this.emittedStructuredMessageIds,
|
|
2781
|
+
compactionSummaryMessageIds: this.compactionSummaryMessageIds,
|
|
2782
|
+
emittedCompactionPartIds: this.emittedCompactionPartIds,
|
|
2783
|
+
suppressAssistantMessagesUntilIdle: this.suppressAssistantMessagesUntilIdle,
|
|
2713
2784
|
partTypes: this.partTypes,
|
|
2714
2785
|
subAgentsByCallId: this.subAgentsByCallId,
|
|
2715
2786
|
subAgentCallIdByChildSessionId: this.subAgentCallIdByChildSessionId,
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
+
import { z } from "zod";
|
|
2
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 ListPersistedAgentsOptions, type ListModesOptions, type ListModelsOptions, type PersistedAgentDescriptor } 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,14 @@ 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
|
-
listPersistedAgents(
|
|
121
|
+
listPersistedAgents(options?: ListPersistedAgentsOptions): Promise<PersistedAgentDescriptor[]>;
|
|
100
122
|
isAvailable(): Promise<boolean>;
|
|
101
123
|
getDiagnostic(): Promise<{
|
|
102
124
|
diagnostic: string;
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { z } from "zod";
|
|
5
6
|
import { runProviderTurn } from "../provider-runner.js";
|
|
6
7
|
import { checkProviderLaunchAvailable, resolveProviderLaunch, } from "../../provider-launch-config.js";
|
|
7
8
|
import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
|
|
@@ -10,6 +11,7 @@ import { buildBinaryDiagnosticRows, formatDiagnosticStatus, formatProviderDiagno
|
|
|
10
11
|
import { getUserMessageText, streamPiHistory, } from "./history-mapper.js";
|
|
11
12
|
import { PiCliRuntime } from "./cli-runtime.js";
|
|
12
13
|
import { revertPiConversation } from "./rewind.js";
|
|
14
|
+
import { listPiPersistedAgents } from "./session-descriptor.js";
|
|
13
15
|
import { mapToolDetail, parseToolArgs, parseToolResult, resolveToolCallName, } from "./tool-call-mapper.js";
|
|
14
16
|
const PI_PROVIDER = "pi";
|
|
15
17
|
const DEFAULT_PI_THINKING_LEVEL = "medium";
|
|
@@ -23,6 +25,23 @@ const QUESTION_RESPONSE_HEADER = "Response";
|
|
|
23
25
|
const QUESTION_COMMENT_HEADER = "Comment";
|
|
24
26
|
const PI_ASK_USER_FREEFORM_SENTINEL = "✏️ Type custom response...";
|
|
25
27
|
const COMBINED_ASK_USER_METADATA = "ask_user_select_optional_comment";
|
|
28
|
+
export const PiProviderParamsSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
sessionDir: z.string().min(1).optional(),
|
|
31
|
+
})
|
|
32
|
+
.strict();
|
|
33
|
+
const PI_HANDLED_BUILTIN_SLASH_COMMANDS = [
|
|
34
|
+
{
|
|
35
|
+
name: "compact",
|
|
36
|
+
description: "Manually compact the session context",
|
|
37
|
+
argumentHint: "[instructions]",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "autocompact",
|
|
41
|
+
description: "Toggle automatic context compaction",
|
|
42
|
+
argumentHint: "[on|off|toggle]",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
26
45
|
const PI_CAPABILITIES = {
|
|
27
46
|
supportsStreaming: true,
|
|
28
47
|
supportsSessionPersistence: true,
|
|
@@ -76,6 +95,19 @@ function normalizePiThinkingOption(value) {
|
|
|
76
95
|
}
|
|
77
96
|
return isPiThinkingLevel(value) ? value : null;
|
|
78
97
|
}
|
|
98
|
+
function parseAutoCompactMode(value) {
|
|
99
|
+
const mode = (value ?? "toggle").trim().toLowerCase();
|
|
100
|
+
if (mode === "on" || mode === "true" || mode === "enable" || mode === "enabled") {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (mode === "off" || mode === "false" || mode === "disable" || mode === "disabled") {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (mode === "toggle") {
|
|
107
|
+
return "toggle";
|
|
108
|
+
}
|
|
109
|
+
return "unknown";
|
|
110
|
+
}
|
|
79
111
|
function mapThinkingOption(option) {
|
|
80
112
|
const mappedOption = {
|
|
81
113
|
id: option.id,
|
|
@@ -654,6 +686,9 @@ export class PiRpcAgentSession {
|
|
|
654
686
|
this.seenUserEntryIds = new Set();
|
|
655
687
|
this.pendingUserMessages = [];
|
|
656
688
|
this.pendingExtensionResults = new Map();
|
|
689
|
+
this.outOfBandCompactionEmit = null;
|
|
690
|
+
this.outOfBandCompactionStarted = false;
|
|
691
|
+
this.outOfBandCompactionCompleted = false;
|
|
657
692
|
this.closed = false;
|
|
658
693
|
this.runtimeSession = options.runtimeSession;
|
|
659
694
|
this.config = options.config;
|
|
@@ -821,11 +856,41 @@ export class PiRpcAgentSession {
|
|
|
821
856
|
}
|
|
822
857
|
async listCommands() {
|
|
823
858
|
const commands = await this.runtimeSession.getCommands();
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
859
|
+
const mappedCommands = new Map(PI_HANDLED_BUILTIN_SLASH_COMMANDS.map((command) => [command.name, { ...command }]));
|
|
860
|
+
for (const command of commands) {
|
|
861
|
+
const knownCommand = mappedCommands.get(command.name);
|
|
862
|
+
mappedCommands.set(command.name, {
|
|
863
|
+
name: command.name,
|
|
864
|
+
description: command.description ?? command.source,
|
|
865
|
+
argumentHint: knownCommand?.argumentHint ?? "",
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
return [...mappedCommands.values()];
|
|
869
|
+
}
|
|
870
|
+
tryHandleOutOfBand(prompt) {
|
|
871
|
+
if (typeof prompt !== "string") {
|
|
872
|
+
return null;
|
|
873
|
+
}
|
|
874
|
+
const parsed = this.parseSlashCommandInput(prompt);
|
|
875
|
+
if (!parsed) {
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
const commandName = parsed.commandName.toLowerCase();
|
|
879
|
+
if (commandName === "compact") {
|
|
880
|
+
return {
|
|
881
|
+
run: async ({ emit }) => {
|
|
882
|
+
await this.executeCompactCommand(parsed.args, emit);
|
|
883
|
+
},
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
if (commandName === "autocompact") {
|
|
887
|
+
return {
|
|
888
|
+
run: async ({ emit }) => {
|
|
889
|
+
await this.executeAutoCompactCommand(parsed.args, emit);
|
|
890
|
+
},
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
return null;
|
|
829
894
|
}
|
|
830
895
|
async setModel(modelId) {
|
|
831
896
|
const parsedReference = parseModelReference(modelId);
|
|
@@ -860,6 +925,117 @@ export class PiRpcAgentSession {
|
|
|
860
925
|
currentTurnIdForEvent() {
|
|
861
926
|
return this.activeTurnId ?? undefined;
|
|
862
927
|
}
|
|
928
|
+
parseSlashCommandInput(text) {
|
|
929
|
+
const trimmed = text.trim();
|
|
930
|
+
if (!trimmed.startsWith("/") || trimmed.length <= 1) {
|
|
931
|
+
return null;
|
|
932
|
+
}
|
|
933
|
+
const withoutPrefix = trimmed.slice(1);
|
|
934
|
+
const firstWhitespaceIdx = withoutPrefix.search(/\s/);
|
|
935
|
+
const commandName = firstWhitespaceIdx === -1 ? withoutPrefix : withoutPrefix.slice(0, firstWhitespaceIdx);
|
|
936
|
+
if (!commandName || commandName.includes("/")) {
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
const rawArgs = firstWhitespaceIdx === -1 ? "" : withoutPrefix.slice(firstWhitespaceIdx + 1).trim();
|
|
940
|
+
return rawArgs.length > 0 ? { commandName, args: rawArgs } : { commandName };
|
|
941
|
+
}
|
|
942
|
+
async executeCompactCommand(customInstructions, emit) {
|
|
943
|
+
if (this.outOfBandCompactionEmit) {
|
|
944
|
+
throw new Error("A Pi compact command is already running");
|
|
945
|
+
}
|
|
946
|
+
this.outOfBandCompactionEmit = emit;
|
|
947
|
+
this.outOfBandCompactionStarted = false;
|
|
948
|
+
this.outOfBandCompactionCompleted = false;
|
|
949
|
+
try {
|
|
950
|
+
await this.runtimeSession.compact(customInstructions);
|
|
951
|
+
}
|
|
952
|
+
catch (error) {
|
|
953
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
954
|
+
if (this.outOfBandCompactionEmit === emit &&
|
|
955
|
+
this.outOfBandCompactionStarted &&
|
|
956
|
+
!this.outOfBandCompactionCompleted) {
|
|
957
|
+
this.emitCompactionTimeline({
|
|
958
|
+
turnId: undefined,
|
|
959
|
+
item: {
|
|
960
|
+
type: "compaction",
|
|
961
|
+
status: "completed",
|
|
962
|
+
trigger: "manual",
|
|
963
|
+
},
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
emit({
|
|
967
|
+
type: "timeline",
|
|
968
|
+
provider: PI_PROVIDER,
|
|
969
|
+
item: {
|
|
970
|
+
type: "assistant_message",
|
|
971
|
+
text: `[Error] Failed to compact context: ${message}`,
|
|
972
|
+
},
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
finally {
|
|
976
|
+
if (this.outOfBandCompactionEmit === emit && !this.outOfBandCompactionStarted) {
|
|
977
|
+
this.outOfBandCompactionEmit = null;
|
|
978
|
+
this.outOfBandCompactionStarted = false;
|
|
979
|
+
this.outOfBandCompactionCompleted = false;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
async executeAutoCompactCommand(mode, emit) {
|
|
984
|
+
let enabled = parseAutoCompactMode(mode);
|
|
985
|
+
if (enabled === "unknown") {
|
|
986
|
+
emit({
|
|
987
|
+
type: "timeline",
|
|
988
|
+
provider: PI_PROVIDER,
|
|
989
|
+
item: {
|
|
990
|
+
type: "assistant_message",
|
|
991
|
+
text: "[Error] Usage: /autocompact [on|off|toggle]",
|
|
992
|
+
},
|
|
993
|
+
});
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
if (enabled === "toggle") {
|
|
997
|
+
const state = await this.runtimeSession.getState();
|
|
998
|
+
if (typeof state.autoCompactionEnabled !== "boolean") {
|
|
999
|
+
emit({
|
|
1000
|
+
type: "timeline",
|
|
1001
|
+
provider: PI_PROVIDER,
|
|
1002
|
+
item: {
|
|
1003
|
+
type: "assistant_message",
|
|
1004
|
+
text: "[Error] Auto-compaction state is unavailable. Use /autocompact on or /autocompact off.",
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
enabled = !state.autoCompactionEnabled;
|
|
1010
|
+
}
|
|
1011
|
+
try {
|
|
1012
|
+
await this.runtimeSession.setAutoCompaction(enabled);
|
|
1013
|
+
}
|
|
1014
|
+
catch (error) {
|
|
1015
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1016
|
+
emit({
|
|
1017
|
+
type: "timeline",
|
|
1018
|
+
provider: PI_PROVIDER,
|
|
1019
|
+
item: {
|
|
1020
|
+
type: "assistant_message",
|
|
1021
|
+
text: `[Error] Failed to set auto-compaction: ${message}`,
|
|
1022
|
+
},
|
|
1023
|
+
});
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
this.state = {
|
|
1027
|
+
...this.state,
|
|
1028
|
+
autoCompactionEnabled: enabled,
|
|
1029
|
+
};
|
|
1030
|
+
emit({
|
|
1031
|
+
type: "timeline",
|
|
1032
|
+
provider: PI_PROVIDER,
|
|
1033
|
+
item: {
|
|
1034
|
+
type: "assistant_message",
|
|
1035
|
+
text: `Auto-compaction ${enabled ? "enabled" : "disabled"}.`,
|
|
1036
|
+
},
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
863
1039
|
async requestEntryCapture(reason) {
|
|
864
1040
|
const requestId = randomUUID();
|
|
865
1041
|
const resultPromise = this.waitForExtensionResult(requestId);
|
|
@@ -1090,9 +1266,7 @@ export class PiRpcAgentSession {
|
|
|
1090
1266
|
return;
|
|
1091
1267
|
}
|
|
1092
1268
|
case "compaction_start":
|
|
1093
|
-
this.
|
|
1094
|
-
type: "timeline",
|
|
1095
|
-
provider: PI_PROVIDER,
|
|
1269
|
+
this.emitCompactionTimeline({
|
|
1096
1270
|
turnId,
|
|
1097
1271
|
item: {
|
|
1098
1272
|
type: "compaction",
|
|
@@ -1102,13 +1276,12 @@ export class PiRpcAgentSession {
|
|
|
1102
1276
|
});
|
|
1103
1277
|
return;
|
|
1104
1278
|
case "compaction_end":
|
|
1105
|
-
this.
|
|
1106
|
-
type: "timeline",
|
|
1107
|
-
provider: PI_PROVIDER,
|
|
1279
|
+
this.emitCompactionTimeline({
|
|
1108
1280
|
turnId,
|
|
1109
1281
|
item: {
|
|
1110
1282
|
type: "compaction",
|
|
1111
1283
|
status: "completed",
|
|
1284
|
+
trigger: event.reason === "manual" ? "manual" : "auto",
|
|
1112
1285
|
},
|
|
1113
1286
|
});
|
|
1114
1287
|
return;
|
|
@@ -1119,6 +1292,33 @@ export class PiRpcAgentSession {
|
|
|
1119
1292
|
return;
|
|
1120
1293
|
}
|
|
1121
1294
|
}
|
|
1295
|
+
emitCompactionTimeline(input) {
|
|
1296
|
+
const emitOutOfBand = this.outOfBandCompactionEmit;
|
|
1297
|
+
if (emitOutOfBand && input.item.type === "compaction") {
|
|
1298
|
+
if (input.item.status === "loading") {
|
|
1299
|
+
this.outOfBandCompactionStarted = true;
|
|
1300
|
+
}
|
|
1301
|
+
if (input.item.status === "completed") {
|
|
1302
|
+
this.outOfBandCompactionCompleted = true;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
const event = {
|
|
1306
|
+
type: "timeline",
|
|
1307
|
+
provider: PI_PROVIDER,
|
|
1308
|
+
...(emitOutOfBand ? {} : { turnId: input.turnId }),
|
|
1309
|
+
item: input.item,
|
|
1310
|
+
};
|
|
1311
|
+
if (emitOutOfBand) {
|
|
1312
|
+
emitOutOfBand(event);
|
|
1313
|
+
if (input.item.type === "compaction" && input.item.status === "completed") {
|
|
1314
|
+
this.outOfBandCompactionEmit = null;
|
|
1315
|
+
this.outOfBandCompactionStarted = false;
|
|
1316
|
+
this.outOfBandCompactionCompleted = false;
|
|
1317
|
+
}
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
this.emit(event);
|
|
1321
|
+
}
|
|
1122
1322
|
handleMessageUpdate(event, turnId) {
|
|
1123
1323
|
if (event.message.role !== "assistant") {
|
|
1124
1324
|
return;
|
|
@@ -1240,6 +1440,7 @@ export class PiRpcAgentClient {
|
|
|
1240
1440
|
this.capabilities = PI_CAPABILITIES;
|
|
1241
1441
|
this.logger = options.logger;
|
|
1242
1442
|
this.runtimeSettings = options.runtimeSettings;
|
|
1443
|
+
this.providerParams = PiProviderParamsSchema.parse(options.providerParams ?? {});
|
|
1243
1444
|
this.runtime = options.runtime ?? createRuntime(options.logger, options.runtimeSettings);
|
|
1244
1445
|
}
|
|
1245
1446
|
async createSession(config, launchContext) {
|
|
@@ -1332,8 +1533,13 @@ export class PiRpcAgentClient {
|
|
|
1332
1533
|
async listModes(_options) {
|
|
1333
1534
|
return [];
|
|
1334
1535
|
}
|
|
1335
|
-
async listPersistedAgents(
|
|
1336
|
-
return
|
|
1536
|
+
async listPersistedAgents(options) {
|
|
1537
|
+
return await listPiPersistedAgents({
|
|
1538
|
+
...options,
|
|
1539
|
+
provider: PI_PROVIDER,
|
|
1540
|
+
sessionDir: this.providerParams.sessionDir,
|
|
1541
|
+
runtimeSettings: this.runtimeSettings,
|
|
1542
|
+
});
|
|
1337
1543
|
}
|
|
1338
1544
|
async isAvailable() {
|
|
1339
1545
|
const launch = await this.resolvePiLaunch();
|
|
@@ -76,6 +76,15 @@ class PiCliRuntimeSession {
|
|
|
76
76
|
async prompt(message, images) {
|
|
77
77
|
await this.request({ type: "prompt", message, ...(images?.length ? { images } : {}) });
|
|
78
78
|
}
|
|
79
|
+
async compact(customInstructions) {
|
|
80
|
+
await this.request({
|
|
81
|
+
type: "compact",
|
|
82
|
+
...(customInstructions ? { customInstructions } : {}),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async setAutoCompaction(enabled) {
|
|
86
|
+
await this.request({ type: "set_auto_compaction", enabled });
|
|
87
|
+
}
|
|
79
88
|
async abort() {
|
|
80
89
|
await this.request({ type: "abort" });
|
|
81
90
|
}
|
|
@@ -66,6 +66,7 @@ export interface PiSessionState {
|
|
|
66
66
|
thinkingLevel: PiThinkingLevel;
|
|
67
67
|
isStreaming: boolean;
|
|
68
68
|
isCompacting: boolean;
|
|
69
|
+
autoCompactionEnabled?: boolean;
|
|
69
70
|
sessionFile?: string;
|
|
70
71
|
sessionId: string;
|
|
71
72
|
sessionName?: string;
|
|
@@ -98,6 +99,14 @@ export type PiRpcCommand = {
|
|
|
98
99
|
type: "prompt";
|
|
99
100
|
message: string;
|
|
100
101
|
images?: PiImageContent[];
|
|
102
|
+
} | {
|
|
103
|
+
id?: string;
|
|
104
|
+
type: "compact";
|
|
105
|
+
customInstructions?: string;
|
|
106
|
+
} | {
|
|
107
|
+
id?: string;
|
|
108
|
+
type: "set_auto_compaction";
|
|
109
|
+
enabled: boolean;
|
|
101
110
|
} | {
|
|
102
111
|
id?: string;
|
|
103
112
|
type: "abort";
|
|
@@ -28,6 +28,8 @@ export interface PiRuntimeSession {
|
|
|
28
28
|
data: string;
|
|
29
29
|
mimeType: string;
|
|
30
30
|
}>): Promise<void>;
|
|
31
|
+
compact(customInstructions?: string): Promise<void>;
|
|
32
|
+
setAutoCompaction(enabled: boolean): Promise<void>;
|
|
31
33
|
abort(): Promise<void>;
|
|
32
34
|
getState(): Promise<PiSessionState>;
|
|
33
35
|
getMessages(): Promise<PiAgentMessage[]>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ListPersistedAgentsOptions, PersistedAgentDescriptor } from "../../agent-sdk-types.js";
|
|
2
|
+
import type { ProviderRuntimeSettings } from "../../provider-launch-config.js";
|
|
3
|
+
interface PiSessionDescriptorOptions extends ListPersistedAgentsOptions {
|
|
4
|
+
provider?: string;
|
|
5
|
+
sessionDir?: string;
|
|
6
|
+
runtimeSettings?: ProviderRuntimeSettings;
|
|
7
|
+
env?: NodeJS.ProcessEnv;
|
|
8
|
+
homeDir?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function listPiPersistedAgents(options?: PiSessionDescriptorOptions): Promise<PersistedAgentDescriptor[]>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=session-descriptor.d.ts.map
|