@getpaseo/server 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) 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/v2/session.js +30 -12
  10. package/dist/server/server/agent/providers/opencode-agent.js +24 -0
  11. package/dist/server/server/agent/tools/paseo-tools.js +6 -4
  12. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js} +1 -1
  13. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.br → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.br} +0 -0
  14. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-9da07adb97f5e0eb726f7762afee43f5.js.gz → desktop-attachment-bridge-9b9ae7a48611e7619ae3dcfc5573a81d.js.gz} +0 -0
  15. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js} +1 -1
  16. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-d5d3402a752965d3037191484127123b.js.br → desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.br} +0 -0
  17. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-850db74e505f3e0b8091b8a319bf6d95.js.gz +0 -0
  18. package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js → index-cefb3a051a5e61705f20366980a641f6.js} +463 -462
  19. package/dist/server/web-ui/_expo/static/js/web/index-cefb3a051a5e61705f20366980a641f6.js.br +0 -0
  20. package/dist/server/web-ui/_expo/static/js/web/{index-136fa41d4adb7ec5c6392839cc354136.js.gz → index-cefb3a051a5e61705f20366980a641f6.js.gz} +0 -0
  21. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js} +1 -1
  22. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.br → indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.br} +0 -0
  23. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-8233162f2e9e360c5680127250516411.js.gz +0 -0
  24. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js → native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js} +3 -3
  25. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.br +0 -0
  26. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-eb2d324071f66d94742cf09a46103e22.js.gz +0 -0
  27. package/dist/server/web-ui/index.html +1 -1
  28. package/dist/server/web-ui/index.html.br +0 -0
  29. package/dist/server/web-ui/index.html.gz +0 -0
  30. package/package.json +6 -6
  31. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-d5d3402a752965d3037191484127123b.js.gz +0 -0
  32. package/dist/server/web-ui/_expo/static/js/web/index-136fa41d4adb7ec5c6392839cc354136.js.br +0 -0
  33. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-3afc19e43c8152bd3c6d71b3ea8776dc.js.gz +0 -0
  34. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.br +0 -0
  35. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-187a9d5c32188f357dbbf037a0f89073.js.gz +0 -0
@@ -1204,6 +1204,7 @@ export class AgentManager {
1204
1204
  if (agent.runtimeInfo) {
1205
1205
  agent.runtimeInfo = { ...agent.runtimeInfo, model: normalizedModelId };
1206
1206
  }
1207
+ this.refreshSessionPersistence(agent);
1207
1208
  this.touchUpdatedAt(agent);
1208
1209
  this.emitState(agent);
1209
1210
  }
@@ -262,6 +262,8 @@ function wrapClientProvider(provider, inner, profileModels, additionalModels, pr
262
262
  const listImportableSessions = inner.listImportableSessions?.bind(inner);
263
263
  const importSession = inner.importSession?.bind(inner);
264
264
  const listFeatures = inner.listFeatures?.bind(inner);
265
+ const archiveNativeSession = inner.archiveNativeSession?.bind(inner);
266
+ const unarchiveNativeSession = inner.unarchiveNativeSession?.bind(inner);
265
267
  return {
266
268
  provider,
267
269
  capabilities: inner.capabilities,
@@ -332,6 +334,12 @@ function wrapClientProvider(provider, inner, profileModels, additionalModels, pr
332
334
  };
333
335
  }
334
336
  : undefined,
337
+ archiveNativeSession: archiveNativeSession
338
+ ? async (handle) => await archiveNativeSession({ ...handle, provider: inner.provider })
339
+ : undefined,
340
+ unarchiveNativeSession: unarchiveNativeSession
341
+ ? async (handle) => await unarchiveNativeSession({ ...handle, provider: inner.provider })
342
+ : undefined,
335
343
  getCatalogCacheKey: inner.getCatalogCacheKey?.bind(inner),
336
344
  isAvailable: (signal, options) => inner.isAvailable(signal, options),
337
345
  getDiagnostic: inner.getDiagnostic?.bind(inner),
@@ -53,10 +53,18 @@ export declare const CLAUDE_MODEL_MANIFEST: readonly [{
53
53
  readonly effortLevels: readonly ["low", "medium", "high", "xhigh", "max"];
54
54
  readonly supportsThinkingDisabled: true;
55
55
  readonly supportsFastMode: true;
56
+ }, {
57
+ readonly id: "claude-sonnet-5-5";
58
+ readonly label: "Sonnet 5.5";
59
+ readonly description: "Sonnet 5.5 · Best for everyday tasks";
60
+ readonly minimumClaudeCodeVersion: "2.1.284";
61
+ readonly defaultThinkingOptionId: "medium";
62
+ readonly contextWindowMaxTokens: 1000000;
63
+ readonly effortLevels: readonly ["low", "medium", "high", "xhigh", "max"];
56
64
  }, {
57
65
  readonly id: "claude-sonnet-5";
58
66
  readonly label: "Sonnet 5";
59
- readonly description: "Sonnet 5 · Best for everyday tasks";
67
+ readonly description: "Sonnet 5 · Previous release";
60
68
  readonly contextWindowMaxTokens: 200000;
61
69
  readonly effortLevels: readonly ["low", "medium", "high", "xhigh", "max"];
62
70
  readonly supportsThinkingDisabled: true;
@@ -71,10 +71,19 @@ export const CLAUDE_MODEL_MANIFEST = [
71
71
  supportsThinkingDisabled: true,
72
72
  supportsFastMode: true,
73
73
  },
74
+ {
75
+ id: "claude-sonnet-5-5",
76
+ label: "Sonnet 5.5",
77
+ description: "Sonnet 5.5 · Best for everyday tasks",
78
+ minimumClaudeCodeVersion: "2.1.284",
79
+ defaultThinkingOptionId: "medium",
80
+ contextWindowMaxTokens: 1000000,
81
+ effortLevels: CLAUDE_EFFORT_LEVELS.xhigh,
82
+ },
74
83
  {
75
84
  id: "claude-sonnet-5",
76
85
  label: "Sonnet 5",
77
- description: "Sonnet 5 · Best for everyday tasks",
86
+ description: "Sonnet 5 · Previous release",
78
87
  contextWindowMaxTokens: 200000,
79
88
  effortLevels: CLAUDE_EFFORT_LEVELS.xhigh,
80
89
  supportsThinkingDisabled: true,
@@ -18,6 +18,7 @@ export declare function revertCodexConversation(input: {
18
18
  cwd?: string | null;
19
19
  model?: string | null;
20
20
  serviceTier?: string | null;
21
+ config?: Record<string, unknown> | null;
21
22
  userMessageTurns: CodexUserMessageTurnIndex;
22
23
  setThreadId: (threadId: string) => void | Promise<void>;
23
24
  }): Promise<void>;
@@ -38,33 +38,32 @@ export async function revertCodexConversation(input) {
38
38
  if (numTurns < 0) {
39
39
  throw new Error(`Codex user message ${input.messageId} is outside the current thread`);
40
40
  }
41
+ // Codex does not carry the parent thread's config into a fork; without it the
42
+ // forked thread falls back to the default model provider.
43
+ const forkParams = {
44
+ threadId: input.threadId,
45
+ cwd: input.cwd ?? null,
46
+ model: input.model ?? null,
47
+ serviceTier: input.serviceTier ?? null,
48
+ ...(input.config ? { config: input.config } : {}),
49
+ excludeTurns: false,
50
+ persistExtendedHistory: true,
51
+ };
41
52
  const historyMode = await readCodexThreadHistoryMode(input.client, input.threadId);
42
53
  if (historyMode === "paginated") {
43
54
  if (!targetTurn.turnId) {
44
55
  throw new Error(`Codex could not find the turn containing user message ${input.messageId}`);
45
56
  }
46
57
  const forked = await forkCodexThread(input.client, {
47
- threadId: input.threadId,
58
+ ...forkParams,
48
59
  beforeTurnId: targetTurn.turnId,
49
- cwd: input.cwd ?? null,
50
- model: input.model ?? null,
51
- serviceTier: input.serviceTier ?? null,
52
- excludeTurns: false,
53
- persistExtendedHistory: true,
54
60
  });
55
61
  await input.setThreadId(forked.thread.id);
56
62
  return;
57
63
  }
58
64
  // Fork is non-destructive: the old thread file stays on disk and remains
59
65
  // recoverable with `codex resume <old-uuid>` if the rewind target was wrong.
60
- const forked = await forkCodexThread(input.client, {
61
- threadId: input.threadId,
62
- cwd: input.cwd ?? null,
63
- model: input.model ?? null,
64
- serviceTier: input.serviceTier ?? null,
65
- excludeTurns: false,
66
- persistExtendedHistory: true,
67
- });
66
+ const forked = await forkCodexThread(input.client, forkParams);
68
67
  const forkedThreadId = forked.thread.id;
69
68
  // Codex rollback is chat-only by design. File edits from rewound turns stay
70
69
  // on disk; a future file primitive would be a separate capability.
@@ -21,6 +21,7 @@ interface CodexAppServerAgentDeps {
21
21
  extends: string;
22
22
  };
23
23
  customCodexConfig?: CodexCustomProviderConfig | null;
24
+ codexHome?: string;
24
25
  _createCodexClient?: (child: ChildProcessWithoutNullStreams, logger: Logger, getTraceContext: () => CodexAppServerTraceContext) => CodexAppServerClientLike;
25
26
  resolveSlashCommandInvocation?: (prompt: AgentPromptInput) => Promise<{
26
27
  commandName: string;
@@ -31,7 +32,7 @@ export declare function normalizeCodexOutputSchema(schema: unknown): Record<stri
31
32
  export declare function codexMicrosoftStoreBinaryCandidates(packageRoot: string, entries: Dirent[]): string[];
32
33
  export declare function findCodexMicrosoftStoreBinary(): Promise<string | null>;
33
34
  export declare function findDefaultCodexBinary(): Promise<string | null>;
34
- export declare function listCodexSkills(cwd: string, workspaceGitService?: Pick<WorkspaceGitService, "resolveRepoRoot">): Promise<AgentSlashCommand[]>;
35
+ export declare function listCodexSkills(cwd: string, codexHome: string, workspaceGitService?: Pick<WorkspaceGitService, "resolveRepoRoot">): Promise<AgentSlashCommand[]>;
35
36
  export declare function toAgentUsage(tokenUsage: unknown): AgentUsage | undefined;
36
37
  export declare function planStepsToMarkdown(steps: Array<{
37
38
  step: string;
@@ -126,6 +127,7 @@ export declare class CodexAppServerAgentSession implements AgentSession {
126
127
  private readonly logger;
127
128
  private readonly config;
128
129
  private readonly asyncQuestions;
130
+ private readonly codexHome;
129
131
  private currentMode;
130
132
  private hasWorkflowModeOverride;
131
133
  private readonly providerOptions;
@@ -321,8 +321,8 @@ async function checkCodexLaunchAvailable(launch) {
321
321
  resolvePath: findDefaultCodexBinary,
322
322
  });
323
323
  }
324
- function resolveCodexHomeDir() {
325
- return process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
324
+ function resolveCodexHomeDir(env) {
325
+ return env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
326
326
  }
327
327
  function decodeEscapedChar(next) {
328
328
  if (next === "n")
@@ -423,8 +423,7 @@ function parseFrontMatter(markdown) {
423
423
  }
424
424
  return { frontMatter, body };
425
425
  }
426
- async function listCodexCustomPrompts() {
427
- const codexHome = resolveCodexHomeDir();
426
+ async function listCodexCustomPrompts(codexHome) {
428
427
  const promptsDir = path.join(codexHome, "prompts");
429
428
  let entries;
430
429
  try {
@@ -457,7 +456,7 @@ async function listCodexCustomPrompts() {
457
456
  const commands = parsedCommands.filter((cmd) => cmd !== null);
458
457
  return commands.sort((a, b) => a.name.localeCompare(b.name));
459
458
  }
460
- export async function listCodexSkills(cwd, workspaceGitService) {
459
+ export async function listCodexSkills(cwd, codexHome, workspaceGitService) {
461
460
  const candidates = [];
462
461
  candidates.push(path.join(cwd, ".codex", "skills"));
463
462
  const repoRoot = workspaceGitService
@@ -467,7 +466,7 @@ export async function listCodexSkills(cwd, workspaceGitService) {
467
466
  candidates.push(path.join(path.dirname(cwd), ".codex", "skills"));
468
467
  candidates.push(path.join(repoRoot, ".codex", "skills"));
469
468
  }
470
- candidates.push(path.join(resolveCodexHomeDir(), "skills"));
469
+ candidates.push(path.join(codexHome, "skills"));
471
470
  const candidateReads = await Promise.all(candidates.map(async (dir) => {
472
471
  let entries;
473
472
  try {
@@ -2532,6 +2531,7 @@ export class CodexAppServerAgentSession {
2532
2531
  this.providerOptions = CodexProviderOptionsSchema.parse(config.providerOptions ?? {});
2533
2532
  this.config = config;
2534
2533
  this.asyncQuestions = new CodexAsyncQuestions(resumeHandle?.metadata?.asyncQuestions);
2534
+ this.codexHome = deps.codexHome ?? resolveCodexHomeDir(process.env);
2535
2535
  this.config.thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
2536
2536
  if (this.config.featureValues?.fast_mode && codexModelSupportsFastMode(this.config.model)) {
2537
2537
  this.serviceTier = "fast";
@@ -3023,8 +3023,7 @@ export class CodexAppServerAgentSession {
3023
3023
  async buildCommandPromptInput(commandName, args) {
3024
3024
  if (commandName.startsWith("prompts:")) {
3025
3025
  const promptName = commandName.slice("prompts:".length);
3026
- const codexHome = resolveCodexHomeDir();
3027
- const promptPath = path.join(codexHome, "prompts", `${promptName}.md`);
3026
+ const promptPath = path.join(this.codexHome, "prompts", `${promptName}.md`);
3028
3027
  const raw = await fs.readFile(promptPath, "utf8");
3029
3028
  const parsed = parseFrontMatter(raw);
3030
3029
  return expandCodexCustomPrompt(parsed.body, args);
@@ -3688,6 +3687,7 @@ export class CodexAppServerAgentSession {
3688
3687
  cwd: this.config.cwd ?? null,
3689
3688
  model: this.config.model ?? null,
3690
3689
  serviceTier: this.serviceTier,
3690
+ config: this.buildCodexInnerConfig(),
3691
3691
  userMessageTurns: this.codexUserMessageTurns(),
3692
3692
  setThreadId: async (threadId) => {
3693
3693
  this.currentThreadId = threadId;
@@ -3783,7 +3783,7 @@ export class CodexAppServerAgentSession {
3783
3783
  this.client = null;
3784
3784
  }
3785
3785
  async listCommands() {
3786
- const prompts = await listCodexCustomPrompts();
3786
+ const prompts = await listCodexCustomPrompts(this.codexHome);
3787
3787
  if (this.connectionState === "disconnected") {
3788
3788
  await this.connect();
3789
3789
  }
@@ -3797,7 +3797,7 @@ export class CodexAppServerAgentSession {
3797
3797
  kind: "skill",
3798
3798
  }));
3799
3799
  const fallbackSkills = this.cachedSkills === null
3800
- ? await listCodexSkills(this.config.cwd, this.deps.workspaceGitService)
3800
+ ? await listCodexSkills(this.config.cwd, this.codexHome, this.deps.workspaceGitService)
3801
3801
  : [];
3802
3802
  const builtin = [
3803
3803
  {
@@ -5602,9 +5602,10 @@ export class CodexAppServerAgentClient {
5602
5602
  this.goalsEnabledPromise = null;
5603
5603
  this.autoReviewEnabledPromise = null;
5604
5604
  }
5605
- sessionDeps() {
5605
+ sessionDeps(launchEnv) {
5606
5606
  return {
5607
5607
  ...this.deps,
5608
+ codexHome: resolveCodexHomeDir(buildCodexAppServerEnv(this.runtimeSettings, launchEnv)),
5608
5609
  customCodexConfig: this.customProviderConfig(),
5609
5610
  };
5610
5611
  }
@@ -5690,7 +5691,7 @@ export class CodexAppServerAgentClient {
5690
5691
  const sessionConfig = { ...config, provider: CODEX_PROVIDER };
5691
5692
  const goalsEnabled = await this.resolveGoalsEnabled();
5692
5693
  const autoReviewEnabled = await this.resolveAutoReviewEnabled();
5693
- const session = new CodexAppServerAgentSession(sessionConfig, null, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(), options?.persistSession === false, goalsEnabled, autoReviewEnabled, launchContext?.agentId);
5694
+ const session = new CodexAppServerAgentSession(sessionConfig, null, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(launchContext?.env), options?.persistSession === false, goalsEnabled, autoReviewEnabled, launchContext?.agentId);
5694
5695
  await session.connect();
5695
5696
  return session;
5696
5697
  }
@@ -5704,7 +5705,7 @@ export class CodexAppServerAgentClient {
5704
5705
  };
5705
5706
  const goalsEnabled = await this.resolveGoalsEnabled();
5706
5707
  const autoReviewEnabled = await this.resolveAutoReviewEnabled();
5707
- const session = new CodexAppServerAgentSession(merged, handle, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(), false, goalsEnabled, autoReviewEnabled, launchContext?.agentId, options?.purpose ?? "interactive");
5708
+ const session = new CodexAppServerAgentSession(merged, handle, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(launchContext?.env), false, goalsEnabled, autoReviewEnabled, launchContext?.agentId, options?.purpose ?? "interactive");
5708
5709
  await session.connect();
5709
5710
  return session;
5710
5711
  }
@@ -239,24 +239,42 @@ export class OpenCodeV2Session {
239
239
  }
240
240
  async setModel(model) {
241
241
  await this.reconnectIfExited();
242
- const selected = model
243
- ? modelRef(model, this.config.thinkingOptionId)
244
- : (await this.client.model.default({ location: { directory: this.config.cwd } })).data;
242
+ const location = { directory: this.config.cwd };
243
+ const selected = model ? modelRef(model) : (await this.client.model.default({ location })).data;
245
244
  if (!selected)
246
245
  throw new Error("OpenCode has no default model");
247
- await this.client.session.switchModel({
248
- sessionID: this.id,
249
- model: {
250
- id: selected.id,
251
- providerID: selected.providerID,
252
- variant: this.config.thinkingOptionId,
253
- },
254
- });
246
+ const catalog = await this.client.model.list({ location });
247
+ const target = catalog.data.find((entry) => entry.enabled && entry.providerID === selected.providerID && entry.id === selected.id);
248
+ if (!target)
249
+ throw new Error(`OpenCode model unavailable: ${selected.providerID}/${selected.id}`);
250
+ const retainedVariant = this.config.thinkingOptionId;
251
+ const variant = retainedVariant !== "default" && target.variants.some((entry) => entry.id === retainedVariant)
252
+ ? retainedVariant
253
+ : undefined;
254
+ const nextModel = {
255
+ id: selected.id,
256
+ providerID: selected.providerID,
257
+ ...(variant ? { variant } : {}),
258
+ };
259
+ await this.client.session.switchModel({ sessionID: this.id, model: nextModel });
260
+ this.info.model = nextModel;
255
261
  this.config.model = model ?? undefined;
262
+ this.config.thinkingOptionId = variant;
263
+ this.emit({
264
+ type: "thinking_option_changed",
265
+ provider: "opencode",
266
+ thinkingOptionId: variant ?? null,
267
+ });
256
268
  this.emit({
257
269
  type: "model_changed",
258
270
  provider: "opencode",
259
- runtimeInfo: await this.getRuntimeInfo(),
271
+ runtimeInfo: {
272
+ provider: "opencode",
273
+ sessionId: this.id,
274
+ model: `${selected.providerID}/${selected.id}`,
275
+ modeId: this.info.agent ?? null,
276
+ thinkingOptionId: variant ?? null,
277
+ },
260
278
  });
261
279
  }
262
280
  async setThinkingOption(variant) {
@@ -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]);