@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.
Files changed (43) hide show
  1. package/dist/server/server/agent/agent-manager.js +1 -0
  2. package/dist/server/server/agent/provider-registry.js +8 -0
  3. package/dist/server/server/agent/providers/claude/model-manifest.d.ts +9 -1
  4. package/dist/server/server/agent/providers/claude/model-manifest.js +10 -1
  5. package/dist/server/server/agent/providers/codex/rewind.d.ts +1 -0
  6. package/dist/server/server/agent/providers/codex/rewind.js +13 -14
  7. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +3 -1
  8. package/dist/server/server/agent/providers/codex-app-server-agent.js +14 -13
  9. package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +16 -6
  10. package/dist/server/server/agent/providers/opencode/v2/api.d.ts +1 -1
  11. package/dist/server/server/agent/providers/opencode/v2/permissions.js +3 -2
  12. package/dist/server/server/agent/providers/opencode/v2/session.d.ts +2 -1
  13. package/dist/server/server/agent/providers/opencode/v2/session.js +43 -20
  14. package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +20 -5
  15. package/dist/server/server/agent/providers/opencode/v2/turns.js +168 -72
  16. package/dist/server/server/agent/providers/opencode/v2/usage.d.ts +21 -0
  17. package/dist/server/server/agent/providers/opencode/v2/usage.js +48 -0
  18. package/dist/server/server/agent/providers/opencode-agent.js +24 -0
  19. package/dist/server/server/agent/tools/paseo-tools.js +6 -4
  20. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js} +1 -1
  21. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.br} +0 -0
  22. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.gz} +0 -0
  23. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js} +1 -1
  24. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.br} +0 -0
  25. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.gz +0 -0
  26. package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js → index-48b52108bb348a6334547c3c03400d50.js} +463 -462
  27. package/dist/server/web-ui/_expo/static/js/web/index-48b52108bb348a6334547c3c03400d50.js.br +0 -0
  28. package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js.gz → index-48b52108bb348a6334547c3c03400d50.js.gz} +0 -0
  29. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js} +1 -1
  30. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.br} +0 -0
  31. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.gz +0 -0
  32. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js → native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js} +3 -3
  33. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.br +0 -0
  34. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.gz +0 -0
  35. package/dist/server/web-ui/index.html +1 -1
  36. package/dist/server/web-ui/index.html.br +0 -0
  37. package/dist/server/web-ui/index.html.gz +0 -0
  38. package/package.json +6 -6
  39. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  40. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.br +0 -0
  41. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  42. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  43. 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.executionError = null;
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
- if (turn)
25
- this.options.emit({
26
- type: "turn_failed",
27
- provider: "opencode",
28
- turnId: turn.id,
29
- error: error.message,
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 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 });
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
- accept();
57
- await this.finish(id);
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?.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
- }
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
- 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")
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 (info.outcome === "failed")
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: failure ?? "OpenCode execution failed",
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 readExecutionError() {
143
- let message = "OpenCode execution failed";
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.type === "session.execution.failed")
148
- message = event.data.error.message;
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 message;
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
- 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 });
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 immediately if background=true
1457
- // Re-fetch snapshot since the state may have changed
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])},5083,[4432,4433]);
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]);
@@ -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}'.`)}},5082,[4426]);
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]);