@getpaseo/server 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/server/agent/agent-manager.js +1 -0
- package/dist/server/server/agent/provider-registry.js +8 -0
- package/dist/server/server/agent/providers/claude/model-manifest.d.ts +9 -1
- package/dist/server/server/agent/providers/claude/model-manifest.js +10 -1
- package/dist/server/server/agent/providers/codex/rewind.d.ts +1 -0
- package/dist/server/server/agent/providers/codex/rewind.js +13 -14
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +3 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.js +14 -13
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +16 -6
- package/dist/server/server/agent/providers/opencode/v2/api.d.ts +1 -1
- package/dist/server/server/agent/providers/opencode/v2/permissions.js +3 -2
- package/dist/server/server/agent/providers/opencode/v2/session.d.ts +2 -1
- package/dist/server/server/agent/providers/opencode/v2/session.js +43 -20
- package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +20 -5
- package/dist/server/server/agent/providers/opencode/v2/turns.js +168 -72
- package/dist/server/server/agent/providers/opencode/v2/usage.d.ts +21 -0
- package/dist/server/server/agent/providers/opencode/v2/usage.js +48 -0
- package/dist/server/server/agent/providers/opencode-agent.js +24 -0
- package/dist/server/server/agent/tools/paseo-tools.js +6 -4
- package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js} +1 -1
- package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.br} +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.gz} +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js} +1 -1
- package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.br} +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js → index-48b52108bb348a6334547c3c03400d50.js} +463 -462
- package/dist/server/web-ui/_expo/static/js/web/index-48b52108bb348a6334547c3c03400d50.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js.gz → index-48b52108bb348a6334547c3c03400d50.js.gz} +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js} +1 -1
- package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.br} +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js → native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js} +3 -3
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.gz +0 -0
- package/dist/server/web-ui/index.html +1 -1
- package/dist/server/web-ui/index.html.br +0 -0
- package/dist/server/web-ui/index.html.gz +0 -0
- package/package.json +6 -6
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
|
@@ -4,13 +4,24 @@ import { toDiagnosticErrorMessage } from "../../diagnostic-utils.js";
|
|
|
4
4
|
import { renderPromptAttachmentAsText } from "../../../prompt-attachments.js";
|
|
5
5
|
import { usageFromV2 } from "./mapping.js";
|
|
6
6
|
import { commands } from "./commands.js";
|
|
7
|
+
function isExecutionEvent(event) {
|
|
8
|
+
return (event.type === "session.execution.started" ||
|
|
9
|
+
event.type === "session.execution.succeeded" ||
|
|
10
|
+
event.type === "session.execution.failed" ||
|
|
11
|
+
event.type === "session.execution.interrupted");
|
|
12
|
+
}
|
|
7
13
|
export class SessionTurns {
|
|
8
14
|
constructor(options) {
|
|
9
15
|
this.options = options;
|
|
10
16
|
this.turn = null;
|
|
11
17
|
this.stopping = null;
|
|
12
18
|
this.stopFailed = false;
|
|
13
|
-
this.
|
|
19
|
+
this.revision = 0;
|
|
20
|
+
this.execution = null;
|
|
21
|
+
this.sequence = 0;
|
|
22
|
+
this.refresh = null;
|
|
23
|
+
this.dirty = false;
|
|
24
|
+
this.retryTimer = null;
|
|
14
25
|
}
|
|
15
26
|
get id() {
|
|
16
27
|
return this.turn?.id;
|
|
@@ -20,14 +31,47 @@ export class SessionTurns {
|
|
|
20
31
|
}
|
|
21
32
|
fail(error) {
|
|
22
33
|
const turn = this.turn;
|
|
34
|
+
if (!turn)
|
|
35
|
+
return;
|
|
36
|
+
this.release(turn);
|
|
37
|
+
this.options.emit({
|
|
38
|
+
type: "turn_failed",
|
|
39
|
+
provider: "opencode",
|
|
40
|
+
turnId: turn.id,
|
|
41
|
+
error: toDiagnosticErrorMessage(error),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
release(turn) {
|
|
23
45
|
this.turn = null;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
this.revision += 1;
|
|
47
|
+
if (this.retryTimer)
|
|
48
|
+
clearTimeout(this.retryTimer);
|
|
49
|
+
this.retryTimer = null;
|
|
50
|
+
turn.settle();
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
if (this.turn)
|
|
54
|
+
this.release(this.turn);
|
|
55
|
+
}
|
|
56
|
+
createTurn(submitted, accepted, output) {
|
|
57
|
+
let settle;
|
|
58
|
+
const completion = new Promise((resolve) => {
|
|
59
|
+
settle = resolve;
|
|
60
|
+
});
|
|
61
|
+
const turn = {
|
|
62
|
+
id: randomUUID(),
|
|
63
|
+
submitted,
|
|
64
|
+
completion,
|
|
65
|
+
settle,
|
|
66
|
+
accepted,
|
|
67
|
+
output,
|
|
68
|
+
};
|
|
69
|
+
this.turn = turn;
|
|
70
|
+
this.execution = null;
|
|
71
|
+
this.revision += 1;
|
|
72
|
+
this.options.emit({ type: "turn_started", provider: "opencode", turnId: turn.id });
|
|
73
|
+
this.scheduleRecovery();
|
|
74
|
+
return turn;
|
|
31
75
|
}
|
|
32
76
|
async startTurn(prompt, options) {
|
|
33
77
|
await this.stopping;
|
|
@@ -35,42 +79,117 @@ export class SessionTurns {
|
|
|
35
79
|
throw new Error("OpenCode session is closed");
|
|
36
80
|
if (this.turn)
|
|
37
81
|
throw new Error("OpenCode session already has an active turn");
|
|
38
|
-
this.executionError = null;
|
|
39
|
-
const id = randomUUID();
|
|
40
82
|
const input = this.promptInput(prompt);
|
|
41
83
|
let accept;
|
|
42
84
|
const submitted = new Promise((resolve) => {
|
|
43
85
|
accept = resolve;
|
|
44
86
|
});
|
|
45
87
|
const output = options?.outputSchema === undefined ? undefined : structuredOutput(options.outputSchema);
|
|
46
|
-
const
|
|
47
|
-
this.turn
|
|
48
|
-
return { turnId: id };
|
|
49
|
-
}
|
|
50
|
-
async submit(
|
|
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 });
|
|
88
|
+
const turn = this.createTurn(submitted, false, output);
|
|
89
|
+
void this.submit(turn, input, accept, options);
|
|
90
|
+
return { turnId: turn.id };
|
|
91
|
+
}
|
|
92
|
+
async submit(turn, input, accept, options) {
|
|
54
93
|
try {
|
|
55
|
-
await this.dispatch(input, options, output);
|
|
56
|
-
|
|
57
|
-
|
|
94
|
+
await this.dispatch(input, options, turn.output);
|
|
95
|
+
if (this.turn !== turn)
|
|
96
|
+
return;
|
|
97
|
+
turn.accepted = true;
|
|
98
|
+
this.revision += 1;
|
|
99
|
+
// Covers a fast execution whose terminal event preceded the admission response.
|
|
100
|
+
this.requestReconciliation();
|
|
58
101
|
}
|
|
59
102
|
catch (error) {
|
|
60
|
-
if (this.turn
|
|
61
|
-
this.
|
|
62
|
-
this.options.emit({
|
|
63
|
-
type: "turn_failed",
|
|
64
|
-
provider: "opencode",
|
|
65
|
-
turnId: id,
|
|
66
|
-
error: toDiagnosticErrorMessage(error),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
103
|
+
if (this.turn === turn)
|
|
104
|
+
this.fail(new Error(toDiagnosticErrorMessage(error)));
|
|
69
105
|
}
|
|
70
106
|
finally {
|
|
71
107
|
accept();
|
|
72
108
|
}
|
|
73
109
|
}
|
|
110
|
+
observe(event) {
|
|
111
|
+
if (!isExecutionEvent(event) || event.durable.seq <= this.sequence)
|
|
112
|
+
return;
|
|
113
|
+
this.revision += 1;
|
|
114
|
+
if (event.type === "session.execution.started")
|
|
115
|
+
this.observeActiveTurn();
|
|
116
|
+
this.execution = event;
|
|
117
|
+
this.sequence = event.durable.seq;
|
|
118
|
+
this.requestReconciliation();
|
|
119
|
+
}
|
|
120
|
+
requestReconciliation() {
|
|
121
|
+
void this.reconcile().catch((error) => this.options.reportReconciliationError(error));
|
|
122
|
+
}
|
|
123
|
+
// Recovery reads state; a quiet stream (including SSE comment heartbeats) is not a reason to reconnect.
|
|
124
|
+
scheduleRecovery() {
|
|
125
|
+
if (this.retryTimer || !this.turn || this.options.signal.aborted)
|
|
126
|
+
return;
|
|
127
|
+
this.retryTimer = setTimeout(() => {
|
|
128
|
+
this.retryTimer = null;
|
|
129
|
+
this.requestReconciliation();
|
|
130
|
+
}, 5000);
|
|
131
|
+
this.retryTimer.unref();
|
|
132
|
+
}
|
|
133
|
+
reconcile() {
|
|
134
|
+
this.dirty = true;
|
|
135
|
+
if (this.refresh)
|
|
136
|
+
return this.refresh;
|
|
137
|
+
this.refresh = Promise.resolve()
|
|
138
|
+
.then(() => this.drainReconciliation())
|
|
139
|
+
.finally(() => {
|
|
140
|
+
this.refresh = null;
|
|
141
|
+
this.scheduleRecovery();
|
|
142
|
+
});
|
|
143
|
+
return this.refresh;
|
|
144
|
+
}
|
|
145
|
+
async drainReconciliation() {
|
|
146
|
+
while (this.dirty && !this.options.signal.aborted) {
|
|
147
|
+
this.dirty = false;
|
|
148
|
+
await this.reconcileTurn();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async reconcileTurn() {
|
|
152
|
+
const revision = this.revision;
|
|
153
|
+
const turn = this.turn;
|
|
154
|
+
const active = await this.options.client().session.active({ signal: this.options.signal });
|
|
155
|
+
if (revision !== this.revision) {
|
|
156
|
+
this.dirty = true;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (active[this.options.id]) {
|
|
160
|
+
this.observeActiveTurn();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (!turn?.accepted)
|
|
164
|
+
return;
|
|
165
|
+
// Idle outcome survives shutdown, and /event has no replay. Recover the latest
|
|
166
|
+
// durable execution even when its start or terminal was lost across reconnect.
|
|
167
|
+
const execution = await this.readExecution();
|
|
168
|
+
if (revision !== this.revision) {
|
|
169
|
+
this.dirty = true;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (!execution)
|
|
173
|
+
return;
|
|
174
|
+
this.execution = execution;
|
|
175
|
+
this.sequence = execution.durable.seq;
|
|
176
|
+
if (execution.type === "session.execution.started" ||
|
|
177
|
+
(execution.type === "session.execution.interrupted" && execution.data.reason === "shutdown"))
|
|
178
|
+
return;
|
|
179
|
+
// Read the final history only after observing idle. Never turn an observation transport error into an execution failure.
|
|
180
|
+
const snapshot = await this.options.reconcile();
|
|
181
|
+
if (revision !== this.revision) {
|
|
182
|
+
this.dirty = true;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
this.finish(turn, snapshot, execution);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (this.turn === turn)
|
|
190
|
+
this.fail(new Error(toDiagnosticErrorMessage(error)));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
74
193
|
async dispatch(input, options, output) {
|
|
75
194
|
const command = input.text.match(/^\/([^\s]+)(?:\s+([\s\S]*))?$/);
|
|
76
195
|
if (command?.[1] === "compact" || command?.[1] === "summarize") {
|
|
@@ -104,50 +223,41 @@ export class SessionTurns {
|
|
|
104
223
|
},
|
|
105
224
|
});
|
|
106
225
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
.
|
|
110
|
-
|
|
111
|
-
|
|
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")
|
|
226
|
+
finish(turn, { info, history }, execution) {
|
|
227
|
+
if (execution.type === "session.execution.succeeded")
|
|
228
|
+
turn.output?.assert(history);
|
|
229
|
+
this.release(turn);
|
|
230
|
+
if (execution.type === "session.execution.interrupted")
|
|
121
231
|
this.options.emit({
|
|
122
232
|
type: "turn_canceled",
|
|
123
233
|
provider: "opencode",
|
|
124
|
-
turnId: id,
|
|
234
|
+
turnId: turn.id,
|
|
125
235
|
reason: "OpenCode interrupted execution",
|
|
126
236
|
});
|
|
127
|
-
else if (
|
|
237
|
+
else if (execution.type === "session.execution.failed")
|
|
128
238
|
this.options.emit({
|
|
129
239
|
type: "turn_failed",
|
|
130
240
|
provider: "opencode",
|
|
131
|
-
turnId: id,
|
|
132
|
-
error:
|
|
241
|
+
turnId: turn.id,
|
|
242
|
+
error: execution.data.error.message,
|
|
133
243
|
});
|
|
134
244
|
else
|
|
135
245
|
this.options.emit({
|
|
136
246
|
type: "turn_completed",
|
|
137
247
|
provider: "opencode",
|
|
138
|
-
turnId: id,
|
|
248
|
+
turnId: turn.id,
|
|
139
249
|
usage: usageFromV2(info),
|
|
140
250
|
});
|
|
141
251
|
}
|
|
142
|
-
async
|
|
143
|
-
let
|
|
252
|
+
async readExecution() {
|
|
253
|
+
let execution = this.execution;
|
|
144
254
|
for await (const event of this.options
|
|
145
255
|
.client()
|
|
146
|
-
.session.log({ sessionID: this.options.id, follow: false }, { signal: this.options.signal })) {
|
|
147
|
-
if (event.
|
|
148
|
-
|
|
256
|
+
.session.log({ sessionID: this.options.id, follow: false, after: this.sequence }, { signal: this.options.signal })) {
|
|
257
|
+
if (isExecutionEvent(event) && event.durable.seq > (execution?.durable.seq ?? this.sequence))
|
|
258
|
+
execution = event;
|
|
149
259
|
}
|
|
150
|
-
return
|
|
260
|
+
return execution;
|
|
151
261
|
}
|
|
152
262
|
promptInput(prompt) {
|
|
153
263
|
if (typeof prompt === "string")
|
|
@@ -187,6 +297,7 @@ export class SessionTurns {
|
|
|
187
297
|
// A stop sent before the queued prompt is accepted would interrupt an idle session.
|
|
188
298
|
await turn?.submitted;
|
|
189
299
|
await this.options.client().session.interrupt({ sessionID: this.options.id });
|
|
300
|
+
await this.reconcile();
|
|
190
301
|
await turn?.completion;
|
|
191
302
|
})();
|
|
192
303
|
this.stopping = stop;
|
|
@@ -203,24 +314,9 @@ export class SessionTurns {
|
|
|
203
314
|
await this.stopping;
|
|
204
315
|
}
|
|
205
316
|
observeActiveTurn() {
|
|
206
|
-
if (this.turn)
|
|
317
|
+
if (this.turn || this.options.signal.aborted)
|
|
207
318
|
return;
|
|
208
|
-
|
|
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 });
|
|
319
|
+
this.createTurn(Promise.resolve(), true);
|
|
224
320
|
}
|
|
225
321
|
}
|
|
226
322
|
//# sourceMappingURL=turns.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpenCodeEvent, SessionInfo } from "@opencode/client";
|
|
2
|
+
import type { AgentStreamEvent } from "../../../agent-sdk-types.js";
|
|
3
|
+
import type { V2Api } from "./api.js";
|
|
4
|
+
interface UsageOptions {
|
|
5
|
+
client(): V2Api;
|
|
6
|
+
cwd: string;
|
|
7
|
+
info(): SessionInfo;
|
|
8
|
+
emit(event: AgentStreamEvent): void;
|
|
9
|
+
reportError(error: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class SessionUsage {
|
|
12
|
+
private readonly options;
|
|
13
|
+
private readonly limits;
|
|
14
|
+
private reports;
|
|
15
|
+
constructor(options: UsageOptions);
|
|
16
|
+
observe(event: OpenCodeEvent): void;
|
|
17
|
+
private report;
|
|
18
|
+
private contextLimit;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { usageFromV2 } from "./mapping.js";
|
|
2
|
+
// A step is one model call, so its tokens are the context that call used.
|
|
3
|
+
function contextWindowUsedTokens(tokens) {
|
|
4
|
+
return tokens.input + tokens.output + tokens.reasoning + tokens.cache.read + tokens.cache.write;
|
|
5
|
+
}
|
|
6
|
+
export class SessionUsage {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.limits = new Map();
|
|
10
|
+
this.reports = Promise.resolve();
|
|
11
|
+
}
|
|
12
|
+
observe(event) {
|
|
13
|
+
if (event.type !== "session.step.ended")
|
|
14
|
+
return;
|
|
15
|
+
const { tokens } = event.data;
|
|
16
|
+
// Reports stay in step order while a model's context limit is still being looked up.
|
|
17
|
+
this.reports = this.reports
|
|
18
|
+
.then(() => this.report(tokens))
|
|
19
|
+
.catch((error) => this.options.reportError(error));
|
|
20
|
+
}
|
|
21
|
+
async report(tokens) {
|
|
22
|
+
const model = this.options.info().model;
|
|
23
|
+
const contextWindowMaxTokens = model ? await this.contextLimit(model) : undefined;
|
|
24
|
+
this.options.emit({
|
|
25
|
+
type: "usage_updated",
|
|
26
|
+
provider: "opencode",
|
|
27
|
+
usage: {
|
|
28
|
+
...usageFromV2(this.options.info()),
|
|
29
|
+
contextWindowUsedTokens: contextWindowUsedTokens(tokens),
|
|
30
|
+
...(contextWindowMaxTokens === undefined ? {} : { contextWindowMaxTokens }),
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
contextLimit(model) {
|
|
35
|
+
const key = `${model.providerID}/${model.id}`;
|
|
36
|
+
const cached = this.limits.get(key);
|
|
37
|
+
if (cached)
|
|
38
|
+
return cached;
|
|
39
|
+
const limit = this.options
|
|
40
|
+
.client()
|
|
41
|
+
.model.list({ location: { directory: this.options.cwd } })
|
|
42
|
+
.then((catalog) => catalog.data.find((entry) => entry.providerID === model.providerID && entry.id === model.id)?.limit.context);
|
|
43
|
+
this.limits.set(key, limit);
|
|
44
|
+
limit.catch(() => this.limits.delete(key));
|
|
45
|
+
return limit;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -2529,12 +2529,36 @@ class OpenCodeAgentSession {
|
|
|
2529
2529
|
sessionId: this.sessionId,
|
|
2530
2530
|
model: this.config.model ?? null,
|
|
2531
2531
|
modeId: this.currentMode,
|
|
2532
|
+
thinkingOptionId: this.config.thinkingOptionId ?? null,
|
|
2532
2533
|
};
|
|
2533
2534
|
}
|
|
2534
2535
|
async setModel(modelId) {
|
|
2536
|
+
await this.reconnectIfServerExited();
|
|
2535
2537
|
const normalizedModelId = typeof modelId === "string" && modelId.trim().length > 0 ? modelId : null;
|
|
2538
|
+
let variant = this.config.thinkingOptionId;
|
|
2539
|
+
if (!normalizedModelId) {
|
|
2540
|
+
variant = undefined;
|
|
2541
|
+
}
|
|
2542
|
+
else if (variant) {
|
|
2543
|
+
const model = this.parseModel(normalizedModelId);
|
|
2544
|
+
const response = await this.client.provider.list({ directory: this.config.cwd });
|
|
2545
|
+
if (response.error)
|
|
2546
|
+
throw new Error(`Failed to fetch OpenCode providers: ${JSON.stringify(response.error)}`);
|
|
2547
|
+
const provider = response.data?.all.find((entry) => entry.id === model?.providerID);
|
|
2548
|
+
const target = model && provider?.models[model.modelID];
|
|
2549
|
+
if (!target)
|
|
2550
|
+
throw new Error(`OpenCode model unavailable: ${normalizedModelId}`);
|
|
2551
|
+
if (!Object.hasOwn(target.variants ?? {}, variant))
|
|
2552
|
+
variant = undefined;
|
|
2553
|
+
}
|
|
2536
2554
|
this.config.model = normalizedModelId ?? undefined;
|
|
2555
|
+
this.config.thinkingOptionId = variant;
|
|
2537
2556
|
this.selectedModelContextWindowMaxTokens = this.resolveConfiguredModelContextWindowMaxTokens(this.config.model);
|
|
2557
|
+
this.notifySubscribers({
|
|
2558
|
+
type: "thinking_option_changed",
|
|
2559
|
+
provider: "opencode",
|
|
2560
|
+
thinkingOptionId: variant ?? null,
|
|
2561
|
+
});
|
|
2538
2562
|
}
|
|
2539
2563
|
async setThinkingOption(thinkingOptionId) {
|
|
2540
2564
|
const normalizedThinkingOptionId = normalizeOpenCodeVariantId(thinkingOptionId);
|
|
@@ -14,7 +14,7 @@ import { everyMsToFiveFieldCron } from "@getpaseo/protocol/schedule/cadence";
|
|
|
14
14
|
import { expandUserPath, isSameOrDescendantPath, resolvePathFromBase } from "../../path-utils.js";
|
|
15
15
|
import { ScheduleRunSchema, ScheduleSummarySchema, StoredScheduleSchema, } from "@getpaseo/protocol/schedule/types";
|
|
16
16
|
import { AgentModelSchema, AgentProviderEnum, AgentStatusEnum, ProviderModeSchema, ProviderSummarySchema, parseDurationString, resolveRequiredProviderModel, sanitizePermissionRequest, serializeSnapshotWithMetadata, toScheduleSummary, waitForAgentWithTimeout, } from "../mcp-shared.js";
|
|
17
|
-
import { sendPromptToAgent, setupFinishNotification } from "../agent-prompt.js";
|
|
17
|
+
import { sendPromptToAgent, setupFinishNotification, waitForAgentRunStartWithTimeout, } from "../agent-prompt.js";
|
|
18
18
|
import { respondToAgentPermission } from "../permission-response.js";
|
|
19
19
|
import { archiveAgentCommand, cancelAgentRunCommand, closeAgentCommand, setAgentModeCommand, updateAgentCommand, } from "../lifecycle-command.js";
|
|
20
20
|
import { resolveWorktreeSourceCwd } from "../../workspace-source.js";
|
|
@@ -1420,7 +1420,7 @@ export function createPaseoToolCatalog(options) {
|
|
|
1420
1420
|
});
|
|
1421
1421
|
return true;
|
|
1422
1422
|
}
|
|
1423
|
-
await sendPromptToAgent({
|
|
1423
|
+
const { disposition } = await sendPromptToAgent({
|
|
1424
1424
|
agentManager,
|
|
1425
1425
|
agentStorage,
|
|
1426
1426
|
agentId,
|
|
@@ -1453,8 +1453,10 @@ export function createPaseoToolCatalog(options) {
|
|
|
1453
1453
|
return response;
|
|
1454
1454
|
}
|
|
1455
1455
|
const notifying = armFinishNotification();
|
|
1456
|
-
// Return
|
|
1457
|
-
|
|
1456
|
+
// Return once the provider has accepted the turn, so the status reports it running.
|
|
1457
|
+
if (disposition === "turn_started") {
|
|
1458
|
+
await waitForAgentRunStartWithTimeout(agentManager, agentId);
|
|
1459
|
+
}
|
|
1458
1460
|
const currentSnapshot = agentManager.getAgent(agentId);
|
|
1459
1461
|
const responseData = {
|
|
1460
1462
|
success: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},
|
|
1
|
+
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},5084,[4432,4433]);
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},
|
|
1
|
+
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},5083,[4426]);
|
|
Binary file
|