@getpaseo/server 0.9.2 → 0.10.0

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 (148) 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-launch-config.d.ts +2 -2
  8. package/dist/server/server/agent/provider-launch-config.js +1 -1
  9. package/dist/server/server/agent/provider-registry.js +2 -2
  10. package/dist/server/server/agent/providers/acp-agent.js +20 -11
  11. package/dist/server/server/agent/providers/claude/agent.d.ts +1 -2
  12. package/dist/server/server/agent/providers/claude/agent.js +10 -9
  13. package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
  14. package/dist/server/server/agent/providers/claude/models.js +1 -5
  15. package/dist/server/server/agent/providers/claude/project-dir.d.ts +1 -0
  16. package/dist/server/server/agent/providers/claude/project-dir.js +5 -1
  17. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +6 -1
  18. package/dist/server/server/agent/providers/codex-app-server-agent.js +10 -1
  19. package/dist/server/server/agent/providers/generic-acp-agent.js +3 -1
  20. package/dist/server/server/agent/providers/omp/agent.js +23 -6
  21. package/dist/server/server/agent/providers/omp/rpc-types.d.ts +1 -0
  22. package/dist/server/server/agent/providers/omp/rpc-types.js +1 -0
  23. package/dist/server/server/agent/providers/opencode/bridge.d.ts +5 -1
  24. package/dist/server/server/agent/providers/opencode/bridge.js +56 -5
  25. package/dist/server/server/agent/providers/opencode/http-error.d.ts +8 -0
  26. package/dist/server/server/agent/providers/opencode/http-error.js +13 -0
  27. package/dist/server/server/agent/providers/opencode/runtime-client.d.ts +38 -0
  28. package/dist/server/server/agent/providers/opencode/runtime-client.js +131 -0
  29. package/dist/server/server/agent/providers/opencode/runtime-notice.d.ts +3 -0
  30. package/dist/server/server/agent/providers/opencode/runtime-notice.js +47 -0
  31. package/dist/server/server/agent/providers/opencode/server-manager.js +19 -8
  32. package/dist/server/server/agent/providers/opencode/v2/agent.d.ts +36 -0
  33. package/dist/server/server/agent/providers/opencode/v2/agent.js +211 -0
  34. package/dist/server/server/agent/providers/opencode/v2/api.d.ts +18 -0
  35. package/dist/server/server/agent/providers/opencode/v2/api.js +2 -0
  36. package/dist/server/server/agent/providers/opencode/v2/bridge-plugin.bundle.mjs +6693 -0
  37. package/dist/server/server/agent/providers/opencode/v2/capabilities.d.ts +3 -0
  38. package/dist/server/server/agent/providers/opencode/v2/capabilities.js +13 -0
  39. package/dist/server/server/agent/providers/opencode/v2/children.d.ts +20 -0
  40. package/dist/server/server/agent/providers/opencode/v2/children.js +75 -0
  41. package/dist/server/server/agent/providers/opencode/v2/commands.d.ts +4 -0
  42. package/dist/server/server/agent/providers/opencode/v2/commands.js +36 -0
  43. package/dist/server/server/agent/providers/opencode/v2/configuration.d.ts +8 -0
  44. package/dist/server/server/agent/providers/opencode/v2/configuration.js +64 -0
  45. package/dist/server/server/agent/providers/opencode/v2/history.d.ts +4 -0
  46. package/dist/server/server/agent/providers/opencode/v2/history.js +15 -0
  47. package/dist/server/server/agent/providers/opencode/v2/mapping.d.ts +7 -0
  48. package/dist/server/server/agent/providers/opencode/v2/mapping.js +42 -0
  49. package/dist/server/server/agent/providers/opencode/v2/permissions.d.ts +18 -0
  50. package/dist/server/server/agent/providers/opencode/v2/permissions.js +157 -0
  51. package/dist/server/server/agent/providers/opencode/v2/readiness.d.ts +18 -0
  52. package/dist/server/server/agent/providers/opencode/v2/readiness.js +51 -0
  53. package/dist/server/server/agent/providers/opencode/v2/runtime.d.ts +36 -0
  54. package/dist/server/server/agent/providers/opencode/v2/runtime.js +230 -0
  55. package/dist/server/server/agent/providers/opencode/v2/session.d.ts +84 -0
  56. package/dist/server/server/agent/providers/opencode/v2/session.js +468 -0
  57. package/dist/server/server/agent/providers/opencode/v2/structured-output.d.ts +8 -0
  58. package/dist/server/server/agent/providers/opencode/v2/structured-output.js +32 -0
  59. package/dist/server/server/agent/providers/opencode/v2/timeline.d.ts +28 -0
  60. package/dist/server/server/agent/providers/opencode/v2/timeline.js +154 -0
  61. package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +40 -0
  62. package/dist/server/server/agent/providers/opencode/v2/turns.js +226 -0
  63. package/dist/server/server/agent/providers/opencode-agent.d.ts +26 -7
  64. package/dist/server/server/agent/providers/opencode-agent.js +100 -40
  65. package/dist/server/server/agent/providers/pi/agent.d.ts +6 -6
  66. package/dist/server/server/agent/providers/pi/agent.js +114 -165
  67. package/dist/server/server/agent/providers/pi/extensions/child-session.d.ts +4 -0
  68. package/dist/server/server/agent/providers/pi/extensions/child-session.js +59 -0
  69. package/dist/server/server/agent/providers/pi/extensions/contract.d.ts +68 -0
  70. package/dist/server/server/agent/providers/pi/extensions/contract.js +2 -0
  71. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.d.ts +3 -0
  72. package/dist/server/server/agent/providers/pi/extensions/gotgenes-pi-subagents/index.js +159 -0
  73. package/dist/server/server/agent/providers/pi/extensions/host.d.ts +28 -0
  74. package/dist/server/server/agent/providers/pi/extensions/host.js +94 -0
  75. package/dist/server/server/agent/providers/pi/extensions/index.d.ts +7 -0
  76. package/dist/server/server/agent/providers/pi/extensions/index.js +6 -0
  77. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.d.ts +3 -0
  78. package/dist/server/server/agent/providers/pi/extensions/pi-ask-user/index.js +138 -0
  79. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.d.ts +3 -0
  80. package/dist/server/server/agent/providers/pi/extensions/pi-example-todo/index.js +38 -0
  81. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.d.ts +3 -0
  82. package/dist/server/server/agent/providers/pi/extensions/pi-goal-x/index.js +63 -0
  83. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.d.ts +3 -0
  84. package/dist/server/server/agent/providers/pi/extensions/pi-mcp-adapter/index.js +48 -0
  85. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.d.ts +3 -0
  86. package/dist/server/server/agent/providers/pi/extensions/pi-subagents/index.js +131 -0
  87. package/dist/server/server/agent/providers/pi/extensions/registry.d.ts +2 -0
  88. package/dist/server/server/agent/providers/pi/extensions/registry.js +21 -0
  89. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.d.ts +3 -0
  90. package/dist/server/server/agent/providers/pi/extensions/rpiv-ask-user-question/index.js +180 -0
  91. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.d.ts +3 -0
  92. package/dist/server/server/agent/providers/pi/extensions/rpiv-todo/index.js +51 -0
  93. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.d.ts +22 -0
  94. package/dist/server/server/agent/providers/pi/extensions/subagent-fixture-test.js +66 -0
  95. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.d.ts +4 -0
  96. package/dist/server/server/agent/providers/pi/extensions/task-fixture-test.js +79 -0
  97. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.d.ts +3 -0
  98. package/dist/server/server/agent/providers/pi/extensions/tintinweb-pi-subagents/index.js +149 -0
  99. package/dist/server/server/agent/providers/pi/history-mapper.d.ts +7 -2
  100. package/dist/server/server/agent/providers/pi/history-mapper.js +78 -35
  101. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +3 -0
  102. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +170 -0
  103. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +355 -0
  104. package/dist/server/server/agent/providers/pi/tool-call-mapper.d.ts +1 -6
  105. package/dist/server/server/agent/providers/pi/tool-call-mapper.js +1 -97
  106. package/dist/server/server/agent/tools/paseo-tools.js +22 -15
  107. package/dist/server/server/auth.d.ts +1 -2
  108. package/dist/server/server/auth.js +8 -14
  109. package/dist/server/server/bootstrap.js +10 -2
  110. package/dist/server/server/daemon-instance.d.ts +1 -0
  111. package/dist/server/server/daemon-instance.js +1 -0
  112. package/dist/server/server/exports.d.ts +1 -1
  113. package/dist/server/server/exports.js +1 -1
  114. package/dist/server/server/local-credential.d.ts +6 -0
  115. package/dist/server/server/local-credential.js +82 -0
  116. package/dist/server/server/session-admission-auth.d.ts +16 -0
  117. package/dist/server/server/session-admission-auth.js +26 -0
  118. package/dist/server/server/websocket-server.d.ts +6 -1
  119. package/dist/server/server/websocket-server.js +132 -55
  120. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js} +1 -1
  121. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.br → desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br} +0 -0
  122. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz +0 -0
  123. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js → desktop-attachment-store-d5d3402a752965d3037191484127123b.js} +1 -1
  124. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.br → desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br} +0 -0
  125. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  126. package/dist/server/web-ui/_expo/static/js/web/{index-8868523fc6d311c5da524c067d1cd426.js → index-136fa41d4adb7ec5c6392839cc354136.js} +1580 -1576
  127. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.br +0 -0
  128. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.gz +0 -0
  129. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js} +1 -1
  130. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.br → indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br} +0 -0
  131. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  132. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js → native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js} +3 -3
  133. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  134. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
  135. package/dist/server/web-ui/index.html +1 -1
  136. package/dist/server/web-ui/index.html.br +0 -0
  137. package/dist/server/web-ui/index.html.gz +0 -0
  138. package/dist/src/server/agent/provider-launch-config.js +1 -1
  139. package/dist/src/server/daemon-instance.js +1 -0
  140. package/dist/src/server/local-credential.js +82 -0
  141. package/package.json +8 -7
  142. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-f41bce08c3c4ac2de0652d20234d19e9.js.gz +0 -0
  143. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-9e271e161480b0d1dd35e58616a37341.js.gz +0 -0
  144. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.br +0 -0
  145. package/dist/server/web-ui/_expo/static/js/web/index-8868523fc6d311c5da524c067d1cd426.js.gz +0 -0
  146. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-369cdb67f5856fd2c72d640df0b7b79e.js.gz +0 -0
  147. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.br +0 -0
  148. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-bcd89f6ce714279a8f4fa0e024f3a610.js.gz +0 -0
@@ -0,0 +1,40 @@
1
+ import type { SessionInfo, SessionMessageInfo } from "@opencode/client";
2
+ import type { AgentPromptInput, AgentRunOptions, AgentStreamEvent, SteerActiveTurnOptions, SteerResult } from "../../../agent-sdk-types.js";
3
+ import type { V2Api } from "./api.js";
4
+ interface TurnSnapshot {
5
+ info: SessionInfo;
6
+ history: SessionMessageInfo[];
7
+ }
8
+ interface TurnOptions {
9
+ client(): V2Api;
10
+ id: string;
11
+ cwd: string;
12
+ signal: AbortSignal;
13
+ emit(event: AgentStreamEvent): void;
14
+ reconcile(): Promise<TurnSnapshot>;
15
+ clearPermissions(): Promise<void>;
16
+ }
17
+ export declare class SessionTurns {
18
+ private readonly options;
19
+ private turn;
20
+ private stopping;
21
+ private stopFailed;
22
+ executionError: string | null;
23
+ constructor(options: TurnOptions);
24
+ get id(): string | undefined;
25
+ get hasStructuredOutput(): boolean;
26
+ fail(error: Error): void;
27
+ startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{
28
+ turnId: `${string}-${string}-${string}-${string}-${string}`;
29
+ }>;
30
+ private submit;
31
+ private dispatch;
32
+ private finish;
33
+ private readExecutionError;
34
+ private promptInput;
35
+ steerActiveTurn(prompt: AgentPromptInput, options: SteerActiveTurnOptions): Promise<SteerResult>;
36
+ interrupt(): Promise<void>;
37
+ observeActiveTurn(): void;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=turns.d.ts.map
@@ -0,0 +1,226 @@
1
+ import { structuredOutput } from "./structured-output.js";
2
+ import { randomUUID } from "node:crypto";
3
+ import { toDiagnosticErrorMessage } from "../../diagnostic-utils.js";
4
+ import { renderPromptAttachmentAsText } from "../../../prompt-attachments.js";
5
+ import { usageFromV2 } from "./mapping.js";
6
+ import { commands } from "./commands.js";
7
+ export class SessionTurns {
8
+ constructor(options) {
9
+ this.options = options;
10
+ this.turn = null;
11
+ this.stopping = null;
12
+ this.stopFailed = false;
13
+ this.executionError = null;
14
+ }
15
+ get id() {
16
+ return this.turn?.id;
17
+ }
18
+ get hasStructuredOutput() {
19
+ return Boolean(this.turn?.output);
20
+ }
21
+ fail(error) {
22
+ const turn = this.turn;
23
+ this.turn = null;
24
+ if (turn)
25
+ this.options.emit({
26
+ type: "turn_failed",
27
+ provider: "opencode",
28
+ turnId: turn.id,
29
+ error: error.message,
30
+ });
31
+ }
32
+ async startTurn(prompt, options) {
33
+ await this.stopping;
34
+ if (this.options.signal.aborted)
35
+ throw new Error("OpenCode session is closed");
36
+ if (this.turn)
37
+ throw new Error("OpenCode session already has an active turn");
38
+ this.executionError = null;
39
+ const id = randomUUID();
40
+ const input = this.promptInput(prompt);
41
+ let accept;
42
+ const submitted = new Promise((resolve) => {
43
+ accept = resolve;
44
+ });
45
+ const output = options?.outputSchema === undefined ? undefined : structuredOutput(options.outputSchema);
46
+ const completion = this.submit(id, input, accept, options, output);
47
+ this.turn = { id, submitted, completion, output };
48
+ return { turnId: id };
49
+ }
50
+ async submit(id, input, accept, options, output) {
51
+ // Defer until startTurn publishes ownership, including for immediately resolved test transports.
52
+ await Promise.resolve();
53
+ this.options.emit({ type: "turn_started", provider: "opencode", turnId: id });
54
+ try {
55
+ await this.dispatch(input, options, output);
56
+ accept();
57
+ await this.finish(id);
58
+ }
59
+ catch (error) {
60
+ if (this.turn?.id === id) {
61
+ this.turn = null;
62
+ this.options.emit({
63
+ type: "turn_failed",
64
+ provider: "opencode",
65
+ turnId: id,
66
+ error: toDiagnosticErrorMessage(error),
67
+ });
68
+ }
69
+ }
70
+ finally {
71
+ accept();
72
+ }
73
+ }
74
+ async dispatch(input, options, output) {
75
+ const command = input.text.match(/^\/([^\s]+)(?:\s+([\s\S]*))?$/);
76
+ if (command?.[1] === "compact" || command?.[1] === "summarize") {
77
+ await this.options.client().session.compact({ sessionID: this.options.id });
78
+ return;
79
+ }
80
+ const selected = command
81
+ ? (await commands(this.options.client(), this.options.cwd)).find((item) => item.name === command[1])
82
+ : undefined;
83
+ if (selected && selected.kind !== "skill") {
84
+ await this.options.client().session.command({
85
+ sessionID: this.options.id,
86
+ name: selected.name,
87
+ text: command?.[2] ?? "",
88
+ files: input.files,
89
+ });
90
+ return;
91
+ }
92
+ await this.options.client().session.prompt({
93
+ sessionID: this.options.id,
94
+ ...input,
95
+ ...(selected?.kind === "skill"
96
+ ? {
97
+ skills: [{ id: selected.name }],
98
+ text: command?.[2] ?? `Use the ${selected.name} skill.`,
99
+ }
100
+ : {}),
101
+ metadata: {
102
+ ...(options?.clientMessageId ? { paseoClientMessageId: options.clientMessageId } : {}),
103
+ ...(output ? { paseoOutputSchema: output.schema } : {}),
104
+ },
105
+ });
106
+ }
107
+ async finish(id) {
108
+ await this.options
109
+ .client()
110
+ .session.wait({ sessionID: this.options.id }, { signal: this.options.signal });
111
+ const { info, history } = await this.options.reconcile();
112
+ if (this.turn?.id !== id)
113
+ return;
114
+ if (info.outcome !== "failed" && info.outcome !== "interrupted")
115
+ this.turn.output?.assert(history);
116
+ const failure = info.outcome === "failed" ? (this.executionError ?? (await this.readExecutionError())) : null;
117
+ if (this.turn?.id !== id)
118
+ return;
119
+ this.turn = null;
120
+ if (info.outcome === "interrupted")
121
+ this.options.emit({
122
+ type: "turn_canceled",
123
+ provider: "opencode",
124
+ turnId: id,
125
+ reason: "OpenCode interrupted execution",
126
+ });
127
+ else if (info.outcome === "failed")
128
+ this.options.emit({
129
+ type: "turn_failed",
130
+ provider: "opencode",
131
+ turnId: id,
132
+ error: failure ?? "OpenCode execution failed",
133
+ });
134
+ else
135
+ this.options.emit({
136
+ type: "turn_completed",
137
+ provider: "opencode",
138
+ turnId: id,
139
+ usage: usageFromV2(info),
140
+ });
141
+ }
142
+ async readExecutionError() {
143
+ let message = "OpenCode execution failed";
144
+ for await (const event of this.options
145
+ .client()
146
+ .session.log({ sessionID: this.options.id, follow: false }, { signal: this.options.signal })) {
147
+ if (event.type === "session.execution.failed")
148
+ message = event.data.error.message;
149
+ }
150
+ return message;
151
+ }
152
+ promptInput(prompt) {
153
+ if (typeof prompt === "string")
154
+ return { text: prompt, files: [] };
155
+ const text = [];
156
+ const files = [];
157
+ for (const part of prompt) {
158
+ if (part.type === "text")
159
+ text.push(part.text);
160
+ else if (part.type === "image")
161
+ files.push({ uri: `data:${part.mimeType};base64,${part.data}` });
162
+ else
163
+ text.push(renderPromptAttachmentAsText(part));
164
+ }
165
+ return { text: text.join("\n"), files };
166
+ }
167
+ async steerActiveTurn(prompt, options) {
168
+ if (this.turn?.id !== options.expectedTurnId || this.stopping)
169
+ return { status: "unavailable" };
170
+ await this.options.client().session.prompt({
171
+ sessionID: this.options.id,
172
+ ...this.promptInput(prompt),
173
+ delivery: "steer",
174
+ metadata: options.clientMessageId
175
+ ? { paseoClientMessageId: options.clientMessageId }
176
+ : undefined,
177
+ });
178
+ if (options.clearPendingPermissions)
179
+ await this.options.clearPermissions();
180
+ return { status: "accepted" };
181
+ }
182
+ async interrupt() {
183
+ if (!this.stopping || this.stopFailed) {
184
+ this.stopFailed = false;
185
+ const turn = this.turn;
186
+ const stop = (async () => {
187
+ // A stop sent before the queued prompt is accepted would interrupt an idle session.
188
+ await turn?.submitted;
189
+ await this.options.client().session.interrupt({ sessionID: this.options.id });
190
+ await turn?.completion;
191
+ })();
192
+ this.stopping = stop;
193
+ try {
194
+ await stop;
195
+ this.stopping = null;
196
+ }
197
+ catch (error) {
198
+ this.stopFailed = true;
199
+ throw error;
200
+ }
201
+ }
202
+ else
203
+ await this.stopping;
204
+ }
205
+ observeActiveTurn() {
206
+ if (this.turn)
207
+ return;
208
+ const id = randomUUID();
209
+ const completion = Promise.resolve()
210
+ .then(() => this.finish(id))
211
+ .catch((error) => {
212
+ if (this.turn?.id !== id)
213
+ return;
214
+ this.turn = null;
215
+ this.options.emit({
216
+ type: "turn_failed",
217
+ provider: "opencode",
218
+ turnId: id,
219
+ error: toDiagnosticErrorMessage(error),
220
+ });
221
+ });
222
+ this.turn = { id, submitted: Promise.resolve(), completion };
223
+ this.options.emit({ type: "turn_started", provider: "opencode", turnId: id });
224
+ }
225
+ }
226
+ //# sourceMappingURL=turns.js.map
@@ -129,6 +129,8 @@ export declare class OpenCodeAgentClient implements AgentClient {
129
129
  createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext, options?: AgentCreateSessionOptions): Promise<AgentSession>;
130
130
  resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launchContext?: AgentLaunchContext): Promise<AgentSession>;
131
131
  private applySessionPermissionRules;
132
+ private connectServer;
133
+ private toServerConnection;
132
134
  private acquireServer;
133
135
  private bindBridgeSession;
134
136
  fetchCatalog(options: FetchCatalogOptions, context?: ProviderRefreshContext): Promise<ProviderCatalog>;
@@ -195,15 +197,24 @@ interface OpenCodeSubAgentActivityState {
195
197
  childSessionId?: string;
196
198
  }
197
199
  export declare function translateOpenCodeEvent(event: OpenCodeEvent, state: OpenCodeEventTranslationState): AgentStreamEvent[];
200
+ /** One OpenCode server generation a session talks to. */
201
+ interface OpenCodeServerConnection {
202
+ client: OpencodeClient;
203
+ events: OpenCodeEventSource;
204
+ url: string;
205
+ release: () => Promise<void>;
206
+ }
198
207
  declare class OpenCodeAgentSession implements AgentSession {
199
- private readonly events;
200
208
  private readonly agentId?;
201
- private readonly serverUrl?;
202
209
  private readonly externallyDriven;
203
210
  readonly provider: "opencode";
204
211
  readonly capabilities: AgentCapabilityFlags;
205
212
  private readonly config;
206
- private readonly client;
213
+ private server;
214
+ /** Connects to the server generation that is current now. */
215
+ private readonly connectServer;
216
+ private serverExited;
217
+ private reconnection;
207
218
  private readonly sessionId;
208
219
  private readonly logger;
209
220
  private readonly modelContextWindowsByModelKey;
@@ -213,8 +224,7 @@ declare class OpenCodeAgentSession implements AgentSession {
213
224
  private abortController;
214
225
  private accumulatedUsage;
215
226
  private sessionTotalCostUsd;
216
- private mcpConfigured;
217
- private mcpSetupPromise;
227
+ private mcpSetup;
218
228
  private messageRoles;
219
229
  private pendingUserMessageText;
220
230
  private pendingClientMessageId;
@@ -252,7 +262,6 @@ declare class OpenCodeAgentSession implements AgentSession {
252
262
  private childHydrationCompleted;
253
263
  private readonly unrelatedSessionIds;
254
264
  private selectedModelContextWindowMaxTokens;
255
- private releaseServer;
256
265
  private releaseBridge;
257
266
  private ingress;
258
267
  private gapRepairRevision;
@@ -261,7 +270,17 @@ declare class OpenCodeAgentSession implements AgentSession {
261
270
  private closed;
262
271
  private readonly persistSession;
263
272
  private deletedFromProvider;
264
- constructor(config: OpenCodeAgentConfig, client: OpencodeClient, sessionId: string, logger: Logger, modelContextWindowsByModelKey?: ReadonlyMap<string, number>, events?: OpenCodeEventSource, releaseServer?: () => Promise<void>, persistSession?: boolean, agentId?: string | undefined, serverUrl?: string | undefined, externallyDriven?: boolean, releaseBridge?: () => void);
273
+ constructor(config: OpenCodeAgentConfig, client: OpencodeClient, sessionId: string, logger: Logger, modelContextWindowsByModelKey?: ReadonlyMap<string, number>, events?: OpenCodeEventSource, releaseServer?: () => Promise<void>, persistSession?: boolean, agentId?: string | undefined, serverUrl?: string, externallyDriven?: boolean, releaseBridge?: () => void, connectServer?: () => Promise<OpenCodeServerConnection>);
274
+ private get client();
275
+ private get events();
276
+ private subscribeServerEvents;
277
+ /**
278
+ * The OpenCode session outlives the server process that served it, and Paseo starts the
279
+ * next server on a new port. Move to the current server before talking to OpenCode again,
280
+ * so the session does not keep calling a port nothing listens on.
281
+ */
282
+ private reconnectIfServerExited;
283
+ private reconnect;
265
284
  get id(): string | null;
266
285
  private get activeForegroundTurnId();
267
286
  get features(): AgentFeature[];
@@ -912,7 +912,7 @@ function buildOpenCodeReplayTimelineEvents(message) {
912
912
  }
913
913
  if (info.role === "user") {
914
914
  const text = parts
915
- .filter((part) => part.type === "text")
915
+ .filter((part) => part.type === "text" && isUserAuthoredOpenCodeText(part))
916
916
  .map((part) => part.text)
917
917
  .join("");
918
918
  return text
@@ -1001,12 +1001,9 @@ export class OpenCodeAgentClient {
1001
1001
  }
1002
1002
  async createSession(config, launchContext, options) {
1003
1003
  const openCodeConfig = this.assertConfig(config);
1004
- const acquisition = await this.acquireServer(openCodeConfig, launchContext);
1005
- const { url } = acquisition.server;
1006
- const client = this.createOpenCodeClient({
1007
- baseUrl: url,
1008
- directory: openCodeConfig.cwd,
1009
- });
1004
+ const connectServer = this.connectServer.bind(this, openCodeConfig, launchContext);
1005
+ const connection = await connectServer();
1006
+ const { client } = connection;
1010
1007
  // OpenCode stores permission rules on the session, so they are set here and on resume
1011
1008
  // rather than sent with each prompt, which drops them.
1012
1009
  const permission = buildOpenCodePermissionRules(openCodeConfig.providerOptions, openCodeConfig.toolPolicy);
@@ -1027,10 +1024,10 @@ export class OpenCodeAgentClient {
1027
1024
  }
1028
1025
  await this.populateModelContextWindowCache(client, openCodeConfig.cwd);
1029
1026
  const unbindBridge = this.bindBridgeSession(session.id, launchContext);
1030
- return new OpenCodeAgentSession(openCodeConfig, client, session.id, this.logger, new Map(this.modelContextWindows), acquisition.events, acquisition.release, options?.persistSession, launchContext?.agentId, url, false, unbindBridge);
1027
+ return new OpenCodeAgentSession(openCodeConfig, client, session.id, this.logger, new Map(this.modelContextWindows), connection.events, connection.release, options?.persistSession, launchContext?.agentId, connection.url, false, unbindBridge, connectServer);
1031
1028
  }
1032
1029
  catch (error) {
1033
- await acquisition.release();
1030
+ await connection.release();
1034
1031
  throw error;
1035
1032
  }
1036
1033
  }
@@ -1051,20 +1048,19 @@ export class OpenCodeAgentClient {
1051
1048
  const registeredAcquisition = registeredServerUrl
1052
1049
  ? this.serverManager.acquireExisting(registeredServerUrl)
1053
1050
  : null;
1054
- const acquisition = registeredAcquisition ?? (await this.acquireServer(openCodeConfig, launchContext));
1055
- const { url } = acquisition.server;
1056
- const client = this.createOpenCodeClient({
1057
- baseUrl: url,
1058
- directory: openCodeConfig.cwd,
1059
- });
1051
+ const connectServer = this.connectServer.bind(this, openCodeConfig, launchContext);
1052
+ const connection = registeredAcquisition
1053
+ ? this.toServerConnection(registeredAcquisition, openCodeConfig.cwd)
1054
+ : await connectServer();
1055
+ const { client } = connection;
1060
1056
  try {
1061
1057
  await this.applySessionPermissionRules(client, openCodeConfig, handle.sessionId);
1062
1058
  await this.populateModelContextWindowCache(client, openCodeConfig.cwd);
1063
1059
  const unbindBridge = this.bindBridgeSession(handle.sessionId, launchContext);
1064
- return new OpenCodeAgentSession(openCodeConfig, client, handle.sessionId, this.logger, new Map(this.modelContextWindows), acquisition.events, acquisition.release, undefined, launchContext?.agentId, url, registeredAcquisition !== null, unbindBridge);
1060
+ return new OpenCodeAgentSession(openCodeConfig, client, handle.sessionId, this.logger, new Map(this.modelContextWindows), connection.events, connection.release, undefined, launchContext?.agentId, connection.url, registeredAcquisition !== null, unbindBridge, connectServer);
1065
1061
  }
1066
1062
  catch (error) {
1067
- await acquisition.release();
1063
+ await connection.release();
1068
1064
  throw error;
1069
1065
  }
1070
1066
  }
@@ -1077,6 +1073,18 @@ export class OpenCodeAgentClient {
1077
1073
  throw new Error(`Failed to apply OpenCode session permission rules: ${toDiagnosticErrorMessage(response.error)}`);
1078
1074
  }
1079
1075
  }
1076
+ async connectServer(config, launchContext) {
1077
+ const acquisition = await this.acquireServer(config, launchContext);
1078
+ return this.toServerConnection(acquisition, config.cwd);
1079
+ }
1080
+ toServerConnection(acquisition, directory) {
1081
+ return {
1082
+ client: this.createOpenCodeClient({ baseUrl: acquisition.server.url, directory }),
1083
+ events: acquisition.events,
1084
+ url: acquisition.server.url,
1085
+ release: acquisition.release,
1086
+ };
1087
+ }
1080
1088
  acquireServer(config, launchContext) {
1081
1089
  if (!this.bridge || requiresDedicatedOpenCodeServer(config, launchContext)) {
1082
1090
  return launchContext?.env
@@ -1997,9 +2005,15 @@ function shouldSuppressOpenCodeAssistantPart(part, messageRole, state) {
1997
2005
  part.type === "text" &&
1998
2006
  messageRole !== "user");
1999
2007
  }
2008
+ // OpenCode marks text it adds to a user message itself with `synthetic` and hides it from its own UI.
2009
+ function isUserAuthoredOpenCodeText(part) {
2010
+ return part.synthetic !== true;
2011
+ }
2000
2012
  function appendOpenCodeTextPart(part, messageRole, state, events) {
2001
2013
  if (messageRole === "user") {
2002
- if (!part.text || state.emittedUserMessageIds?.has(part.messageID)) {
2014
+ if (!part.text ||
2015
+ !isUserAuthoredOpenCodeText(part) ||
2016
+ state.emittedUserMessageIds?.has(part.messageID)) {
2003
2017
  return;
2004
2018
  }
2005
2019
  state.emittedUserMessageIds?.add(part.messageID);
@@ -2376,20 +2390,19 @@ async function listOpenCodeChildSessions(client, sessionId, directory, signal) {
2376
2390
  return readOpenCodeChildSessionInfosFromResponse(sessionIdResponse) ?? [];
2377
2391
  }
2378
2392
  class OpenCodeAgentSession {
2379
- constructor(config, client, sessionId, logger, modelContextWindowsByModelKey = new Map(), events = EMPTY_OPENCODE_EVENT_SOURCE, releaseServer, persistSession = true, agentId, serverUrl, externallyDriven = false, releaseBridge) {
2380
- this.events = events;
2393
+ constructor(config, client, sessionId, logger, modelContextWindowsByModelKey = new Map(), events = EMPTY_OPENCODE_EVENT_SOURCE, releaseServer = async () => undefined, persistSession = true, agentId, serverUrl, externallyDriven = false, releaseBridge, connectServer) {
2381
2394
  this.agentId = agentId;
2382
- this.serverUrl = serverUrl;
2383
2395
  this.externallyDriven = externallyDriven;
2384
2396
  this.provider = "opencode";
2385
2397
  this.capabilities = OPENCODE_CAPABILITIES;
2398
+ this.serverExited = false;
2399
+ this.reconnection = null;
2386
2400
  this.currentMode = null;
2387
2401
  this.autoAcceptEnabled = false;
2388
2402
  this.pendingPermissions = new Map();
2389
2403
  this.abortController = null;
2390
2404
  this.accumulatedUsage = {};
2391
- this.mcpConfigured = false;
2392
- this.mcpSetupPromise = null;
2405
+ this.mcpSetup = null;
2393
2406
  this.messageRoles = new Map();
2394
2407
  this.pendingUserMessageText = null;
2395
2408
  this.pendingClientMessageId = null;
@@ -2433,19 +2446,30 @@ class OpenCodeAgentSession {
2433
2446
  this.closed = false;
2434
2447
  this.deletedFromProvider = false;
2435
2448
  this.config = config;
2436
- this.client = client;
2449
+ this.server = { client, events, url: serverUrl ?? "", release: releaseServer };
2450
+ this.connectServer = connectServer ?? null;
2437
2451
  this.sessionId = sessionId;
2438
2452
  this.logger = logger.child({ agentId: this.agentId });
2439
2453
  this.modelContextWindowsByModelKey = modelContextWindowsByModelKey;
2440
2454
  this.currentMode = normalizeOpenCodeModeId(config.modeId);
2441
2455
  this.autoAcceptEnabled = !config.toolPolicy && isOpenCodeAutoAcceptEnabled(config);
2442
- this.releaseServer = releaseServer ?? null;
2443
2456
  this.releaseBridge = releaseBridge ?? null;
2444
2457
  this.persistSession = persistSession;
2445
2458
  this.selectedModelContextWindowMaxTokens = this.resolveConfiguredModelContextWindowMaxTokens(config.model);
2459
+ this.subscribeServerEvents();
2460
+ }
2461
+ get client() {
2462
+ return this.server.client;
2463
+ }
2464
+ get events() {
2465
+ return this.server.events;
2466
+ }
2467
+ subscribeServerEvents() {
2446
2468
  this.unsubscribeEvents = this.events.subscribe((input) => {
2447
- if ("type" in input && input.type === "server-exited")
2469
+ if ("type" in input && input.type === "server-exited") {
2448
2470
  this.recoveryAbortController.abort(input.error);
2471
+ this.serverExited = true;
2472
+ }
2449
2473
  this.ingress = this.ingress
2450
2474
  .then(() => this.consumeEventSourceInput(input))
2451
2475
  .catch((error) => {
@@ -2453,6 +2477,43 @@ class OpenCodeAgentSession {
2453
2477
  });
2454
2478
  });
2455
2479
  }
2480
+ /**
2481
+ * The OpenCode session outlives the server process that served it, and Paseo starts the
2482
+ * next server on a new port. Move to the current server before talking to OpenCode again,
2483
+ * so the session does not keep calling a port nothing listens on.
2484
+ */
2485
+ async reconnectIfServerExited() {
2486
+ if (!this.serverExited || !this.connectServer)
2487
+ return;
2488
+ this.reconnection ?? (this.reconnection = this.reconnect(this.connectServer).finally(() => {
2489
+ this.reconnection = null;
2490
+ }));
2491
+ await this.reconnection;
2492
+ }
2493
+ async reconnect(connectServer) {
2494
+ const exited = this.server;
2495
+ const next = await connectServer();
2496
+ if (this.closed) {
2497
+ await next.release();
2498
+ return;
2499
+ }
2500
+ this.unsubscribeEvents?.();
2501
+ this.unsubscribeEvents = null;
2502
+ // Let the exited server's queued events, including its exit, settle while no turn is
2503
+ // running, so none of them can fail a turn started on the new server.
2504
+ await this.ingress;
2505
+ if (this.closed) {
2506
+ await next.release();
2507
+ return;
2508
+ }
2509
+ this.server = next;
2510
+ this.serverExited = false;
2511
+ this.recoveryAbortController = new AbortController();
2512
+ this.mcpSetup = null;
2513
+ this.subscribeServerEvents();
2514
+ this.logger.info({ sessionId: this.sessionId, previousUrl: exited.url, url: next.url }, "OpenCode session moved to the current server after its server exited");
2515
+ await exited.release();
2516
+ }
2456
2517
  get id() {
2457
2518
  return this.sessionId;
2458
2519
  }
@@ -2580,6 +2641,7 @@ class OpenCodeAgentSession {
2580
2641
  }
2581
2642
  }
2582
2643
  async revertBoth(input) {
2644
+ await this.reconnectIfServerExited();
2583
2645
  await revertOpenCodeConversationAndFiles({
2584
2646
  client: this.client,
2585
2647
  sessionId: this.sessionId,
@@ -2680,6 +2742,7 @@ class OpenCodeAgentSession {
2680
2742
  if (this.turnState.status === "running") {
2681
2743
  throw new Error("A foreground turn is already active");
2682
2744
  }
2745
+ await this.reconnectIfServerExited();
2683
2746
  try {
2684
2747
  await this.awaitRunnerQuiescence();
2685
2748
  }
@@ -3094,8 +3157,8 @@ class OpenCodeAgentSession {
3094
3157
  if (event.event.cwd) {
3095
3158
  this.childSessionCwds.set(event.event.id, event.event.cwd);
3096
3159
  }
3097
- if (this.serverUrl) {
3098
- registerOpenCodeChildSessionServerUrl(event.event.id, this.serverUrl);
3160
+ if (this.server.url) {
3161
+ registerOpenCodeChildSessionServerUrl(event.event.id, this.server.url);
3099
3162
  }
3100
3163
  }
3101
3164
  else if (event.event.type === "remove") {
@@ -3574,6 +3637,7 @@ class OpenCodeAgentSession {
3574
3637
  }, msg);
3575
3638
  }
3576
3639
  async *streamHistory() {
3640
+ await this.reconnectIfServerExited();
3577
3641
  const sessionResponse = await this.client.session.get({
3578
3642
  sessionID: this.sessionId,
3579
3643
  directory: this.config.cwd,
@@ -3596,6 +3660,7 @@ class OpenCodeAgentSession {
3596
3660
  if (this.availableModesCache) {
3597
3661
  return this.availableModesCache;
3598
3662
  }
3663
+ await this.reconnectIfServerExited();
3599
3664
  const response = await openCodeMetadataLimit(() => this.client.app.agents({
3600
3665
  directory: this.config.cwd,
3601
3666
  }));
@@ -3608,6 +3673,7 @@ class OpenCodeAgentSession {
3608
3673
  return this.currentMode;
3609
3674
  }
3610
3675
  async listCommands() {
3676
+ await this.reconnectIfServerExited();
3611
3677
  return await listOpenCodeCommandsFromSdk(this.client, this.config.cwd);
3612
3678
  }
3613
3679
  async setMode(modeId) {
@@ -3714,8 +3780,7 @@ class OpenCodeAgentSession {
3714
3780
  finally {
3715
3781
  this.releaseBridge?.();
3716
3782
  this.releaseBridge = null;
3717
- await this.releaseServer?.();
3718
- this.releaseServer = null;
3783
+ await this.server.release();
3719
3784
  }
3720
3785
  }
3721
3786
  async deleteProviderSessionIfEphemeral() {
@@ -3778,23 +3843,18 @@ class OpenCodeAgentSession {
3778
3843
  return { providerID: "opencode", modelID: model };
3779
3844
  }
3780
3845
  async ensureMcpServersConfigured() {
3781
- if (this.mcpConfigured) {
3782
- return;
3783
- }
3784
3846
  const mcpServers = this.config.mcpServers;
3785
3847
  if (!mcpServers || Object.keys(mcpServers).length === 0) {
3786
- this.mcpConfigured = true;
3787
3848
  return;
3788
3849
  }
3789
- if (!this.mcpSetupPromise) {
3790
- this.mcpSetupPromise = this.configureMcpServers(mcpServers);
3791
- }
3850
+ const setup = (this.mcpSetup ?? (this.mcpSetup = this.configureMcpServers(mcpServers)));
3792
3851
  try {
3793
- await this.mcpSetupPromise;
3794
- this.mcpConfigured = true;
3852
+ await setup;
3795
3853
  }
3796
3854
  catch (error) {
3797
- this.mcpSetupPromise = null;
3855
+ if (this.mcpSetup === setup) {
3856
+ this.mcpSetup = null;
3857
+ }
3798
3858
  throw error;
3799
3859
  }
3800
3860
  }
@@ -38,8 +38,7 @@ export declare class PiRpcAgentSession implements AgentSession {
38
38
  private readonly subscribers;
39
39
  private readonly activeToolCalls;
40
40
  private readonly pendingExtensionUiRequests;
41
- private activeAskUserDialog;
42
- private pendingCombinedAskUserResponse;
41
+ private readonly extensionHost;
43
42
  private activeTurnId;
44
43
  private activeClientMessageId;
45
44
  private activeAssistantMessageId;
@@ -52,8 +51,8 @@ export declare class PiRpcAgentSession implements AgentSession {
52
51
  private readonly pendingPromptResults;
53
52
  private readonly pendingSteerSubmissions;
54
53
  currentLeafOverrideId: string | null | undefined;
55
- private readonly capturedUserEntries;
56
- private readonly capturedUserEntriesById;
54
+ private readonly contextUserEntries;
55
+ private readonly treeUserEntriesById;
57
56
  private readonly pendingExtensionResults;
58
57
  private outOfBandCompactionEmit;
59
58
  private outOfBandCompactionStarted;
@@ -64,6 +63,8 @@ export declare class PiRpcAgentSession implements AgentSession {
64
63
  private readonly logger;
65
64
  private readonly usagePoller;
66
65
  private closed;
66
+ private readonly closeController;
67
+ private readonly pendingExtensionHydrations;
67
68
  private interruptingTurn;
68
69
  constructor(options: PiRpcAgentSessionOptions);
69
70
  private readonly runtimeSession;
@@ -100,6 +101,7 @@ export declare class PiRpcAgentSession implements AgentSession {
100
101
  setModel(modelId: string | null): Promise<void>;
101
102
  setThinkingOption(thinkingOptionId: string | null): Promise<void>;
102
103
  private emit;
104
+ private emitExtensionOutput;
103
105
  private currentTurnIdForEvent;
104
106
  private completeNoTurnPrompt;
105
107
  private completePromptIfHandledWithoutTurn;
@@ -119,7 +121,6 @@ export declare class PiRpcAgentSession implements AgentSession {
119
121
  private handleEntryCaptureMarker;
120
122
  private handleCommandResultMarker;
121
123
  private handleExtensionUiRequest;
122
- private respondToCombinedAskUserFollowUp;
123
124
  private handleCommandOutput;
124
125
  private handleRuntimeEvent;
125
126
  private handleProcessExit;
@@ -131,7 +132,6 @@ export declare class PiRpcAgentSession implements AgentSession {
131
132
  private handleMessageStart;
132
133
  private handleMessageEnd;
133
134
  private emitToolCallEvent;
134
- private mapToolDetail;
135
135
  private completeTurn;
136
136
  private refreshState;
137
137
  private refreshAfterTurn;