@getpaseo/server 0.9.2 → 0.10.0-beta.1

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 (145) hide show
  1. package/dist/scripts/supervisor.js +51 -21
  2. package/dist/server/server/agent/agent-manager.js +22 -2
  3. package/dist/server/server/agent/agent-prompt.js +12 -0
  4. package/dist/server/server/agent/agent-sdk-types.d.ts +3 -0
  5. package/dist/server/server/agent/mcp-shared.d.ts +5 -1
  6. package/dist/server/server/agent/mcp-shared.js +2 -1
  7. package/dist/server/server/agent/provider-registry.js +2 -2
  8. package/dist/server/server/agent/providers/acp-agent.js +20 -11
  9. package/dist/server/server/agent/providers/claude/agent.d.ts +1 -2
  10. package/dist/server/server/agent/providers/claude/agent.js +10 -9
  11. package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
  12. package/dist/server/server/agent/providers/claude/models.js +1 -5
  13. package/dist/server/server/agent/providers/claude/project-dir.d.ts +1 -0
  14. package/dist/server/server/agent/providers/claude/project-dir.js +5 -1
  15. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +6 -1
  16. package/dist/server/server/agent/providers/codex-app-server-agent.js +10 -1
  17. package/dist/server/server/agent/providers/generic-acp-agent.js +3 -1
  18. package/dist/server/server/agent/providers/omp/agent.js +23 -6
  19. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +1 -0
  20. package/dist/server/server/agent/providers/omp/rpc-types.js +1 -0
  21. package/dist/server/server/agent/providers/opencode/bridge.d.ts +5 -1
  22. package/dist/server/server/agent/providers/opencode/bridge.js +56 -5
  23. package/dist/server/server/agent/providers/opencode/http-error.d.ts +8 -0
  24. package/dist/server/server/agent/providers/opencode/http-error.js +13 -0
  25. package/dist/server/server/agent/providers/opencode/runtime-client.d.ts +38 -0
  26. package/dist/server/server/agent/providers/opencode/runtime-client.js +131 -0
  27. package/dist/server/server/agent/providers/opencode/runtime-notice.d.ts +3 -0
  28. package/dist/server/server/agent/providers/opencode/runtime-notice.js +47 -0
  29. package/dist/server/server/agent/providers/opencode/server-manager.js +19 -8
  30. package/dist/server/server/agent/providers/opencode/v2/agent.d.ts +36 -0
  31. package/dist/server/server/agent/providers/opencode/v2/agent.js +208 -0
  32. package/dist/server/server/agent/providers/opencode/v2/api.d.ts +18 -0
  33. package/dist/server/server/agent/providers/opencode/v2/api.js +2 -0
  34. package/dist/server/server/agent/providers/opencode/v2/bridge-plugin.bundle.mjs +6693 -0
  35. package/dist/server/server/agent/providers/opencode/v2/capabilities.d.ts +3 -0
  36. package/dist/server/server/agent/providers/opencode/v2/capabilities.js +13 -0
  37. package/dist/server/server/agent/providers/opencode/v2/children.d.ts +20 -0
  38. package/dist/server/server/agent/providers/opencode/v2/children.js +75 -0
  39. package/dist/server/server/agent/providers/opencode/v2/commands.d.ts +4 -0
  40. package/dist/server/server/agent/providers/opencode/v2/commands.js +36 -0
  41. package/dist/server/server/agent/providers/opencode/v2/configuration.d.ts +8 -0
  42. package/dist/server/server/agent/providers/opencode/v2/configuration.js +64 -0
  43. package/dist/server/server/agent/providers/opencode/v2/history.d.ts +4 -0
  44. package/dist/server/server/agent/providers/opencode/v2/history.js +15 -0
  45. package/dist/server/server/agent/providers/opencode/v2/mapping.d.ts +7 -0
  46. package/dist/server/server/agent/providers/opencode/v2/mapping.js +42 -0
  47. package/dist/server/server/agent/providers/opencode/v2/permissions.d.ts +18 -0
  48. package/dist/server/server/agent/providers/opencode/v2/permissions.js +157 -0
  49. package/dist/server/server/agent/providers/opencode/v2/readiness.d.ts +18 -0
  50. package/dist/server/server/agent/providers/opencode/v2/readiness.js +51 -0
  51. package/dist/server/server/agent/providers/opencode/v2/runtime.d.ts +36 -0
  52. package/dist/server/server/agent/providers/opencode/v2/runtime.js +230 -0
  53. package/dist/server/server/agent/providers/opencode/v2/session.d.ts +84 -0
  54. package/dist/server/server/agent/providers/opencode/v2/session.js +465 -0
  55. package/dist/server/server/agent/providers/opencode/v2/structured-output.d.ts +8 -0
  56. package/dist/server/server/agent/providers/opencode/v2/structured-output.js +32 -0
  57. package/dist/server/server/agent/providers/opencode/v2/timeline.d.ts +28 -0
  58. package/dist/server/server/agent/providers/opencode/v2/timeline.js +154 -0
  59. package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +40 -0
  60. package/dist/server/server/agent/providers/opencode/v2/turns.js +226 -0
  61. package/dist/server/server/agent/providers/opencode-agent.d.ts +26 -7
  62. package/dist/server/server/agent/providers/opencode-agent.js +100 -40
  63. package/dist/server/server/agent/providers/pi/agent.d.ts +6 -6
  64. package/dist/server/server/agent/providers/pi/agent.js +114 -165
  65. package/dist/server/server/agent/providers/pi/extensions/child-session.d.ts +4 -0
  66. package/dist/server/server/agent/providers/pi/extensions/child-session.js +59 -0
  67. package/dist/server/server/agent/providers/pi/extensions/contract.d.ts +68 -0
  68. package/dist/server/server/agent/providers/pi/extensions/contract.js +2 -0
  69. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.d.ts +3 -0
  70. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.js +159 -0
  71. package/dist/server/server/agent/providers/pi/extensions/host.d.ts +28 -0
  72. package/dist/server/server/agent/providers/pi/extensions/host.js +94 -0
  73. package/dist/server/server/agent/providers/pi/extensions/index.d.ts +7 -0
  74. package/dist/server/server/agent/providers/pi/extensions/index.js +6 -0
  75. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.d.ts +3 -0
  76. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.js +138 -0
  77. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.d.ts +3 -0
  78. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.js +38 -0
  79. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.d.ts +3 -0
  80. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.js +63 -0
  81. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.d.ts +3 -0
  82. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.js +48 -0
  83. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.d.ts +3 -0
  84. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.js +131 -0
  85. package/dist/server/server/agent/providers/pi/extensions/registry.d.ts +2 -0
  86. package/dist/server/server/agent/providers/pi/extensions/registry.js +21 -0
  87. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.d.ts +3 -0
  88. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.js +180 -0
  89. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.d.ts +3 -0
  90. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.js +51 -0
  91. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.d.ts +22 -0
  92. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.js +66 -0
  93. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.d.ts +4 -0
  94. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.js +79 -0
  95. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.d.ts +3 -0
  96. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.js +149 -0
  97. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +7 -2
  98. package/dist/server/server/agent/providers/pi/history-mapper.js +78 -35
  99. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
  100. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +170 -0
  101. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +355 -0
  102. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +1 -6
  103. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +1 -97
  104. package/dist/server/server/agent/tools/paseo-tools.js +22 -15
  105. package/dist/server/server/auth.d.ts +1 -2
  106. package/dist/server/server/auth.js +8 -14
  107. package/dist/server/server/bootstrap.js +10 -2
  108. package/dist/server/server/daemon-instance.d.ts +1 -0
  109. package/dist/server/server/daemon-instance.js +1 -0
  110. package/dist/server/server/exports.d.ts +1 -1
  111. package/dist/server/server/exports.js +1 -1
  112. package/dist/server/server/local-credential.d.ts +6 -0
  113. package/dist/server/server/local-credential.js +82 -0
  114. package/dist/server/server/session-admission-auth.d.ts +16 -0
  115. package/dist/server/server/session-admission-auth.js +26 -0
  116. package/dist/server/server/websocket-server.d.ts +6 -1
  117. package/dist/server/server/websocket-server.js +132 -55
  118. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js} +1 -1
  119. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.br → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br} +0 -0
  120. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz +0 -0
  121. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js → desktop-attachment-store-d5d3402a752965d3037191484127123b.js} +1 -1
  122. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.br → desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br} +0 -0
  123. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  124. package/dist/server/web-ui/_expo/static/js/web/{index-8868523fc6d311c5da524c067d1cd426.js → index-69ce3c243032c3bedfc6f2ad379a4cdd.js} +1579 -1575
  125. package/dist/server/web-ui/_expo/static/js/web/index-69ce3c243032c3bedfc6f2ad379a4cdd.js.br +0 -0
  126. package/dist/server/web-ui/_expo/static/js/web/index-69ce3c243032c3bedfc6f2ad379a4cdd.js.gz +0 -0
  127. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js} +1 -1
  128. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.br → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br} +0 -0
  129. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  130. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js → native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js} +3 -3
  131. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  132. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
  133. package/dist/server/web-ui/index.html +1 -1
  134. package/dist/server/web-ui/index.html.br +0 -0
  135. package/dist/server/web-ui/index.html.gz +0 -0
  136. package/dist/src/server/daemon-instance.js +1 -0
  137. package/dist/src/server/local-credential.js +82 -0
  138. package/package.json +8 -7
  139. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.gz +0 -0
  140. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.gz +0 -0
  141. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.br +0 -0
  142. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.gz +0 -0
  143. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.gz +0 -0
  144. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.br +0 -0
  145. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.gz +0 -0
@@ -0,0 +1,149 @@
1
+ import { z } from "zod";
2
+ import { extractTextFromToolResult } from "../../tool-call-mapper.js";
3
+ const SpawnArgs = z
4
+ .object({
5
+ subagent_type: z.string().trim().min(1),
6
+ prompt: z.string().trim().min(1),
7
+ description: z.string().optional(),
8
+ })
9
+ .passthrough();
10
+ const FollowupArgs = z.object({ agent_id: z.string().trim().min(1) }).passthrough();
11
+ const Details = z
12
+ .object({
13
+ agentId: z.string().trim().min(1),
14
+ status: z.string(),
15
+ displayName: z.string().optional(),
16
+ description: z.string().optional(),
17
+ })
18
+ .passthrough();
19
+ const Notification = z
20
+ .object({
21
+ id: z.string().trim().min(1),
22
+ status: z.string(),
23
+ description: z.string().optional(),
24
+ outputFile: z.string().trim().min(1).optional(),
25
+ })
26
+ .passthrough();
27
+ const status = (value) => {
28
+ if (value === "completed")
29
+ return "completed";
30
+ if (value === "error")
31
+ return "failed";
32
+ if (value === "aborted" || value === "stopped")
33
+ return "canceled";
34
+ return "running";
35
+ };
36
+ export const tintinwebPiSubagents = {
37
+ id: "@tintinweb/pi-subagents",
38
+ createSession: () => {
39
+ const callsByAgent = new Map();
40
+ const readSessions = new Set();
41
+ const mapSpawn = (call) => {
42
+ const args = SpawnArgs.safeParse(call.args);
43
+ if (!args.success)
44
+ return undefined;
45
+ const details = Details.safeParse(typeof call.result === "object" ? call.result?.details : null);
46
+ const title = args.data.subagent_type;
47
+ const description = args.data.description ?? args.data.prompt;
48
+ const detail = {
49
+ type: "sub_agent",
50
+ subAgentType: title,
51
+ description,
52
+ log: extractTextFromToolResult(call.result)?.trim() ?? "",
53
+ };
54
+ if (call.status === "running")
55
+ return {
56
+ detail,
57
+ subagents: [
58
+ {
59
+ type: "upsert",
60
+ id: call.callId,
61
+ title,
62
+ description,
63
+ toolCallId: call.callId,
64
+ status: "running",
65
+ },
66
+ ],
67
+ };
68
+ if (!details.success)
69
+ return call.status === "failed"
70
+ ? {
71
+ detail,
72
+ subagents: [{ type: "upsert", id: call.callId, status: "failed" }],
73
+ }
74
+ : { detail };
75
+ callsByAgent.set(details.data.agentId, call.callId);
76
+ return {
77
+ detail,
78
+ subagents: [
79
+ {
80
+ type: "upsert",
81
+ id: call.callId,
82
+ title,
83
+ description,
84
+ toolCallId: call.callId,
85
+ status: status(details.data.status),
86
+ },
87
+ ],
88
+ };
89
+ };
90
+ const mapFollowup = (call) => {
91
+ const args = FollowupArgs.safeParse(call.args);
92
+ if (!args.success)
93
+ return undefined;
94
+ const id = callsByAgent.get(args.data.agent_id);
95
+ if (!id)
96
+ return undefined;
97
+ const details = Details.safeParse(typeof call.result === "object" ? call.result?.details : null);
98
+ const detail = {
99
+ type: "sub_agent",
100
+ description: details.success ? details.data.description : undefined,
101
+ log: extractTextFromToolResult(call.result)?.trim() ?? "",
102
+ };
103
+ if (call.status === "running" || !details.success)
104
+ return { detail };
105
+ return {
106
+ detail,
107
+ subagents: [{ type: "upsert", id, status: status(details.data.status) }],
108
+ };
109
+ };
110
+ return {
111
+ mapToolCall(call) {
112
+ if (call.toolName === "Agent")
113
+ return mapSpawn(call);
114
+ if (call.toolName === "get_subagent_result" || call.toolName === "steer_subagent")
115
+ return mapFollowup(call);
116
+ return undefined;
117
+ },
118
+ mapCustomMessage(message) {
119
+ if (message.customType !== "subagent-notification" &&
120
+ message.customType !== "subagent-update")
121
+ return undefined;
122
+ const details = Notification.safeParse(message.details);
123
+ if (!details.success)
124
+ return undefined;
125
+ const id = callsByAgent.get(details.data.id);
126
+ if (!id)
127
+ return undefined;
128
+ const file = details.data.outputFile;
129
+ const childSessions = file && status(details.data.status) !== "running" && !readSessions.has(file)
130
+ ? [{ id, file }]
131
+ : [];
132
+ if (childSessions.length && file)
133
+ readSessions.add(file);
134
+ return {
135
+ subagents: [
136
+ {
137
+ type: "upsert",
138
+ id,
139
+ description: details.data.description,
140
+ status: status(details.data.status),
141
+ },
142
+ ],
143
+ childSessions,
144
+ };
145
+ },
146
+ };
147
+ },
148
+ };
149
+ //# sourceMappingURL=index.js.map
@@ -1,4 +1,5 @@
1
1
  import type { AgentStreamEvent, ToolCallDetail } from "../../agent-sdk-types.js";
2
+ import { type PiExtensionHost } from "./extensions/index.js";
2
3
  import type { PiAgentMessage, PiImageContent, PiTextContent } from "./rpc-types.js";
3
4
  import { type PiToolResult, type PiTrackedToolCall } from "./tool-call-mapper.js";
4
5
  export interface PiCapturedUserMessageEntry {
@@ -19,18 +20,22 @@ export declare class PiHistoryMapper {
19
20
  private readonly provider;
20
21
  private readonly userEntries;
21
22
  private readonly hooks;
23
+ private readonly extensionHost;
22
24
  private readonly pendingToolCalls;
25
+ private readonly hydrations;
23
26
  private userIndex;
24
27
  private assistantIndex;
25
- constructor(provider: string, userEntries?: readonly PiCapturedUserMessageEntry[], hooks?: PiHistoryMapperHooks);
28
+ constructor(provider: string, userEntries?: readonly PiCapturedUserMessageEntry[], hooks?: PiHistoryMapperHooks, extensionHost?: PiExtensionHost);
26
29
  mapMessages(messages: readonly PiAgentMessage[]): AgentStreamEvent[];
30
+ hydrate(): Promise<AgentStreamEvent[]>;
27
31
  private mapUserMessage;
28
32
  private mapCustomMessage;
29
33
  private mapAssistantMessage;
30
34
  private mapToolResultMessage;
35
+ private extensionEvents;
31
36
  private mapBashExecutionMessage;
32
37
  private resolveToolCallId;
33
38
  private mapToolDetail;
34
39
  }
35
- export declare function streamPiHistory(provider: string, messages: PiAgentMessage[], userEntries?: readonly PiCapturedUserMessageEntry[], hooks?: PiHistoryMapperHooks): AsyncGenerator<AgentStreamEvent>;
40
+ export declare function streamPiHistory(provider: string, messages: PiAgentMessage[], userEntries?: readonly PiCapturedUserMessageEntry[], hooks?: PiHistoryMapperHooks, extensionHost?: PiExtensionHost, signal?: AbortSignal): AsyncGenerator<AgentStreamEvent>;
36
41
  //# sourceMappingURL=history-mapper.d.ts.map
@@ -1,4 +1,5 @@
1
- import { extractTextFromToolResult, mapToolDetail, parseToolArgs, parseToolResult, resolveToolCallName, } from "./tool-call-mapper.js";
1
+ import { createPiExtensionHost, } from "./extensions/index.js";
2
+ import { extractTextFromToolResult, mapToolDetail, parseToolArgs, parseToolResult, } from "./tool-call-mapper.js";
2
3
  function isTextContentBlock(block) {
3
4
  return (typeof block === "object" &&
4
5
  block !== null &&
@@ -19,11 +20,13 @@ export function getUserMessageText(content) {
19
20
  return textParts.join("\n\n");
20
21
  }
21
22
  export class PiHistoryMapper {
22
- constructor(provider, userEntries = [], hooks = {}) {
23
+ constructor(provider, userEntries = [], hooks = {}, extensionHost = createPiExtensionHost()) {
23
24
  this.provider = provider;
24
25
  this.userEntries = userEntries;
25
26
  this.hooks = hooks;
27
+ this.extensionHost = extensionHost;
26
28
  this.pendingToolCalls = new Map();
29
+ this.hydrations = [];
27
30
  this.userIndex = 0;
28
31
  this.assistantIndex = 0;
29
32
  }
@@ -41,10 +44,7 @@ export class PiHistoryMapper {
41
44
  events.push(...this.mapAssistantMessage(message));
42
45
  break;
43
46
  case "toolResult": {
44
- const event = this.mapToolResultMessage(message);
45
- if (event) {
46
- events.push(event);
47
- }
47
+ events.push(...this.mapToolResultMessage(message));
48
48
  break;
49
49
  }
50
50
  case "bashExecution":
@@ -54,6 +54,9 @@ export class PiHistoryMapper {
54
54
  }
55
55
  return events;
56
56
  }
57
+ async hydrate() {
58
+ return (await Promise.all(this.hydrations)).flat();
59
+ }
57
60
  mapUserMessage(message) {
58
61
  const text = getUserMessageText(message.content);
59
62
  this.userIndex += 1;
@@ -74,20 +77,25 @@ export class PiHistoryMapper {
74
77
  ];
75
78
  }
76
79
  mapCustomMessage(message) {
80
+ const extensionMapping = this.extensionHost.mapCustomMessage(message);
81
+ const extensionEvents = this.extensionEvents(extensionMapping);
77
82
  const text = getUserMessageText(message.content);
78
83
  const mappedEvent = text ? this.hooks.mapCustomMessage?.(text, this.provider) : null;
79
84
  if (mappedEvent) {
80
- return [mappedEvent];
85
+ return [...extensionEvents, mappedEvent];
81
86
  }
82
- return text
83
- ? [
84
- {
85
- type: "timeline",
86
- provider: this.provider,
87
- item: { type: "assistant_message", text },
88
- },
89
- ]
90
- : [];
87
+ return [
88
+ ...extensionEvents,
89
+ ...(text
90
+ ? [
91
+ {
92
+ type: "timeline",
93
+ provider: this.provider,
94
+ item: { type: "assistant_message", text },
95
+ },
96
+ ]
97
+ : []),
98
+ ];
91
99
  }
92
100
  mapAssistantMessage(message) {
93
101
  const events = [];
@@ -113,7 +121,14 @@ export class PiHistoryMapper {
113
121
  if (content.type === "toolCall") {
114
122
  const tracked = parseToolArgs(content.name, content.arguments);
115
123
  this.pendingToolCalls.set(content.id, tracked);
116
- const detail = this.mapToolDetail(content.id, tracked, null);
124
+ const mapping = this.extensionHost.mapToolCall({
125
+ callId: content.id,
126
+ toolName: tracked.toolName,
127
+ args: tracked.args,
128
+ status: "running",
129
+ result: null,
130
+ });
131
+ const detail = this.mapToolDetail(content.id, tracked, null, mapping?.detail);
117
132
  if (!detail) {
118
133
  continue;
119
134
  }
@@ -123,12 +138,13 @@ export class PiHistoryMapper {
123
138
  item: {
124
139
  type: "tool_call",
125
140
  callId: this.resolveToolCallId(content.id, tracked),
126
- name: tracked.toolName,
141
+ name: mapping?.name ?? tracked.toolName,
127
142
  status: "running",
128
143
  detail,
129
144
  error: null,
130
145
  },
131
146
  });
147
+ events.push(...this.extensionEvents(mapping));
132
148
  }
133
149
  }
134
150
  return events;
@@ -137,21 +153,37 @@ export class PiHistoryMapper {
137
153
  const tracked = this.pendingToolCalls.get(message.toolCallId) ?? parseToolArgs(message.toolName, null);
138
154
  this.pendingToolCalls.delete(message.toolCallId);
139
155
  const result = parseToolResult({ content: message.content, details: message.details });
140
- const detail = this.mapToolDetail(message.toolCallId, tracked, result);
156
+ const mapping = this.extensionHost.mapToolCall({
157
+ callId: message.toolCallId,
158
+ toolName: tracked.toolName,
159
+ args: tracked.args,
160
+ status: message.isError ? "failed" : "completed",
161
+ result,
162
+ });
163
+ const detail = this.mapToolDetail(message.toolCallId, tracked, result, mapping?.detail);
141
164
  if (!detail) {
142
- return null;
165
+ return [];
143
166
  }
144
- return {
145
- type: "timeline",
146
- provider: this.provider,
147
- item: toToolResultTimelineItem({
148
- callId: this.resolveToolCallId(message.toolCallId, tracked),
149
- name: resolveToolCallName(tracked, result),
150
- isError: Boolean(message.isError),
151
- detail,
152
- errorText: extractTextFromToolResult(result) ?? "Tool call failed",
153
- }),
154
- };
167
+ return [
168
+ {
169
+ type: "timeline",
170
+ provider: this.provider,
171
+ item: toToolResultTimelineItem({
172
+ callId: this.resolveToolCallId(message.toolCallId, tracked),
173
+ name: mapping?.name ?? tracked.toolName,
174
+ isError: Boolean(message.isError),
175
+ detail,
176
+ errorText: extractTextFromToolResult(result) ?? "Tool call failed",
177
+ }),
178
+ },
179
+ ...this.extensionEvents(mapping),
180
+ ];
181
+ }
182
+ extensionEvents(mapping) {
183
+ if (!mapping)
184
+ return [];
185
+ this.hydrations.push(mapping.hydration);
186
+ return mapping.events;
155
187
  }
156
188
  mapBashExecutionMessage(message) {
157
189
  const detail = {
@@ -176,18 +208,29 @@ export class PiHistoryMapper {
176
208
  resolveToolCallId(toolCallId, toolCall) {
177
209
  return this.hooks.resolveToolCallId?.(toolCallId, toolCall) ?? toolCallId;
178
210
  }
179
- mapToolDetail(toolCallId, toolCall, result) {
211
+ mapToolDetail(toolCallId, toolCall, result, extensionDetail) {
180
212
  const hook = this.hooks.mapToolDetail;
181
- return hook ? hook(toolCall, result, { toolCallId }) : mapToolDetail(toolCall, result);
213
+ return hook
214
+ ? hook(toolCall, result, { toolCallId })
215
+ : (extensionDetail ?? mapToolDetail(toolCall, result));
182
216
  }
183
217
  }
184
- export async function* streamPiHistory(provider, messages, userEntries = [], hooks = {}) {
185
- const mapper = new PiHistoryMapper(provider, userEntries, hooks);
218
+ export async function* streamPiHistory(provider, messages, userEntries = [], hooks = {},
219
+ // At most eight 2 MiB child files per replay; remaining cards keep their summaries.
220
+ extensionHost = createPiExtensionHost(undefined, undefined, 16 * 1024 * 1024), signal) {
221
+ const mapper = new PiHistoryMapper(provider, userEntries, hooks, extensionHost);
186
222
  for (const event of mapper.mapMessages(messages)) {
223
+ if (signal?.aborted)
224
+ return;
187
225
  if (event) {
188
226
  yield event;
189
227
  }
190
228
  }
229
+ for (const event of await mapper.hydrate()) {
230
+ if (signal?.aborted)
231
+ return;
232
+ yield event;
233
+ }
191
234
  }
192
235
  function toToolResultTimelineItem(input) {
193
236
  if (input.isError) {
@@ -32,6 +32,9 @@ export type PiAgentMessage = {
32
32
  } | {
33
33
  role: "custom";
34
34
  content: string | Array<PiTextContent | PiImageContent>;
35
+ customType?: string;
36
+ details?: unknown;
37
+ display?: boolean;
35
38
  } | {
36
39
  role: "assistant";
37
40
  content: PiAssistantContent[];
@@ -0,0 +1,170 @@
1
+ import type { PiRuntime, PiRuntimeLaunch, PiRuntimeSession, PiStartSessionInput } from "../runtime.js";
2
+ import type { PiAgentMessage, PiModel, PiPromptAck, PiRpcSlashCommand, PiRuntimeEvent, PiSessionState, PiSessionStats } from "../rpc-types.js";
3
+ type FakePiSubagentSubscriptionLevel = "off" | "progress" | "events";
4
+ type FakePiSubagentStatus = "pending" | "running" | "completed" | "failed" | "aborted";
5
+ export interface FakePiSubagentSnapshot {
6
+ id: string;
7
+ index: number;
8
+ agent: string;
9
+ description?: string;
10
+ status: FakePiSubagentStatus;
11
+ task?: string;
12
+ assignment?: string;
13
+ sessionFile?: string;
14
+ parentToolCallId?: string;
15
+ lastUpdate?: number;
16
+ }
17
+ export interface FakePiSubagentMessagesSelector {
18
+ subagentId?: string;
19
+ sessionFile?: string;
20
+ fromByte?: number;
21
+ }
22
+ export interface FakePiSubagentMessagesResult {
23
+ sessionFile: string;
24
+ fromByte: number;
25
+ nextByte: number;
26
+ reset: boolean;
27
+ messages: PiAgentMessage[];
28
+ }
29
+ interface FakePiUserEntry {
30
+ id: string;
31
+ parentId: string | null;
32
+ text: string;
33
+ }
34
+ export declare class FakePi implements PiRuntime {
35
+ readonly recordedLaunches: PiRuntimeLaunch[];
36
+ private readonly sessions;
37
+ private readonly command;
38
+ private readonly queuedCommands;
39
+ private readonly queuedSessionSetups;
40
+ constructor(command?: [string, ...string[]]);
41
+ startSession(input: PiStartSessionInput): Promise<FakePiSession>;
42
+ queueCommands(commands: PiRpcSlashCommand[]): void;
43
+ queueSessionSetup(setup: (session: FakePiSession) => void): void;
44
+ latestSession(): FakePiSession;
45
+ }
46
+ export declare class FakePiSession implements PiRuntimeSession {
47
+ readonly prompts: Array<{
48
+ message: string;
49
+ imageCount: number;
50
+ }>;
51
+ readonly steerCalls: Array<{
52
+ message: string;
53
+ imageCount: number;
54
+ }>;
55
+ steerError: Error | null;
56
+ readonly controlRequests: string[];
57
+ clearQueueError: Error | null;
58
+ readonly compactRequests: Array<{
59
+ customInstructions?: string;
60
+ }>;
61
+ readonly setAutoCompactionRequests: boolean[];
62
+ readonly subagentSubscriptionRequests: FakePiSubagentSubscriptionLevel[];
63
+ readonly subagentMessageRequests: FakePiSubagentMessagesSelector[];
64
+ readonly setModelRequests: Array<{
65
+ provider: string;
66
+ modelId: string;
67
+ }>;
68
+ readonly setThinkingLevelRequests: string[];
69
+ readonly treeNavigationRequests: string[];
70
+ readonly handoffRequests: Array<{
71
+ customInstructions?: string;
72
+ }>;
73
+ readonly sessionNameRequests: string[];
74
+ readonly rawFrames: Array<object & {
75
+ type: string;
76
+ }>;
77
+ treeUserEntries: FakePiUserEntry[];
78
+ contextUserEntries: FakePiUserEntry[];
79
+ abortRequested: boolean;
80
+ readonly canceledExtensionUiRequests: string[];
81
+ readonly extensionUiResponses: Array<{
82
+ id: string;
83
+ response: {
84
+ value?: string;
85
+ confirmed?: boolean;
86
+ cancelled?: boolean;
87
+ };
88
+ }>;
89
+ setModelResult: PiModel | null;
90
+ models: PiModel[];
91
+ messages: PiAgentMessage[];
92
+ stats: PiSessionStats;
93
+ commands: PiRpcSlashCommand[];
94
+ subagents: FakePiSubagentSnapshot[];
95
+ subagentSubscriptionError: Error | null;
96
+ setSessionNameError: Error | null;
97
+ compactError: Error | null;
98
+ emitCompactEnd: boolean;
99
+ getStateError: Error | null;
100
+ getSessionStatsError: Error | null;
101
+ promptAck: PiPromptAck;
102
+ branchResponse: {
103
+ text?: string;
104
+ cancelled?: boolean;
105
+ };
106
+ readonly branchRequests: string[];
107
+ state: PiSessionState;
108
+ private readonly subscribers;
109
+ private readonly subagentMessageResults;
110
+ private nextHeldPrompt;
111
+ private activeHeldPrompt;
112
+ constructor(launch: PiRuntimeLaunch);
113
+ onEvent(callback: (event: PiRuntimeEvent) => void): () => void;
114
+ prompt(message: string, images?: Array<{
115
+ type: "image";
116
+ data: string;
117
+ mimeType: string;
118
+ }>): Promise<PiPromptAck>;
119
+ holdNextPrompt(): void;
120
+ failHeldPrompt(error: Error): Promise<void>;
121
+ steer(message: string, images?: Array<{
122
+ type: "image";
123
+ data: string;
124
+ mimeType: string;
125
+ }>): Promise<void>;
126
+ clearQueue(): Promise<void>;
127
+ compact(customInstructions?: string): Promise<void>;
128
+ setAutoCompaction(enabled: boolean): Promise<void>;
129
+ abort(): Promise<void>;
130
+ getState(): Promise<PiSessionState>;
131
+ getMessages(): Promise<PiAgentMessage[]>;
132
+ getAvailableModels(_timeoutMs?: number | null): Promise<PiModel[]>;
133
+ setModel(provider: string, modelId: string): Promise<PiModel>;
134
+ setThinkingLevel(level: string): Promise<void>;
135
+ getSessionStats(): Promise<PiSessionStats>;
136
+ setSubagentSubscription(level: FakePiSubagentSubscriptionLevel): Promise<void>;
137
+ getSubagents(): Promise<FakePiSubagentSnapshot[]>;
138
+ getSubagentMessages(selector: FakePiSubagentMessagesSelector): Promise<FakePiSubagentMessagesResult>;
139
+ queueSubagentMessages(result: FakePiSubagentMessagesResult): void;
140
+ getCommands(): Promise<PiRpcSlashCommand[]>;
141
+ sendRawFrame(frame: object & {
142
+ type: string;
143
+ }): void;
144
+ request(command: {
145
+ type: string;
146
+ [key: string]: unknown;
147
+ }): Promise<unknown>;
148
+ respondToExtensionUiRequest(id: string, response: {
149
+ value?: string;
150
+ confirmed?: boolean;
151
+ cancelled?: boolean;
152
+ }): void;
153
+ cancelExtensionUiRequest(id: string): void;
154
+ close(): Promise<void>;
155
+ emit(event: PiRuntimeEvent): void;
156
+ finishAgentRun({ message, willRetry }: {
157
+ message: PiAgentMessage;
158
+ willRetry: boolean;
159
+ }): void;
160
+ settleTurn(): void;
161
+ finishTurn(message?: PiAgentMessage): void;
162
+ finishLegacyTurn(message?: PiAgentMessage): void;
163
+ finishSubmittedUserMessage(entry: FakePiUserEntry): void;
164
+ private handleTreeNavigationCommand;
165
+ private handleEntryCaptureCommand;
166
+ emitEntryCapture(requestId?: string, reason?: string): void;
167
+ private emitExtensionCommandResult;
168
+ }
169
+ export {};
170
+ //# sourceMappingURL=fake-pi.d.ts.map