@getpaseo/server 0.1.91-beta.1 → 0.1.91

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 (50) hide show
  1. package/dist/scripts/supervisor.js +21 -0
  2. package/dist/server/server/agent/agent-manager.d.ts +1 -1
  3. package/dist/server/server/agent/agent-manager.js +23 -48
  4. package/dist/server/server/agent/agent-sdk-types.d.ts +15 -0
  5. package/dist/server/server/agent/prompt-attachments.js +8 -0
  6. package/dist/server/server/agent/provider-registry.d.ts +0 -1
  7. package/dist/server/server/agent/provider-registry.js +22 -4
  8. package/dist/server/server/agent/provider-snapshot-manager.js +19 -1
  9. package/dist/server/server/agent/providers/claude/agent.d.ts +5 -2
  10. package/dist/server/server/agent/providers/claude/agent.js +6 -2
  11. package/dist/server/server/agent/providers/claude/models.d.ts +1 -1
  12. package/dist/server/server/agent/providers/claude/models.js +6 -6
  13. package/dist/server/server/agent/providers/codex-app-server-agent.js +9 -5
  14. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +1 -0
  15. package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +4 -0
  16. package/dist/server/server/agent/providers/opencode-agent.d.ts +16 -2
  17. package/dist/server/server/agent/providers/opencode-agent.js +75 -4
  18. package/dist/server/server/agent/providers/pi/agent.d.ts +23 -1
  19. package/dist/server/server/agent/providers/pi/agent.js +219 -13
  20. package/dist/server/server/agent/providers/pi/cli-runtime.js +9 -0
  21. package/dist/server/server/agent/providers/pi/rpc-types.d.ts +9 -0
  22. package/dist/server/server/agent/providers/pi/runtime.d.ts +2 -0
  23. package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +12 -0
  24. package/dist/server/server/agent/providers/pi/session-descriptor.js +304 -0
  25. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +8 -0
  26. package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +22 -0
  27. package/dist/server/server/agent/runtime-mcp-config.d.ts +8 -0
  28. package/dist/server/server/agent/runtime-mcp-config.js +50 -0
  29. package/dist/server/server/auth.js +16 -1
  30. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +2 -2
  31. package/dist/server/server/daemon-worker.js +84 -1
  32. package/dist/server/server/file-upload/index.d.ts +27 -0
  33. package/dist/server/server/file-upload/index.js +158 -0
  34. package/dist/server/server/loop-service.d.ts +12 -12
  35. package/dist/server/server/persisted-config.d.ts +11 -0
  36. package/dist/server/server/persisted-config.js +2 -1
  37. package/dist/server/server/persistence-hooks.js +6 -4
  38. package/dist/server/server/session.d.ts +5 -2
  39. package/dist/server/server/session.js +20 -2
  40. package/dist/server/server/speech/providers/local/runtime.js +1 -0
  41. package/dist/server/server/speech/providers/local/worker-client.d.ts +14 -1
  42. package/dist/server/server/speech/providers/local/worker-client.js +169 -7
  43. package/dist/server/server/websocket-server.d.ts +2 -0
  44. package/dist/server/server/websocket-server.js +20 -7
  45. package/dist/server/server/workspace-registry.d.ts +4 -4
  46. package/dist/server/utils/directory-suggestions.js +10 -5
  47. package/dist/server/utils/worktree.d.ts +4 -0
  48. package/dist/server/utils/worktree.js +19 -2
  49. package/dist/src/server/persisted-config.js +2 -1
  50. package/package.json +5 -5
@@ -127,6 +127,26 @@ export function runSupervisor(options) {
127
127
  execArgv: workerExecArgv,
128
128
  });
129
129
  }
130
+ const currentChild = child;
131
+ const heartbeat = setInterval(() => {
132
+ const message = { type: "paseo:supervisor-heartbeat" };
133
+ if (currentChild.connected) {
134
+ currentChild.send?.(message, (error) => {
135
+ if (error) {
136
+ writeLifecycleLog("Worker heartbeat IPC send failed", {
137
+ error: error instanceof Error ? error.message : String(error),
138
+ });
139
+ }
140
+ });
141
+ }
142
+ else {
143
+ writeLifecycleLog("Worker heartbeat skipped because IPC channel is disconnected");
144
+ }
145
+ }, 1000);
146
+ heartbeat.unref();
147
+ child.on("disconnect", () => {
148
+ writeLifecycleLog("Worker IPC channel disconnected");
149
+ });
130
150
  child.stdout?.on("data", (chunk) => {
131
151
  process.stdout.write(chunk);
132
152
  writeDurableChunk(chunk);
@@ -157,6 +177,7 @@ export function runSupervisor(options) {
157
177
  requestRestart("Restart requested by worker");
158
178
  });
159
179
  child.on("close", (code, signal) => {
180
+ clearInterval(heartbeat);
160
181
  const exitDescriptor = describeExit(code, signal);
161
182
  writeLifecycleLog("Worker exited", { code, signal, exit: exitDescriptor });
162
183
  if (shuttingDown) {
@@ -163,7 +163,6 @@ export interface AgentMetricsSnapshot {
163
163
  export declare class AgentManager {
164
164
  private readonly clients;
165
165
  private readonly providerEnabled;
166
- private readonly providerDerivedFromId;
167
166
  private readonly agents;
168
167
  private readonly timelineStore;
169
168
  private readonly agentsAwaitingInitialSnapshotPersist;
@@ -337,6 +336,7 @@ export declare class AgentManager {
337
336
  private dispatchStream;
338
337
  private dispatch;
339
338
  private normalizeConfig;
339
+ private prepareSessionConfig;
340
340
  private applyDaemonAppendSystemPrompt;
341
341
  private buildLaunchContext;
342
342
  private requireAvailableClient;
@@ -10,9 +10,9 @@ import { InMemoryAgentTimelineStore, } from "./agent-timeline-store.js";
10
10
  import { AGENT_STREAM_COALESCE_DEFAULT_WINDOW_MS, AgentStreamCoalescer, } from "./agent-stream-coalescer.js";
11
11
  import { ForegroundRunState } from "./foreground-run-state.js";
12
12
  import { getAgentProviderDefinition } from "@getpaseo/protocol/provider-manifest";
13
- import { IMPORTABLE_PROVIDERS } from "./provider-registry.js";
14
13
  import { invokeRewindCapability } from "./rewind/rewind.js";
15
14
  import { isSystemInjectedEnvelope } from "./agent-prompt.js";
15
+ import { stripInternalPaseoMcpServer, withRuntimePaseoMcpServer } from "./runtime-mcp-config.js";
16
16
  const RELOAD_SESSION_CLOSE_TIMEOUT_MS = 3000;
17
17
  const INTERRUPT_SESSION_TIMEOUT_MS = 2000;
18
18
  const STORED_AGENT_CAPABILITIES = {
@@ -54,7 +54,7 @@ function buildStoredAgentConfig(record) {
54
54
  }
55
55
  if (record.config.mcpServers != null)
56
56
  config.mcpServers = record.config.mcpServers;
57
- return config;
57
+ return stripInternalPaseoMcpServer(config);
58
58
  }
59
59
  export { AGENT_LIFECYCLE_STATUSES };
60
60
  function resolveInitialAttention(input) {
@@ -126,7 +126,6 @@ export class AgentManager {
126
126
  constructor(options) {
127
127
  this.clients = new Map();
128
128
  this.providerEnabled = new Map();
129
- this.providerDerivedFromId = new Map();
130
129
  this.agents = new Map();
131
130
  this.timelineStore = new InMemoryAgentTimelineStore();
132
131
  this.agentsAwaitingInitialSnapshotPersist = new Set();
@@ -166,7 +165,6 @@ export class AgentManager {
166
165
  for (const [provider, definition] of Object.entries(input.providerDefinitions)) {
167
166
  if (definition) {
168
167
  this.providerEnabled.set(provider, definition.enabled);
169
- this.providerDerivedFromId.set(provider, definition.derivedFromProviderId ?? null);
170
168
  }
171
169
  }
172
170
  for (const [provider, client] of Object.entries(input.clients)) {
@@ -303,15 +301,9 @@ export class AgentManager {
303
301
  .slice(0, limit);
304
302
  }
305
303
  isProviderImportable(provider, providerFilter) {
306
- if (!IMPORTABLE_PROVIDERS.includes(provider)) {
307
- return false;
308
- }
309
304
  if (this.providerEnabled.get(provider) === false) {
310
305
  return false;
311
306
  }
312
- if (this.providerDerivedFromId.get(provider) != null) {
313
- return false;
314
- }
315
307
  if (providerFilter && !providerFilter.has(provider)) {
316
308
  return false;
317
309
  }
@@ -427,27 +419,15 @@ export class AgentManager {
427
419
  }
428
420
  async createAgent(config, agentId, options) {
429
421
  const resolvedAgentId = validateAgentId(agentId ?? this.idFactory(), "createAgent");
430
- const injectedConfig = this.mcpBaseUrl == null
431
- ? config
432
- : {
433
- ...config,
434
- mcpServers: {
435
- paseo: {
436
- type: "http",
437
- url: `${this.mcpBaseUrl}?callerAgentId=${resolvedAgentId}`,
438
- },
439
- ...config.mcpServers,
440
- },
441
- };
442
- this.requireEnabledProvider(injectedConfig.provider);
443
- const normalizedConfig = this.applyDaemonAppendSystemPrompt(await this.normalizeConfig(injectedConfig));
422
+ const { storedConfig, launchConfig } = await this.prepareSessionConfig(config, resolvedAgentId);
423
+ this.requireEnabledProvider(storedConfig.provider);
444
424
  const launchContext = this.buildLaunchContext(resolvedAgentId, options?.env);
445
425
  const client = await this.requireAvailableClient({
446
- provider: normalizedConfig.provider,
426
+ provider: storedConfig.provider,
447
427
  });
448
428
  const createOptions = this.buildCreateSessionOptions(options);
449
- const session = await client.createSession(normalizedConfig, launchContext, createOptions);
450
- return this.registerSession(session, normalizedConfig, resolvedAgentId, {
429
+ const session = await client.createSession(launchConfig, launchContext, createOptions);
430
+ return this.registerSession(session, storedConfig, resolvedAgentId, {
451
431
  labels: options?.labels,
452
432
  workspaceId: options?.workspaceId,
453
433
  initialTitle: options?.initialTitle,
@@ -468,29 +448,15 @@ export class AgentManager {
468
448
  ...overrides,
469
449
  provider: handle.provider,
470
450
  };
471
- const normalizedConfig = this.applyDaemonAppendSystemPrompt(await this.normalizeConfig(mergedConfig));
472
- const resumeOverrides = { ...overrides };
473
- let hasResumeOverrides = overrides !== undefined;
474
- if (normalizedConfig.model !== mergedConfig.model) {
475
- resumeOverrides.model = normalizedConfig.model;
476
- hasResumeOverrides = true;
477
- }
478
- if (normalizedConfig.modeId !== mergedConfig.modeId) {
479
- resumeOverrides.modeId = normalizedConfig.modeId;
480
- hasResumeOverrides = true;
481
- }
482
- if (metadata.daemonAppendSystemPrompt !== normalizedConfig.daemonAppendSystemPrompt) {
483
- resumeOverrides.daemonAppendSystemPrompt = normalizedConfig.daemonAppendSystemPrompt;
484
- hasResumeOverrides = true;
485
- }
451
+ const { storedConfig, launchConfig } = await this.prepareSessionConfig(mergedConfig, resolvedAgentId);
486
452
  const launchContext = this.buildLaunchContext(resolvedAgentId);
487
453
  const client = this.requireClient(handle.provider);
488
454
  const available = await client.isAvailable();
489
455
  if (!available) {
490
456
  throw new Error(`Provider '${handle.provider}' is not available. Please ensure the CLI is installed.`);
491
457
  }
492
- const session = await client.resumeSession(handle, hasResumeOverrides ? resumeOverrides : undefined, launchContext);
493
- return this.registerSession(session, normalizedConfig, resolvedAgentId, options);
458
+ const session = await client.resumeSession(handle, launchConfig, launchContext);
459
+ return this.registerSession(session, storedConfig, resolvedAgentId, options);
494
460
  }
495
461
  // Hot-reload an active agent session with config overrides. By default the
496
462
  // in-memory timeline is preserved (used for voice-mode toggles and similar
@@ -517,11 +483,11 @@ export class AgentManager {
517
483
  ...overrides,
518
484
  provider,
519
485
  };
520
- const normalizedConfig = this.applyDaemonAppendSystemPrompt(await this.normalizeConfig(refreshConfig));
486
+ const { storedConfig, launchConfig } = await this.prepareSessionConfig(refreshConfig, agentId);
521
487
  const launchContext = this.buildLaunchContext(agentId);
522
488
  const session = handle
523
- ? await client.resumeSession(handle, normalizedConfig, launchContext)
524
- : await client.createSession(normalizedConfig, launchContext);
489
+ ? await client.resumeSession(handle, launchConfig, launchContext)
490
+ : await client.createSession(launchConfig, launchContext);
525
491
  this.agentStreamCoalescer.flushAndDiscard(agentId);
526
492
  // Remove the existing agent entry before swapping sessions
527
493
  this.agents.delete(agentId);
@@ -539,7 +505,7 @@ export class AgentManager {
539
505
  this.timelineStore.delete(agentId);
540
506
  }
541
507
  // Preserve existing labels and timeline during reload.
542
- return this.registerSession(session, normalizedConfig, agentId, {
508
+ return this.registerSession(session, storedConfig, agentId, {
543
509
  labels: existing.labels,
544
510
  createdAt: existing.createdAt,
545
511
  updatedAt: existing.updatedAt,
@@ -2503,6 +2469,15 @@ export class AgentManager {
2503
2469
  }
2504
2470
  return normalized;
2505
2471
  }
2472
+ async prepareSessionConfig(config, agentId) {
2473
+ const storedConfig = await this.normalizeConfig(stripInternalPaseoMcpServer(config));
2474
+ const launchConfig = this.applyDaemonAppendSystemPrompt(withRuntimePaseoMcpServer({
2475
+ config: storedConfig,
2476
+ agentId,
2477
+ mcpBaseUrl: this.mcpBaseUrl,
2478
+ }));
2479
+ return { storedConfig, launchConfig };
2480
+ }
2506
2481
  applyDaemonAppendSystemPrompt(config) {
2507
2482
  const daemonAppendSystemPrompt = this.appendSystemPrompt.trim();
2508
2483
  const next = { ...config };
@@ -12,6 +12,11 @@ export interface McpStdioServerConfig {
12
12
  command: string;
13
13
  args?: string[];
14
14
  env?: Record<string, string>;
15
+ /**
16
+ * When true, all tools from this server are always included in the prompt
17
+ * and never deferred behind tool search. Honored by the Claude provider.
18
+ */
19
+ alwaysLoad?: boolean;
15
20
  }
16
21
  /**
17
22
  * HTTP-based MCP server.
@@ -20,6 +25,11 @@ export interface McpHttpServerConfig {
20
25
  type: "http";
21
26
  url: string;
22
27
  headers?: Record<string, string>;
28
+ /**
29
+ * When true, all tools from this server are always included in the prompt
30
+ * and never deferred behind tool search. Honored by the Claude provider.
31
+ */
32
+ alwaysLoad?: boolean;
23
33
  }
24
34
  /**
25
35
  * SSE-based MCP server (Server-Sent Events over HTTP).
@@ -28,6 +38,11 @@ export interface McpSseServerConfig {
28
38
  type: "sse";
29
39
  url: string;
30
40
  headers?: Record<string, string>;
41
+ /**
42
+ * When true, all tools from this server are always included in the prompt
43
+ * and never deferred behind tool search. Honored by the Claude provider.
44
+ */
45
+ alwaysLoad?: boolean;
31
46
  }
32
47
  /**
33
48
  * Canonical MCP server configuration.
@@ -45,6 +45,14 @@ export function renderPromptAttachmentAsText(attachment) {
45
45
  });
46
46
  return lines.join("\n");
47
47
  }
48
+ case "uploaded_file": {
49
+ return [
50
+ `Uploaded file: ${attachment.fileName}`,
51
+ `Path: ${attachment.path}`,
52
+ `MIME: ${attachment.mimeType}`,
53
+ `Size: ${attachment.size} bytes`,
54
+ ].join("\n");
55
+ }
48
56
  default:
49
57
  throw new Error("unreachable");
50
58
  }
@@ -19,7 +19,6 @@ export interface ProviderDefinition extends AgentProviderDefinition {
19
19
  fetchModels: (options: ListModelsOptions) => Promise<AgentModelDefinition[]>;
20
20
  fetchModes: (options: ListModesOptions) => Promise<AgentMode[]>;
21
21
  }
22
- export { IMPORTABLE_PROVIDERS } from "@getpaseo/protocol/importable-providers";
23
22
  export interface BuildProviderRegistryOptions {
24
23
  runtimeSettings?: AgentProviderRuntimeSettingsMap;
25
24
  providerOverrides?: Record<string, ProviderOverride>;
@@ -14,7 +14,6 @@ function isNonEmptyStringArray(value) {
14
14
  return value.length > 0;
15
15
  }
16
16
  export { AGENT_PROVIDER_DEFINITIONS, getAgentProviderDefinition };
17
- export { IMPORTABLE_PROVIDERS } from "@getpaseo/protocol/importable-providers";
18
17
  const PROVIDER_CLIENT_FACTORIES = {
19
18
  claude: (logger, runtimeSettings) => new ClaudeAgentClient({
20
19
  logger,
@@ -34,9 +33,22 @@ const PROVIDER_CLIENT_FACTORIES = {
34
33
  env: runtimeSettings?.env,
35
34
  }),
36
35
  opencode: (logger, runtimeSettings) => new OpenCodeAgentClient(logger, runtimeSettings),
37
- pi: (logger, runtimeSettings) => new PiRpcAgentClient({
36
+ pi: (logger, runtimeSettings, options) => new PiRpcAgentClient({
38
37
  logger,
39
38
  runtimeSettings,
39
+ providerParams: options?.providerParams,
40
+ }),
41
+ omp: (logger, runtimeSettings, options) => new PiRpcAgentClient({
42
+ logger,
43
+ runtimeSettings: mergeRuntimeSettings({
44
+ command: {
45
+ mode: "replace",
46
+ argv: ["omp"],
47
+ },
48
+ }, runtimeSettings),
49
+ providerParams: options?.providerParams ?? {
50
+ sessionDir: "~/.omp/agent/sessions",
51
+ },
40
52
  }),
41
53
  mock: (logger) => new MockLoadTestAgentClient(logger),
42
54
  "mock-slow": () => new MockSlowProviderClient(),
@@ -292,11 +304,13 @@ function buildResolvedBuiltinProviders(providerOverrides, runtimeSettings, optio
292
304
  runtimeSettings: mergedRuntimeSettings,
293
305
  profileModels: override?.models ?? [],
294
306
  additionalModels: override?.additionalModels ?? [],
295
- profileModelsAreAdditive: definition.id === "claude",
296
- enabled: override?.enabled !== false,
307
+ profileModelsAreAdditive: false,
308
+ enabled: override?.enabled ?? definition.enabledByDefault ?? true,
297
309
  derivedFromProviderId: null,
310
+ providerParams: override?.params,
298
311
  createBaseClient: (logger) => factory(logger, mergedRuntimeSettings, {
299
312
  workspaceGitService: options.workspaceGitService,
313
+ providerParams: override?.params,
300
314
  }),
301
315
  });
302
316
  }
@@ -330,6 +344,7 @@ function addDerivedProviders(resolvedProviders, providerOverrides) {
330
344
  profileModelsAreAdditive: false,
331
345
  enabled: override.enabled !== false,
332
346
  derivedFromProviderId: null,
347
+ providerParams: override.params,
333
348
  createBaseClient: (logger) => providerId === "cursor"
334
349
  ? new CursorACPAgentClient({
335
350
  logger,
@@ -356,6 +371,7 @@ function addDerivedProviders(resolvedProviders, providerOverrides) {
356
371
  const mergedRuntimeSettings = mergeRuntimeSettings(baseProvider.runtimeSettings, toRuntimeSettings(override));
357
372
  const baseDefinition = baseProvider.definition;
358
373
  const baseFactory = getProviderClientFactory(baseProviderId);
374
+ const providerParams = override.params ?? baseProvider.providerParams;
359
375
  resolvedProviders.set(providerId, {
360
376
  definition: createDerivedDefinition(providerId, baseDefinition, override),
361
377
  runtimeSettings: mergedRuntimeSettings,
@@ -364,7 +380,9 @@ function addDerivedProviders(resolvedProviders, providerOverrides) {
364
380
  profileModelsAreAdditive: false,
365
381
  enabled: override.enabled !== false,
366
382
  derivedFromProviderId: baseProviderId,
383
+ providerParams,
367
384
  createBaseClient: (logger) => baseFactory(logger, mergedRuntimeSettings, {
385
+ providerParams,
368
386
  customProvider: {
369
387
  id: providerId,
370
388
  label: override.label ?? providerId,
@@ -6,6 +6,24 @@ import { withTimeout } from "../../utils/promise-timeout.js";
6
6
  import { buildProviderRegistry, shutdownAgentClients, } from "./provider-registry.js";
7
7
  import { applyMutableProviderConfigToOverrides } from "../daemon-config-store.js";
8
8
  const DEFAULT_REFRESH_TIMEOUT_MS = 30000;
9
+ const REFRESH_TIMEOUT_ENV_VAR = "PASEO_PROVIDER_REFRESH_TIMEOUT_MS";
10
+ // Provider refresh probes can be slow on cold starts (e.g. Copilot's first
11
+ // `copilot --acp` invocation, OpenCode workspace probes with many MCP servers).
12
+ // Allow operators to bump the ceiling via env var without rebuilding.
13
+ function resolveRefreshTimeoutMs(option) {
14
+ if (typeof option === "number" && Number.isFinite(option) && option > 0) {
15
+ return option;
16
+ }
17
+ const fromEnv = process.env[REFRESH_TIMEOUT_ENV_VAR];
18
+ if (fromEnv) {
19
+ // Number() handles scientific notation (e.g. "6e4") which parseInt would silently truncate.
20
+ const parsed = Number(fromEnv);
21
+ if (Number.isFinite(parsed) && parsed > 0) {
22
+ return parsed;
23
+ }
24
+ }
25
+ return DEFAULT_REFRESH_TIMEOUT_MS;
26
+ }
9
27
  export class ProviderSnapshotManager {
10
28
  constructor(options) {
11
29
  this.snapshots = new Map();
@@ -19,7 +37,7 @@ export class ProviderSnapshotManager {
19
37
  this.runtimeSettings = options.runtimeSettings;
20
38
  this.providerOverrides = options.providerOverrides;
21
39
  this.baseProviderOverrides = options.providerOverrides;
22
- this.refreshTimeoutMs = options.refreshTimeoutMs ?? DEFAULT_REFRESH_TIMEOUT_MS;
40
+ this.refreshTimeoutMs = resolveRefreshTimeoutMs(options.refreshTimeoutMs);
23
41
  this.providerRegistry = this.buildRegistry();
24
42
  this.providerClients = { ...this.extraClients };
25
43
  }
@@ -1,7 +1,7 @@
1
- import { type AgentDefinition, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";
1
+ import { type AgentDefinition, type McpServerConfig as ClaudeSdkMcpServerConfig, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";
2
2
  import type { Logger } from "pino";
3
3
  import { type ClaudeQueryFactory } from "./query.js";
4
- import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMetadata, type AgentModelDefinition, type AgentPersistenceHandle, type AgentSession, type AgentSessionConfig, type AgentTimelineItem, type ListModelsOptions, type ListPersistedAgentsOptions, type PersistedAgentDescriptor } from "../../agent-sdk-types.js";
4
+ import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMetadata, type AgentModelDefinition, type AgentPersistenceHandle, type AgentSession, type AgentSessionConfig, type AgentTimelineItem, type ListModelsOptions, type ListPersistedAgentsOptions, type McpServerConfig, type PersistedAgentDescriptor } from "../../agent-sdk-types.js";
5
5
  import { type ProviderRuntimeSettings } from "../../provider-launch-config.js";
6
6
  export declare function normalizeClaudeAskUserQuestionUpdatedInput(updatedInput: AgentMetadata | undefined, fallbackInput: AgentMetadata | undefined): AgentMetadata;
7
7
  interface EventIdentifiers {
@@ -21,8 +21,10 @@ interface ClaudeAgentClientOptions {
21
21
  runtimeSettings?: ProviderRuntimeSettings;
22
22
  queryFactory?: ClaudeQueryFactory;
23
23
  resolveBinary?: () => Promise<string>;
24
+ configDir?: string;
24
25
  }
25
26
  export declare function extractUserMessageText(content: unknown): string | null;
27
+ export declare function toClaudeSdkMcpConfig(config: McpServerConfig): ClaudeSdkMcpServerConfig;
26
28
  export declare function readEventIdentifiers(message: SDKMessage): EventIdentifiers;
27
29
  export declare class ClaudeAgentClient implements AgentClient {
28
30
  readonly provider: "claude";
@@ -32,6 +34,7 @@ export declare class ClaudeAgentClient implements AgentClient {
32
34
  private readonly runtimeSettings?;
33
35
  private readonly queryFactory?;
34
36
  private readonly resolveBinary;
37
+ private readonly configDir?;
35
38
  constructor(options: ClaudeAgentClientOptions);
36
39
  createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext, options?: AgentCreateSessionOptions): Promise<AgentSession>;
37
40
  resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launchContext?: AgentLaunchContext): Promise<AgentSession>;
@@ -539,7 +539,7 @@ function coerceSessionMetadata(metadata) {
539
539
  }
540
540
  return result;
541
541
  }
542
- function toClaudeSdkMcpConfig(config) {
542
+ export function toClaudeSdkMcpConfig(config) {
543
543
  switch (config.type) {
544
544
  case "stdio":
545
545
  return {
@@ -547,18 +547,21 @@ function toClaudeSdkMcpConfig(config) {
547
547
  command: config.command,
548
548
  args: config.args,
549
549
  env: config.env,
550
+ alwaysLoad: config.alwaysLoad,
550
551
  };
551
552
  case "http":
552
553
  return {
553
554
  type: "http",
554
555
  url: config.url,
555
556
  headers: config.headers,
557
+ alwaysLoad: config.alwaysLoad,
556
558
  };
557
559
  case "sse":
558
560
  return {
559
561
  type: "sse",
560
562
  url: config.url,
561
563
  headers: config.headers,
564
+ alwaysLoad: config.alwaysLoad,
562
565
  };
563
566
  }
564
567
  throw new Error("Unhandled MCP server config type");
@@ -922,6 +925,7 @@ export class ClaudeAgentClient {
922
925
  this.runtimeSettings = options.runtimeSettings;
923
926
  this.queryFactory = options.queryFactory;
924
927
  this.resolveBinary = options.resolveBinary ?? (() => resolveClaudeBinary(this.runtimeSettings));
928
+ this.configDir = options.configDir;
925
929
  }
926
930
  async createSession(config, launchContext, options) {
927
931
  const claudeConfig = this.assertConfig(config);
@@ -961,7 +965,7 @@ export class ClaudeAgentClient {
961
965
  }
962
966
  async listModels(_options) {
963
967
  // Claude exposes a global catalog here; cwd/force are intentionally irrelevant.
964
- return await getClaudeModelsWithSettings(this.logger);
968
+ return await getClaudeModelsWithSettings(this.logger, this.configDir);
965
969
  }
966
970
  async listFeatures(config) {
967
971
  const claudeConfig = this.assertConfig(config);
@@ -1,7 +1,7 @@
1
1
  import type { Logger } from "pino";
2
2
  import type { AgentModelDefinition } from "../../agent-sdk-types.js";
3
3
  export declare function getClaudeModels(): AgentModelDefinition[];
4
- export declare function getClaudeModelsWithSettings(logger: Logger): Promise<AgentModelDefinition[]>;
4
+ export declare function getClaudeModelsWithSettings(logger: Logger, configDir?: string): Promise<AgentModelDefinition[]>;
5
5
  /**
6
6
  * Normalize a runtime model string (from SDK init message) to a known model ID.
7
7
  * Handles the `[1m]` suffix that the SDK appends for 1M context sessions.
@@ -89,9 +89,9 @@ const CLAUDE_SETTINGS_MODEL_ENV_KEYS = [
89
89
  export function getClaudeModels() {
90
90
  return CLAUDE_MODELS.map((model) => ({ ...model }));
91
91
  }
92
- export async function getClaudeModelsWithSettings(logger) {
92
+ export async function getClaudeModelsWithSettings(logger, configDir) {
93
93
  const hardcodedModels = getClaudeModels();
94
- const settingsModels = await readClaudeSettingsModels(logger);
94
+ const settingsModels = await readClaudeSettingsModels(logger, configDir);
95
95
  if (settingsModels.length === 0) {
96
96
  return hardcodedModels;
97
97
  }
@@ -106,8 +106,8 @@ export async function getClaudeModelsWithSettings(logger) {
106
106
  }
107
107
  return models;
108
108
  }
109
- async function readClaudeSettingsModels(logger) {
110
- const settingsPath = path.join(resolveClaudeConfigDir(), "settings.json");
109
+ async function readClaudeSettingsModels(logger, configDir) {
110
+ const settingsPath = path.join(resolveClaudeConfigDir(configDir), "settings.json");
111
111
  let parsed;
112
112
  try {
113
113
  const rawSettings = await fs.readFile(settingsPath, "utf8");
@@ -136,8 +136,8 @@ async function readClaudeSettingsModels(logger) {
136
136
  }
137
137
  return models;
138
138
  }
139
- function resolveClaudeConfigDir() {
140
- return process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
139
+ function resolveClaudeConfigDir(configDir) {
140
+ return configDir ?? process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
141
141
  }
142
142
  function addSettingsModel(models, value, settingsKey) {
143
143
  if (typeof value !== "string") {
@@ -34,6 +34,14 @@ const TURN_START_TIMEOUT_MS = 90 * 1000;
34
34
  const INTERRUPT_TIMEOUT_MS = 2000;
35
35
  const CODEX_PROVIDER = "codex";
36
36
  const CODEX_IMAGE_ATTACHMENT_DIR = "paseo-attachments";
37
+ // Codex treats most app-server client names as the model-request originator.
38
+ // This reserved Codex name is non-originating, so requests keep Codex's default
39
+ // CLI identity instead of showing up as Paseo in provider usage logs.
40
+ const CODEX_NON_ORIGINATING_APP_SERVER_CLIENT_INFO = {
41
+ name: "codex_app_server_daemon",
42
+ title: "Codex App Server Daemon",
43
+ version: "0.0.0",
44
+ };
37
45
  const ASSISTANT_MESSAGE_BOUNDARY_MARKDOWN = "\n\n---\n\n";
38
46
  const CODEX_TOOL_THREAD_ITEM_TYPES = new Set([
39
47
  "commandExecution",
@@ -2093,11 +2101,7 @@ export function buildCodexAppServerEnv(runtimeSettings, launchEnv) {
2093
2101
  }
2094
2102
  function buildCodexAppServerInitializeParams() {
2095
2103
  return {
2096
- clientInfo: {
2097
- name: "paseo",
2098
- title: "Paseo",
2099
- version: "0.0.0",
2100
- },
2104
+ clientInfo: CODEX_NON_ORIGINATING_APP_SERVER_CLIENT_INFO,
2101
2105
  capabilities: {
2102
2106
  experimentalApi: true,
2103
2107
  },
@@ -76,6 +76,7 @@ export declare class TestOpenCodeClient {
76
76
  sessionMessagesResponse: OpenCodeResponse;
77
77
  sessionPromptAsyncEvents: unknown[];
78
78
  sessionPromptAsyncResponse: OpenCodeResponse;
79
+ sessionSummarizeEvents: unknown[];
79
80
  sessionSummarizeResponse: OpenCodeResponse;
80
81
  sessionUpdateResponse: OpenCodeResponse;
81
82
  private readonly queuedEventStream;
@@ -70,6 +70,7 @@ export class TestOpenCodeClient {
70
70
  this.sessionMessagesResponse = { data: [] };
71
71
  this.sessionPromptAsyncEvents = [idleEvent()];
72
72
  this.sessionPromptAsyncResponse = {};
73
+ this.sessionSummarizeEvents = [idleEvent()];
73
74
  this.sessionSummarizeResponse = { data: {} };
74
75
  this.sessionUpdateResponse = {};
75
76
  this.queuedEventStream = createQueuedEventStream();
@@ -182,6 +183,9 @@ export class TestOpenCodeClient {
182
183
  },
183
184
  summarize: async (parameters) => {
184
185
  this.calls.sessionSummarize.push(parameters);
186
+ for (const event of this.sessionSummarizeEvents) {
187
+ this.emitEvent(event);
188
+ }
185
189
  return this.sessionSummarizeResponse;
186
190
  },
187
191
  update: async (parameters) => {
@@ -1,6 +1,6 @@
1
- import { type AssistantMessage as OpenCodeAssistantMessage, type Event as OpenCodeEvent, type FilePartInput as OpenCodeFilePartInput, type OpencodeClient, type TextPartInput as OpenCodeTextPartInput } from "@opencode-ai/sdk/v2/client";
1
+ import { type AssistantMessage as OpenCodeAssistantMessage, type Event as OpenCodeEvent, type FilePartInput as OpenCodeFilePartInput, type Message as OpenCodeMessage, type OpencodeClient, type Part as OpenCodePart, type TextPartInput as OpenCodeTextPartInput } from "@opencode-ai/sdk/v2/client";
2
2
  import type { Logger } from "pino";
3
- import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentUsage, type ResolveAgentCreateConfigInput, type ResolveAgentCreateConfigResult, type ListModelsOptions, type ListModesOptions, type ListPersistedAgentsOptions, type PersistedAgentDescriptor, type ToolCallTimelineItem } from "../agent-sdk-types.js";
3
+ import { type AgentCapabilityFlags, type AgentClient, type AgentCreateSessionOptions, type AgentFeature, type AgentLaunchContext, type AgentMode, type AgentModelDefinition, type AgentPermissionRequest, type AgentPermissionResponse, type AgentPersistenceHandle, type AgentPromptInput, type AgentRunOptions, type AgentRunResult, type AgentRuntimeInfo, type AgentSession, type AgentSessionConfig, type AgentSlashCommand, type AgentStreamEvent, type AgentTimelineItem, type AgentUsage, type ResolveAgentCreateConfigInput, type ResolveAgentCreateConfigResult, type ListModelsOptions, type ListModesOptions, type ListPersistedAgentsOptions, type PersistedAgentDescriptor, type ToolCallTimelineItem } from "../agent-sdk-types.js";
4
4
  import { isDefaultAgentCreateConfigUnattended } from "../create-agent-mode.js";
5
5
  import { type ProviderRuntimeSettings } from "../provider-launch-config.js";
6
6
  import { type OpenCodeRuntime } from "./opencode/runtime.js";
@@ -10,6 +10,10 @@ type OpenCodeAgentConfig = AgentSessionConfig & {
10
10
  provider: "opencode";
11
11
  };
12
12
  type OpenCodeMessageRole = "user" | "assistant";
13
+ interface OpenCodeSessionMessage {
14
+ info: OpenCodeMessage;
15
+ parts: OpenCodePart[];
16
+ }
13
17
  declare function reconcileOpenCodeSessionClose(params: {
14
18
  client: Pick<OpencodeClient, "session">;
15
19
  sessionId: string;
@@ -79,8 +83,10 @@ declare function mergeOpenCodeStepFinishUsage(usage: AgentUsage, part: {
79
83
  }): void;
80
84
  declare function hasNormalizedOpenCodeUsage(usage: AgentUsage): boolean;
81
85
  declare function buildOpenCodePromptParts(prompt: AgentPromptInput): Array<OpenCodeTextPartInput | OpenCodeFilePartInput>;
86
+ declare function buildOpenCodeSessionTimeline(messages: ReadonlyArray<OpenCodeSessionMessage>): AgentTimelineItem[];
82
87
  export declare const __openCodeInternals: {
83
88
  buildOpenCodePromptParts: typeof buildOpenCodePromptParts;
89
+ buildOpenCodeSessionTimeline: typeof buildOpenCodeSessionTimeline;
84
90
  buildOpenCodeModelContextWindowLookup: typeof buildOpenCodeModelContextWindowLookup;
85
91
  buildOpenCodeModelDefinition: typeof buildOpenCodeModelDefinition;
86
92
  buildOpenCodeModelLookupKey: typeof buildOpenCodeModelLookupKey;
@@ -133,6 +139,11 @@ export interface OpenCodeEventTranslationState {
133
139
  sessionTotalCostUsd?: number;
134
140
  streamedPartKeys: Set<string>;
135
141
  emittedStructuredMessageIds: Set<string>;
142
+ compactionSummaryMessageIds: Set<string>;
143
+ emittedCompactionPartIds: Set<string>;
144
+ suppressAssistantMessagesUntilIdle?: {
145
+ active: boolean;
146
+ };
136
147
  /** Tracks the type of each part by ID, learned from message.part.updated events. */
137
148
  partTypes: Map<string, string>;
138
149
  subAgentsByCallId?: Map<string, OpenCodeSubAgentActivityState>;
@@ -186,6 +197,9 @@ declare class OpenCodeAgentSession implements AgentSession {
186
197
  private streamedPartKeys;
187
198
  /** Tracks assistant messages already emitted from structured payloads. */
188
199
  private emittedStructuredMessageIds;
200
+ private compactionSummaryMessageIds;
201
+ private emittedCompactionPartIds;
202
+ private suppressAssistantMessagesUntilIdle;
189
203
  /** Tracks the type of each part by ID, learned from message.part.updated events. */
190
204
  private partTypes;
191
205
  private availableModesCache;