@getpaseo/server 0.1.84 → 0.1.86

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 (60) hide show
  1. package/dist/scripts/supervisor-entrypoint.js +1 -0
  2. package/dist/server/server/agent/agent-manager.d.ts +4 -0
  3. package/dist/server/server/agent/agent-manager.js +23 -0
  4. package/dist/server/server/agent/agent-metadata-generator.d.ts +9 -0
  5. package/dist/server/server/agent/agent-metadata-generator.js +11 -2
  6. package/dist/server/server/agent/agent-response-loop.d.ts +1 -1
  7. package/dist/server/server/agent/agent-response-loop.js +3 -13
  8. package/dist/server/server/agent/create-agent/create.d.ts +2 -0
  9. package/dist/server/server/agent/create-agent/create.js +7 -0
  10. package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +0 -1
  11. package/dist/server/server/agent/import-sessions.d.ts +3 -0
  12. package/dist/server/server/agent/import-sessions.js +11 -0
  13. package/dist/server/server/agent/mcp-server.d.ts +0 -1
  14. package/dist/server/server/agent/mcp-server.js +0 -4
  15. package/dist/server/server/agent/providers/claude/agent.d.ts +2 -1
  16. package/dist/server/server/agent/providers/claude/agent.js +70 -0
  17. package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
  18. package/dist/server/server/agent/providers/claude/feature-definitions.js +36 -0
  19. package/dist/server/server/agent/providers/claude/models.js +19 -5
  20. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +6 -3
  21. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +5 -0
  22. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +62 -0
  23. package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
  24. package/dist/server/server/agent/structured-generation-providers.js +192 -0
  25. package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +0 -2
  26. package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +0 -1
  27. package/dist/server/server/bootstrap.d.ts +7 -0
  28. package/dist/server/server/bootstrap.js +11 -2
  29. package/dist/server/server/config.js +1 -0
  30. package/dist/server/server/daemon-config-store.js +46 -6
  31. package/dist/server/server/daemon-worker.js +1 -0
  32. package/dist/server/server/file-explorer/service.js +4 -4
  33. package/dist/server/server/paseo-worktree-archive-service.d.ts +2 -6
  34. package/dist/server/server/paseo-worktree-archive-service.js +13 -33
  35. package/dist/server/server/persisted-config.d.ts +77 -22
  36. package/dist/server/server/persisted-config.js +13 -0
  37. package/dist/server/server/schedule/service.d.ts +1 -0
  38. package/dist/server/server/schedule/service.js +15 -0
  39. package/dist/server/server/session.d.ts +3 -2
  40. package/dist/server/server/session.js +77 -25
  41. package/dist/server/server/speech/providers/local/runtime.js +52 -133
  42. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +9 -2
  43. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +7 -0
  44. package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
  45. package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
  46. package/dist/server/server/speech/providers/local/worker-client.d.ts +80 -0
  47. package/dist/server/server/speech/providers/local/worker-client.js +438 -0
  48. package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
  49. package/dist/server/server/speech/providers/local/worker-process.js +270 -0
  50. package/dist/server/server/speech/providers/local/worker-protocol.d.ts +95 -0
  51. package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
  52. package/dist/server/server/websocket-server.js +2 -0
  53. package/dist/server/server/worktree-branch-name-generator.d.ts +9 -0
  54. package/dist/server/server/worktree-branch-name-generator.js +11 -2
  55. package/dist/server/utils/worktree.d.ts +1 -1
  56. package/dist/server/utils/worktree.js +2 -2
  57. package/dist/src/server/persisted-config.js +13 -0
  58. package/package.json +5 -10
  59. package/dist/server/utils/branch-slug.d.ts +0 -14
  60. package/dist/server/utils/branch-slug.js +0 -49
@@ -7,6 +7,7 @@ import { loadPersistedConfig } from "../src/server/persisted-config.js";
7
7
  import { runSupervisor } from "./supervisor.js";
8
8
  import { resolveSupervisorLogFile } from "./supervisor-log-config.js";
9
9
  import { applySherpaLoaderEnv } from "../src/server/speech/providers/local/sherpa/sherpa-runtime-env.js";
10
+ process.title = "Paseo Supervisor";
10
11
  function parseConfig(argv) {
11
12
  let devMode = false;
12
13
  const workerArgs = [];
@@ -40,6 +40,7 @@ export type AgentAttentionCallback = (params: {
40
40
  provider: AgentProvider;
41
41
  reason: "finished" | "error" | "permission";
42
42
  }) => void;
43
+ export type AgentArchivedCallback = (agentId: string) => Promise<void> | void;
43
44
  export interface ProviderAvailability {
44
45
  provider: AgentProvider;
45
46
  available: boolean;
@@ -178,6 +179,7 @@ export declare class AgentManager {
178
179
  private mcpBaseUrl;
179
180
  private appendSystemPrompt;
180
181
  private onAgentAttention?;
182
+ private onAgentArchived?;
181
183
  private logger;
182
184
  private readonly rescueTimeouts;
183
185
  constructor(options: AgentManagerOptions);
@@ -188,6 +190,7 @@ export declare class AgentManager {
188
190
  }): void;
189
191
  getRegisteredProviderIds(): AgentProvider[];
190
192
  setAgentAttentionCallback(callback: AgentAttentionCallback): void;
193
+ setAgentArchivedCallback(callback: AgentArchivedCallback): void;
191
194
  setMcpBaseUrl(url: string | null): void;
192
195
  setAppendSystemPrompt(prompt: string | null | undefined): void;
193
196
  getMetricsSnapshot(): AgentMetricsSnapshot;
@@ -232,6 +235,7 @@ export declare class AgentManager {
232
235
  }>;
233
236
  private cascadeArchiveChildren;
234
237
  private markRecordArchived;
238
+ private fireAgentArchived;
235
239
  private dispatchArchivedStoredAgent;
236
240
  setAgentMode(agentId: string, modeId: string): Promise<void>;
237
241
  setAgentModel(agentId: string, modelId: string | null): Promise<void>;
@@ -181,6 +181,9 @@ export class AgentManager {
181
181
  setAgentAttentionCallback(callback) {
182
182
  this.onAgentAttention = callback;
183
183
  }
184
+ setAgentArchivedCallback(callback) {
185
+ this.onAgentArchived = callback;
186
+ }
184
187
  setMcpBaseUrl(url) {
185
188
  this.mcpBaseUrl = url;
186
189
  }
@@ -672,8 +675,21 @@ export class AgentManager {
672
675
  else if (!archivedRecord.internal) {
673
676
  this.dispatchArchivedStoredAgent(archivedRecord);
674
677
  }
678
+ await this.fireAgentArchived(record.id);
675
679
  return archivedRecord;
676
680
  }
681
+ async fireAgentArchived(agentId) {
682
+ const callback = this.onAgentArchived;
683
+ if (!callback) {
684
+ return;
685
+ }
686
+ try {
687
+ await callback(agentId);
688
+ }
689
+ catch (error) {
690
+ this.logger.warn({ err: error, agentId }, "onAgentArchived callback failed");
691
+ }
692
+ }
677
693
  dispatchArchivedStoredAgent(record) {
678
694
  const updatedAt = new Date(record.updatedAt);
679
695
  this.dispatch({
@@ -829,6 +845,13 @@ export class AgentManager {
829
845
  const nextRecord = buildArchivedAgentRecord(record, { archivedAt });
830
846
  await registry.upsert(nextRecord);
831
847
  await this.archiveNativeSessionBestEffort(record.provider, record.persistence);
848
+ if (this.agents.has(agentId)) {
849
+ this.notifyAgentState(agentId);
850
+ }
851
+ else if (!nextRecord.internal) {
852
+ this.dispatchArchivedStoredAgent(nextRecord);
853
+ }
854
+ await this.fireAgentArchived(agentId);
832
855
  return nextRecord;
833
856
  }
834
857
  async unarchiveSnapshot(agentId) {
@@ -1,7 +1,9 @@
1
1
  import type { Logger } from "pino";
2
2
  import type { AgentManager } from "./agent-manager.js";
3
3
  import { generateStructuredAgentResponseWithFallback } from "./agent-response-loop.js";
4
+ import { type StructuredGenerationDaemonConfig } from "./structured-generation-providers.js";
4
5
  import type { WorkspaceGitService } from "../workspace-git-service.js";
6
+ import type { ProviderSnapshotManager } from "./provider-snapshot-manager.js";
5
7
  export interface AgentMetadataGeneratorDeps {
6
8
  generateStructuredAgentResponseWithFallback?: typeof generateStructuredAgentResponseWithFallback;
7
9
  }
@@ -10,6 +12,13 @@ export interface AgentMetadataGenerationOptions {
10
12
  agentId: string;
11
13
  cwd: string;
12
14
  workspaceGitService?: Pick<WorkspaceGitService, "resolveRepoRoot">;
15
+ providerSnapshotManager?: Pick<ProviderSnapshotManager, "listProviders">;
16
+ daemonConfig?: StructuredGenerationDaemonConfig | null;
17
+ currentSelection?: {
18
+ provider?: string | null;
19
+ model?: string | null;
20
+ thinkingOptionId?: string | null;
21
+ };
13
22
  initialPrompt?: string | null;
14
23
  explicitTitle?: string | null;
15
24
  paseoHome?: string;
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { DEFAULT_STRUCTURED_GENERATION_PROVIDERS, StructuredAgentFallbackError, StructuredAgentResponseError, generateStructuredAgentResponseWithFallback, } from "./agent-response-loop.js";
2
+ import { StructuredAgentFallbackError, StructuredAgentResponseError, generateStructuredAgentResponseWithFallback, } from "./agent-response-loop.js";
3
+ import { resolveStructuredGenerationProviders, } from "./structured-generation-providers.js";
3
4
  import { MAX_AUTO_AGENT_TITLE_CHARS } from "@getpaseo/protocol/agent-title-limits";
4
5
  import { buildMetadataPrompt } from "../../utils/build-metadata-prompt.js";
5
6
  function hasExplicitTitle(title) {
@@ -60,6 +61,14 @@ export async function generateAndApplyAgentMetadata(options) {
60
61
  generateStructuredAgentResponseWithFallback;
61
62
  let result;
62
63
  try {
64
+ const providers = options.providerSnapshotManager
65
+ ? await resolveStructuredGenerationProviders({
66
+ cwd: options.cwd,
67
+ providerSnapshotManager: options.providerSnapshotManager,
68
+ daemonConfig: options.daemonConfig,
69
+ currentSelection: options.currentSelection,
70
+ })
71
+ : [];
63
72
  result = await generator({
64
73
  manager: options.agentManager,
65
74
  cwd: options.cwd,
@@ -70,7 +79,7 @@ export async function generateAndApplyAgentMetadata(options) {
70
79
  schema,
71
80
  schemaName: "AgentMetadata",
72
81
  maxRetries: 2,
73
- providers: DEFAULT_STRUCTURED_GENERATION_PROVIDERS,
82
+ providers,
74
83
  persistSession: false,
75
84
  logger: options.logger,
76
85
  agentConfigOverrides: {
@@ -60,7 +60,7 @@ export interface StructuredAgentGenerationWithFallbackOptions<T> {
60
60
  logger?: StructuredGenerationLogger;
61
61
  runner?: <TResult>(options: StructuredAgentGenerationOptions<TResult>) => Promise<TResult>;
62
62
  }
63
- export declare const DEFAULT_STRUCTURED_GENERATION_PROVIDERS: readonly StructuredGenerationProvider[];
63
+ export { DEFAULT_STRUCTURED_GENERATION_PROVIDERS } from "./structured-generation-providers.js";
64
64
  export declare function getStructuredAgentResponse<T>(options: StructuredAgentResponseOptions<T>): Promise<T>;
65
65
  export declare function generateStructuredAgentResponse<T>(options: StructuredAgentGenerationOptions<T>): Promise<T>;
66
66
  export declare function generateStructuredAgentResponseWithFallback<T>(options: StructuredAgentGenerationWithFallbackOptions<T>): Promise<T>;
@@ -1,6 +1,5 @@
1
1
  import { zodToJsonSchema } from "zod-to-json-schema";
2
2
  import Ajv from "ajv";
3
- import { getAgentProviderDefinition } from "@getpaseo/protocol/provider-manifest";
4
3
  export class StructuredAgentResponseError extends Error {
5
4
  constructor(message, options) {
6
5
  super(message);
@@ -27,12 +26,8 @@ export class StructuredAgentFallbackError extends Error {
27
26
  this.attempts = attempts;
28
27
  }
29
28
  }
30
- export const DEFAULT_STRUCTURED_GENERATION_PROVIDERS = [
31
- { provider: "claude", model: "haiku" },
32
- { provider: "codex", model: "gpt-5.4-mini", thinkingOptionId: "low" },
33
- { provider: "opencode", model: "opencode/minimax-m2.5-free" },
34
- { provider: "opencode", model: "opencode/nemotron-3-super-free" },
35
- ];
29
+ // Re-export from the legacy module path so existing server consumers keep working.
30
+ export { DEFAULT_STRUCTURED_GENERATION_PROVIDERS } from "./structured-generation-providers.js";
36
31
  function isZodSchema(value) {
37
32
  return typeof value?.safeParse === "function";
38
33
  }
@@ -229,12 +224,7 @@ export async function getStructuredAgentResponse(options) {
229
224
  }
230
225
  export async function generateStructuredAgentResponse(options) {
231
226
  const { manager, agentConfig, agentId, persistSession, prompt, schema, maxRetries, schemaName } = options;
232
- const modeId = agentConfig.modeId ??
233
- getAgentProviderDefinition(agentConfig.provider).defaultModeId ??
234
- undefined;
235
- const agent = await manager.createAgent({ ...agentConfig, modeId }, agentId, {
236
- persistSession,
237
- });
227
+ const agent = await manager.createAgent(agentConfig, agentId, { persistSession });
238
228
  try {
239
229
  const caller = async (nextPrompt) => {
240
230
  const result = await manager.runAgent(agent.id, nextPrompt);
@@ -4,6 +4,7 @@ import type { WorkspaceGitService } from "../../workspace-git-service.js";
4
4
  import type { AgentWorktreeSetupContinuation, CreatePaseoWorktreeWorkflowFn } from "../../worktree-session.js";
5
5
  import type { AgentAttachment, FirstAgentContext, GitSetupOptions } from "../../messages.js";
6
6
  import type { AgentManager, ManagedAgent } from "../agent-manager.js";
7
+ import type { StructuredGenerationDaemonConfig } from "../structured-generation-providers.js";
7
8
  import type { AgentSessionConfig } from "../agent-sdk-types.js";
8
9
  import type { AgentStorage } from "../agent-storage.js";
9
10
  import type { ProviderSnapshotManager } from "../provider-snapshot-manager.js";
@@ -22,6 +23,7 @@ interface CreateAgentCommandDependencies {
22
23
  workspaceGitService?: Pick<WorkspaceGitService, "getSnapshot" | "listWorktrees" | "resolveRepoRoot">;
23
24
  terminalManager?: TerminalManager | null;
24
25
  providerSnapshotManager: ProviderSnapshotManager;
26
+ daemonConfig?: StructuredGenerationDaemonConfig | null;
25
27
  createPaseoWorktree?: CreatePaseoWorktreeWorkflowFn;
26
28
  }
27
29
  export interface CreateAgentFromSessionInput {
@@ -121,6 +121,13 @@ async function sendInitialPrompt(dependencies, resolved, snapshot) {
121
121
  agentId: snapshot.id,
122
122
  cwd: snapshot.cwd,
123
123
  workspaceGitService: dependencies.workspaceGitService,
124
+ providerSnapshotManager: dependencies.providerSnapshotManager,
125
+ daemonConfig: dependencies.daemonConfig,
126
+ currentSelection: {
127
+ provider: snapshot.provider,
128
+ model: snapshot.runtimeInfo?.model ?? resolved.config.model,
129
+ thinkingOptionId: snapshot.runtimeInfo?.thinkingOptionId ?? resolved.config.thinkingOptionId ?? null,
130
+ },
124
131
  initialPrompt: resolved.metadataInitialPrompt,
125
132
  explicitTitle: resolved.explicitTitle,
126
133
  paseoHome: dependencies.paseoHome,
@@ -119,7 +119,6 @@ export class CreateAgentLifecycleDispatch {
119
119
  agentManager: this.dependencies.agentManager,
120
120
  agentStorage: this.dependencies.agentStorage,
121
121
  archiveWorkspaceRecord: this.dependencies.archiveWorkspaceRecord,
122
- emit: this.dependencies.emit,
123
122
  emitWorkspaceUpdatesForWorkspaceIds: this.dependencies.emitWorkspaceUpdatesForWorkspaceIds,
124
123
  markWorkspaceArchiving: this.dependencies.markWorkspaceArchiving,
125
124
  clearWorkspaceArchiving: this.dependencies.clearWorkspaceArchiving,
@@ -4,6 +4,7 @@ import type { ProviderSnapshotManager } from "./provider-snapshot-manager.js";
4
4
  import type { AgentManager, ManagedAgent } from "./agent-manager.js";
5
5
  import type { AgentStorage } from "./agent-storage.js";
6
6
  import { scheduleAgentMetadataGeneration } from "./agent-metadata-generator.js";
7
+ import type { StructuredGenerationDaemonConfig } from "./structured-generation-providers.js";
7
8
  import type { FetchRecentProviderSessionsRequestMessage, ImportAgentRequestMessageSchema, RecentProviderSessionDescriptorPayload } from "@getpaseo/protocol/messages";
8
9
  import type { WorkspaceGitService } from "../workspace-git-service.js";
9
10
  type ImportAgentRequestMessage = z.infer<typeof ImportAgentRequestMessageSchema>;
@@ -33,6 +34,8 @@ export interface ImportProviderSessionInput {
33
34
  agentManager: AgentManager;
34
35
  agentStorage: AgentStorage;
35
36
  workspaceGitService?: Pick<WorkspaceGitService, "resolveRepoRoot">;
37
+ providerSnapshotManager?: Pick<ProviderSnapshotManager, "listProviders">;
38
+ daemonConfig?: StructuredGenerationDaemonConfig | null;
36
39
  paseoHome?: string;
37
40
  logger: Logger;
38
41
  deps?: {
@@ -94,6 +94,8 @@ export async function importProviderSession(input) {
94
94
  snapshot,
95
95
  agentManager: input.agentManager,
96
96
  workspaceGitService: input.workspaceGitService,
97
+ providerSnapshotManager: input.providerSnapshotManager,
98
+ daemonConfig: input.daemonConfig,
97
99
  paseoHome: input.paseoHome,
98
100
  logger: input.logger,
99
101
  scheduleAgentMetadataGeneration: input.deps?.scheduleAgentMetadataGeneration ?? scheduleAgentMetadataGeneration,
@@ -129,6 +131,15 @@ async function applyImportedAgentTitle(input) {
129
131
  agentId: input.snapshot.id,
130
132
  cwd: input.snapshot.cwd,
131
133
  workspaceGitService: input.workspaceGitService,
134
+ providerSnapshotManager: input.providerSnapshotManager,
135
+ daemonConfig: input.daemonConfig,
136
+ currentSelection: {
137
+ provider: input.snapshot.provider,
138
+ model: input.snapshot.runtimeInfo?.model ?? input.snapshot.config.model,
139
+ thinkingOptionId: input.snapshot.runtimeInfo?.thinkingOptionId ??
140
+ input.snapshot.config.thinkingOptionId ??
141
+ null,
142
+ },
132
143
  initialPrompt,
133
144
  explicitTitle,
134
145
  paseoHome: input.paseoHome,
@@ -23,7 +23,6 @@ export interface AgentMcpServerOptions {
23
23
  emitWorkspaceUpdatesForWorkspaceIds?: ArchivePaseoWorktreeDependencies["emitWorkspaceUpdatesForWorkspaceIds"];
24
24
  markWorkspaceArchiving?: ArchivePaseoWorktreeDependencies["markWorkspaceArchiving"];
25
25
  clearWorkspaceArchiving?: ArchivePaseoWorktreeDependencies["clearWorkspaceArchiving"];
26
- emitSessionMessage?: ArchivePaseoWorktreeDependencies["emit"];
27
26
  createPaseoWorktree?: CreatePaseoWorktreeWorkflowFn;
28
27
  paseoHome?: string;
29
28
  /**
@@ -1745,9 +1745,6 @@ function archiveWorktreeDependencies(options, context) {
1745
1745
  if (!options.clearWorkspaceArchiving) {
1746
1746
  throw new Error("Workspace archiving clearer is required to archive worktrees");
1747
1747
  }
1748
- if (!options.emitSessionMessage) {
1749
- throw new Error("Session message emitter is required to archive worktrees");
1750
- }
1751
1748
  return {
1752
1749
  paseoHome: options.paseoHome,
1753
1750
  github: options.github,
@@ -1755,7 +1752,6 @@ function archiveWorktreeDependencies(options, context) {
1755
1752
  agentManager: context.agentManager,
1756
1753
  agentStorage: context.agentStorage,
1757
1754
  archiveWorkspaceRecord: options.archiveWorkspaceRecord,
1758
- emit: options.emitSessionMessage,
1759
1755
  emitWorkspaceUpdatesForWorkspaceIds: options.emitWorkspaceUpdatesForWorkspaceIds,
1760
1756
  markWorkspaceArchiving: options.markWorkspaceArchiving,
1761
1757
  clearWorkspaceArchiving: options.clearWorkspaceArchiving,
@@ -1,7 +1,7 @@
1
1
  import { type AgentDefinition, 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 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 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 {
@@ -36,6 +36,7 @@ export declare class ClaudeAgentClient implements AgentClient {
36
36
  createSession(config: AgentSessionConfig, launchContext?: AgentLaunchContext, options?: AgentCreateSessionOptions): Promise<AgentSession>;
37
37
  resumeSession(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, launchContext?: AgentLaunchContext): Promise<AgentSession>;
38
38
  listModels(_options: ListModelsOptions): Promise<AgentModelDefinition[]>;
39
+ listFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
39
40
  listPersistedAgents(options?: ListPersistedAgentsOptions): Promise<PersistedAgentDescriptor[]>;
40
41
  isAvailable(): Promise<boolean>;
41
42
  getDiagnostic(): Promise<{
@@ -8,6 +8,7 @@ import { mapTaskNotificationSystemRecordToToolCall, mapTaskNotificationUserConte
8
8
  import { getClaudeModelsWithSettings, normalizeClaudeRuntimeModelId } from "./models.js";
9
9
  import { parsePartialJsonObject } from "./partial-json.js";
10
10
  import { ClaudeSidechainTracker } from "./sidechain-tracker.js";
11
+ import { buildClaudeFeatures, claudeModelSupportsFastMode } from "./feature-definitions.js";
11
12
  import { buildBinaryDiagnosticRows, formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, toDiagnosticErrorMessage, } from "../diagnostic-utils.js";
12
13
  import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "../provider-runner.js";
13
14
  import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
@@ -215,8 +216,21 @@ function summarizeClaudeOptionsForLog(options) {
215
216
  ? options.pathToClaudeCodeExecutable
216
217
  : null,
217
218
  persistSession: typeof options.persistSession === "boolean" ? options.persistSession : null,
219
+ fastMode: readClaudeFastModeSetting(options.settings),
218
220
  };
219
221
  }
222
+ function readClaudeFastModeSetting(settings) {
223
+ if (!settings || typeof settings === "string") {
224
+ return null;
225
+ }
226
+ return typeof settings.fastMode === "boolean" ? settings.fastMode : null;
227
+ }
228
+ function mergeClaudeSettings(settings, updates) {
229
+ if (!settings || typeof settings === "string") {
230
+ return settings ?? updates;
231
+ }
232
+ return { ...settings, ...updates };
233
+ }
220
234
  function isToolResultTextBlock(value) {
221
235
  return (!!value &&
222
236
  typeof value === "object" &&
@@ -951,6 +965,13 @@ export class ClaudeAgentClient {
951
965
  // Claude exposes a global catalog here; cwd/force are intentionally irrelevant.
952
966
  return await getClaudeModelsWithSettings(this.logger);
953
967
  }
968
+ async listFeatures(config) {
969
+ const claudeConfig = this.assertConfig(config);
970
+ return buildClaudeFeatures({
971
+ modelId: claudeConfig.model,
972
+ fastModeEnabled: claudeConfig.featureValues?.fast_mode === true,
973
+ });
974
+ }
954
975
  async listPersistedAgents(options) {
955
976
  const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
956
977
  const projectsRoot = path.join(configDir, "projects");
@@ -1273,6 +1294,12 @@ class ClaudeAgentSession {
1273
1294
  get id() {
1274
1295
  return this.claudeSessionId;
1275
1296
  }
1297
+ get features() {
1298
+ return buildClaudeFeatures({
1299
+ modelId: this.config.model,
1300
+ fastModeEnabled: this.config.featureValues?.fast_mode === true,
1301
+ });
1302
+ }
1276
1303
  async getRuntimeInfo() {
1277
1304
  if (this.cachedRuntimeInfo) {
1278
1305
  return { ...this.cachedRuntimeInfo };
@@ -1444,6 +1471,9 @@ class ClaudeAgentSession {
1444
1471
  const activeQuery = await this.ensureQuery();
1445
1472
  await activeQuery.setModel(normalizedModelId ?? undefined);
1446
1473
  this.config.model = normalizedModelId ?? undefined;
1474
+ if (!claudeModelSupportsFastMode(this.config.model) && this.config.featureValues?.fast_mode) {
1475
+ await this.applyFastModeFeature(false, activeQuery);
1476
+ }
1447
1477
  this.lastOptionsModel = normalizedModelId ?? this.lastOptionsModel;
1448
1478
  this.lastRuntimeModel = null;
1449
1479
  this.cachedRuntimeInfo = null;
@@ -1465,6 +1495,27 @@ class ClaudeAgentSession {
1465
1495
  }
1466
1496
  this.queryRestartNeeded = true;
1467
1497
  }
1498
+ async setFeature(featureId, value) {
1499
+ if (featureId !== "fast_mode") {
1500
+ throw new Error(`Unknown Claude feature: ${featureId}`);
1501
+ }
1502
+ const enabled = Boolean(value);
1503
+ if (enabled && !claudeModelSupportsFastMode(this.config.model)) {
1504
+ throw new Error(`Claude fast mode is not available for model '${this.config.model ?? "default"}'`);
1505
+ }
1506
+ await this.applyFastModeFeature(enabled);
1507
+ }
1508
+ async applyFastModeFeature(enabled, query) {
1509
+ this.config.featureValues = {
1510
+ ...this.config.featureValues,
1511
+ fast_mode: enabled,
1512
+ };
1513
+ const activeQuery = query ?? this.query;
1514
+ if (activeQuery) {
1515
+ await activeQuery.applyFlagSettings({ fastMode: enabled });
1516
+ }
1517
+ this.cachedRuntimeInfo = null;
1518
+ }
1468
1519
  getPendingPermissions() {
1469
1520
  return Array.from(this.pendingPermissions.values()).map((entry) => entry.request);
1470
1521
  }
@@ -1920,6 +1971,10 @@ class ClaudeAgentSession {
1920
1971
  launchEnv: this.launchEnv,
1921
1972
  queryFactory: this.queryFactory,
1922
1973
  });
1974
+ const fastMode = this.resolveFastModeSetting();
1975
+ if (fastMode !== null) {
1976
+ await this.query.applyFlagSettings({ fastMode });
1977
+ }
1923
1978
  // Do not kick off background control-plane queries here. Methods like
1924
1979
  // supportedCommands()/setPermissionMode() may execute immediately after
1925
1980
  // ensureQuery() (for listCommands()/setMode()), and sharing the same query
@@ -1991,6 +2046,7 @@ class ClaudeAgentSession {
1991
2046
  const { thinking, effort } = this.resolveThinkingConfig();
1992
2047
  const appendedSystemPrompt = this.buildAppendedSystemPrompt();
1993
2048
  const extraClaudeOptions = this.config.extra?.claude;
2049
+ const fastModeOptions = this.buildFastModeOptions(extraClaudeOptions);
1994
2050
  const sdkEnv = this.buildSdkEnv(extraClaudeOptions);
1995
2051
  assertClaudeAutoModeEligible(this.currentMode, sdkEnv);
1996
2052
  const claudeBinary = await this.resolveBinary();
@@ -2039,6 +2095,7 @@ class ClaudeAgentSession {
2039
2095
  ...(thinking ? { thinking } : {}),
2040
2096
  ...(effort ? { effort } : {}),
2041
2097
  ...extraClaudeOptions,
2098
+ ...fastModeOptions,
2042
2099
  ...(this.persistSession === undefined ? {} : { persistSession: this.persistSession }),
2043
2100
  env: sdkEnv,
2044
2101
  };
@@ -2060,6 +2117,19 @@ class ClaudeAgentSession {
2060
2117
  }
2061
2118
  return base;
2062
2119
  }
2120
+ buildFastModeOptions(extraClaudeOptions) {
2121
+ const fastMode = this.resolveFastModeSetting();
2122
+ if (fastMode === null) {
2123
+ return {};
2124
+ }
2125
+ return { settings: mergeClaudeSettings(extraClaudeOptions?.settings, { fastMode }) };
2126
+ }
2127
+ resolveFastModeSetting() {
2128
+ if (!claudeModelSupportsFastMode(this.config.model)) {
2129
+ return null;
2130
+ }
2131
+ return this.config.featureValues?.fast_mode === true;
2132
+ }
2063
2133
  normalizeMcpServers(servers) {
2064
2134
  const result = {};
2065
2135
  for (const [name, config] of Object.entries(servers)) {
@@ -0,0 +1,8 @@
1
+ import type { AgentFeature, AgentFeatureToggle } from "../../agent-sdk-types.js";
2
+ export declare const CLAUDE_FAST_MODE_FEATURE: Omit<AgentFeatureToggle, "value">;
3
+ export declare function claudeModelSupportsFastMode(modelId: string | null | undefined): boolean;
4
+ export declare function buildClaudeFeatures(input: {
5
+ modelId: string | null | undefined;
6
+ fastModeEnabled: boolean;
7
+ }): AgentFeature[];
8
+ //# sourceMappingURL=feature-definitions.d.ts.map
@@ -0,0 +1,36 @@
1
+ const CLAUDE_FAST_MODE_SUPPORTED_MODEL_PREFIXES = [
2
+ "claude-opus-4-8",
3
+ "claude-opus-4-7",
4
+ "claude-opus-4-6",
5
+ ];
6
+ export const CLAUDE_FAST_MODE_FEATURE = {
7
+ type: "toggle",
8
+ id: "fast_mode",
9
+ label: "Fast",
10
+ description: "Lower latency Opus responses at higher token cost",
11
+ tooltip: "Toggle fast mode",
12
+ icon: "zap",
13
+ };
14
+ function normalizeClaudeModelId(modelId) {
15
+ const normalized = typeof modelId === "string" ? modelId.trim() : "";
16
+ return normalized.length > 0 ? normalized : null;
17
+ }
18
+ export function claudeModelSupportsFastMode(modelId) {
19
+ const normalizedModelId = normalizeClaudeModelId(modelId);
20
+ if (!normalizedModelId) {
21
+ return false;
22
+ }
23
+ return CLAUDE_FAST_MODE_SUPPORTED_MODEL_PREFIXES.some((prefix) => normalizedModelId === prefix || normalizedModelId.startsWith(`${prefix}[`));
24
+ }
25
+ export function buildClaudeFeatures(input) {
26
+ if (!claudeModelSupportsFastMode(input.modelId)) {
27
+ return [];
28
+ }
29
+ return [
30
+ {
31
+ ...CLAUDE_FAST_MODE_FEATURE,
32
+ value: input.fastModeEnabled,
33
+ },
34
+ ];
35
+ }
36
+ //# sourceMappingURL=feature-definitions.js.map
@@ -7,7 +7,7 @@ const CLAUDE_THINKING_OPTIONS = [
7
7
  { id: "high", label: "High" },
8
8
  { id: "max", label: "Max" },
9
9
  ];
10
- const CLAUDE_OPUS_4_7_THINKING_OPTIONS = [
10
+ const CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS = [
11
11
  { id: "low", label: "Low" },
12
12
  { id: "medium", label: "Medium" },
13
13
  { id: "high", label: "High" },
@@ -15,19 +15,34 @@ const CLAUDE_OPUS_4_7_THINKING_OPTIONS = [
15
15
  { id: "max", label: "Max" },
16
16
  ];
17
17
  const CLAUDE_MODELS = [
18
+ {
19
+ provider: "claude",
20
+ id: "claude-opus-4-8[1m]",
21
+ label: "Opus 4.8 1M",
22
+ description: "Opus 4.8 with 1M context window",
23
+ thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
24
+ },
25
+ {
26
+ provider: "claude",
27
+ id: "claude-opus-4-8",
28
+ label: "Opus 4.8",
29
+ description: "Opus 4.8 · Latest release",
30
+ isDefault: true,
31
+ thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
32
+ },
18
33
  {
19
34
  provider: "claude",
20
35
  id: "claude-opus-4-7[1m]",
21
36
  label: "Opus 4.7 1M",
22
37
  description: "Opus 4.7 with 1M context window",
23
- thinkingOptions: [...CLAUDE_OPUS_4_7_THINKING_OPTIONS],
38
+ thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
24
39
  },
25
40
  {
26
41
  provider: "claude",
27
42
  id: "claude-opus-4-7",
28
43
  label: "Opus 4.7",
29
- description: "Opus 4.7 · Latest release",
30
- thinkingOptions: [...CLAUDE_OPUS_4_7_THINKING_OPTIONS],
44
+ description: "Opus 4.7 · Previous release",
45
+ thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
31
46
  },
32
47
  {
33
48
  provider: "claude",
@@ -41,7 +56,6 @@ const CLAUDE_MODELS = [
41
56
  id: "claude-opus-4-6",
42
57
  label: "Opus 4.6",
43
58
  description: "Opus 4.6 · Most capable for complex work",
44
- isDefault: true,
45
59
  thinkingOptions: [...CLAUDE_THINKING_OPTIONS],
46
60
  },
47
61
  {
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { extractCodexShellOutput, flattenReadContent as flattenToolReadContent, nonEmptyString, truncateDiffText, } from "./tool-call-mapper-utils.js";
2
+ import { extractCodexShellOutput, flattenReadContent as flattenToolReadContent, nonEmptyString, stripReadLineNumberGutter, truncateDiffText, } from "./tool-call-mapper-utils.js";
3
3
  export const CommandValueSchema = z.union([z.string(), z.array(z.string())]);
4
4
  export const ToolShellInputSchema = z
5
5
  .union([
@@ -628,11 +628,14 @@ export function toReadToolDetail(input, output, options) {
628
628
  if (!filePath) {
629
629
  return undefined;
630
630
  }
631
+ const stripped = output?.content ? stripReadLineNumberGutter(output.content) : undefined;
632
+ const content = stripped?.content ?? output?.content;
633
+ const offset = input?.offset ?? stripped?.startLine;
631
634
  return {
632
635
  type: "read",
633
636
  filePath,
634
- ...(output?.content ? { content: output.content } : {}),
635
- ...(input?.offset !== undefined ? { offset: input.offset } : {}),
637
+ ...(content ? { content } : {}),
638
+ ...(offset !== undefined ? { offset } : {}),
636
639
  ...(input?.limit !== undefined ? { limit: input.limit } : {}),
637
640
  };
638
641
  }
@@ -9,6 +9,11 @@ export declare function nonEmptyString(value: unknown): string | undefined;
9
9
  export declare function extractCodexShellOutput(value: string | undefined): string | undefined;
10
10
  export declare function extractCodexTerminalSessionId(value: string | undefined): string | undefined;
11
11
  export declare function flattenReadContent<Chunk extends ReadChunkLike>(value: string | Chunk | Chunk[] | undefined): string | undefined;
12
+ export interface StrippedReadContent {
13
+ content: string;
14
+ startLine?: number;
15
+ }
16
+ export declare function stripReadLineNumberGutter(content: string | undefined): StrippedReadContent | undefined;
12
17
  export declare function truncateDiffText(text: string | undefined, maxChars?: number): string | undefined;
13
18
  export declare function coerceToolCallId(params: {
14
19
  providerPrefix: string;