@getpaseo/server 0.1.91-beta.2 → 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.
Files changed (40) hide show
  1. package/dist/scripts/supervisor.js +21 -0
  2. package/dist/server/server/agent/agent-manager.d.ts +1 -1
  3. package/dist/server/server/agent/agent-manager.js +23 -48
  4. package/dist/server/server/agent/prompt-attachments.js +8 -0
  5. package/dist/server/server/agent/provider-registry.d.ts +0 -1
  6. package/dist/server/server/agent/provider-registry.js +21 -3
  7. package/dist/server/server/agent/providers/codex-app-server-agent.js +9 -5
  8. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +1 -0
  9. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +4 -0
  10. package/dist/server/server/agent/providers/opencode-agent.d.ts +16 -2
  11. package/dist/server/server/agent/providers/opencode-agent.js +75 -4
  12. package/dist/server/server/agent/providers/pi/agent.d.ts +23 -1
  13. package/dist/server/server/agent/providers/pi/agent.js +219 -13
  14. package/dist/server/server/agent/providers/pi/cli-runtime.js +9 -0
  15. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +9 -0
  16. package/dist/server/server/agent/providers/pi/runtime.d.ts +2 -0
  17. package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +12 -0
  18. package/dist/server/server/agent/providers/pi/session-descriptor.js +304 -0
  19. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +8 -0
  20. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +22 -0
  21. package/dist/server/server/agent/runtime-mcp-config.d.ts +8 -0
  22. package/dist/server/server/agent/runtime-mcp-config.js +50 -0
  23. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +2 -2
  24. package/dist/server/server/daemon-worker.js +84 -1
  25. package/dist/server/server/file-upload/index.d.ts +27 -0
  26. package/dist/server/server/file-upload/index.js +158 -0
  27. package/dist/server/server/loop-service.d.ts +12 -12
  28. package/dist/server/server/persisted-config.d.ts +8 -0
  29. package/dist/server/server/persisted-config.js +1 -1
  30. package/dist/server/server/persistence-hooks.js +6 -4
  31. package/dist/server/server/session.d.ts +5 -2
  32. package/dist/server/server/session.js +20 -2
  33. package/dist/server/server/speech/providers/local/runtime.js +1 -0
  34. package/dist/server/server/speech/providers/local/worker-client.d.ts +14 -1
  35. package/dist/server/server/speech/providers/local/worker-client.js +169 -7
  36. package/dist/server/server/websocket-server.d.ts +2 -0
  37. package/dist/server/server/websocket-server.js +20 -7
  38. package/dist/server/server/workspace-registry.d.ts +4 -4
  39. package/dist/src/server/persisted-config.js +1 -1
  40. package/package.json +5 -5
@@ -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(_options?: ListPersistedAgentsOptions): Promise<PersistedAgentDescriptor[]>;
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
- return commands.map((command) => ({
825
- name: command.name,
826
- description: command.description ?? command.source,
827
- argumentHint: "",
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.emit({
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.emit({
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(_options) {
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