@getpaseo/server 0.1.85 → 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 (44) hide show
  1. package/dist/scripts/supervisor-entrypoint.js +1 -0
  2. package/dist/server/server/agent/agent-metadata-generator.d.ts +9 -0
  3. package/dist/server/server/agent/agent-metadata-generator.js +11 -2
  4. package/dist/server/server/agent/agent-response-loop.d.ts +1 -1
  5. package/dist/server/server/agent/agent-response-loop.js +3 -13
  6. package/dist/server/server/agent/create-agent/create.d.ts +2 -0
  7. package/dist/server/server/agent/create-agent/create.js +7 -0
  8. package/dist/server/server/agent/import-sessions.d.ts +3 -0
  9. package/dist/server/server/agent/import-sessions.js +11 -0
  10. package/dist/server/server/agent/providers/claude/agent.d.ts +2 -1
  11. package/dist/server/server/agent/providers/claude/agent.js +70 -0
  12. package/dist/server/server/agent/providers/claude/feature-definitions.d.ts +8 -0
  13. package/dist/server/server/agent/providers/claude/feature-definitions.js +36 -0
  14. package/dist/server/server/agent/providers/tool-call-detail-primitives.js +6 -3
  15. package/dist/server/server/agent/providers/tool-call-mapper-utils.d.ts +5 -0
  16. package/dist/server/server/agent/providers/tool-call-mapper-utils.js +62 -0
  17. package/dist/server/server/agent/structured-generation-providers.d.ts +29 -0
  18. package/dist/server/server/agent/structured-generation-providers.js +192 -0
  19. package/dist/server/server/bootstrap.d.ts +7 -0
  20. package/dist/server/server/bootstrap.js +3 -0
  21. package/dist/server/server/config.js +1 -0
  22. package/dist/server/server/daemon-config-store.js +46 -6
  23. package/dist/server/server/daemon-worker.js +1 -0
  24. package/dist/server/server/file-explorer/service.js +4 -4
  25. package/dist/server/server/persisted-config.d.ts +77 -22
  26. package/dist/server/server/persisted-config.js +13 -0
  27. package/dist/server/server/session.d.ts +3 -2
  28. package/dist/server/server/session.js +76 -24
  29. package/dist/server/server/speech/providers/local/runtime.js +52 -133
  30. package/dist/server/server/speech/providers/local/sherpa/model-catalog.d.ts +9 -2
  31. package/dist/server/server/speech/providers/local/sherpa/model-catalog.js +7 -0
  32. package/dist/server/server/speech/providers/local/worker-bytes.d.ts +4 -0
  33. package/dist/server/server/speech/providers/local/worker-bytes.js +9 -0
  34. package/dist/server/server/speech/providers/local/worker-client.d.ts +80 -0
  35. package/dist/server/server/speech/providers/local/worker-client.js +438 -0
  36. package/dist/server/server/speech/providers/local/worker-process.d.ts +2 -0
  37. package/dist/server/server/speech/providers/local/worker-process.js +270 -0
  38. package/dist/server/server/speech/providers/local/worker-protocol.d.ts +95 -0
  39. package/dist/server/server/speech/providers/local/worker-protocol.js +2 -0
  40. package/dist/server/server/websocket-server.js +2 -0
  41. package/dist/server/server/worktree-branch-name-generator.d.ts +9 -0
  42. package/dist/server/server/worktree-branch-name-generator.js +11 -2
  43. package/dist/src/server/persisted-config.js +13 -0
  44. package/package.json +5 -5
@@ -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 = [];
@@ -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,
@@ -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,
@@ -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
@@ -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;
@@ -112,6 +112,68 @@ export function flattenReadContent(value) {
112
112
  }
113
113
  return (nonEmptyString(value.text) ?? nonEmptyString(value.content) ?? nonEmptyString(value.output));
114
114
  }
115
+ // Claude's Read tool returns `cat -n`-style content: each line prefixed with a
116
+ // right-aligned line number and a tab (`␣␣␣1\timport ...`). Other providers
117
+ // return raw source. We strip the gutter here so `read.content` is uniformly
118
+ // raw source across providers, and surface the first line number as `offset`
119
+ // so the client can rebuild the gutter itself. Guarded tightly (first line must
120
+ // match, near-total match ratio, strictly sequential numbering) so real source
121
+ // is never mistaken for a gutter.
122
+ const READ_GUTTER_LINE = /^\s*(\d+)\t(.*)$/;
123
+ export function stripReadLineNumberGutter(content) {
124
+ const text = nonEmptyString(content);
125
+ if (!text) {
126
+ return undefined;
127
+ }
128
+ const lines = text.replace(/\r\n/g, "\n").split("\n");
129
+ const stripped = [];
130
+ let nonEmpty = 0;
131
+ let matched = 0;
132
+ let startLine;
133
+ let prevNumber;
134
+ let sequential = true;
135
+ let firstNonEmptyMatched = false;
136
+ let sawNonEmpty = false;
137
+ for (const line of lines) {
138
+ if (line.length === 0) {
139
+ stripped.push(line);
140
+ continue;
141
+ }
142
+ nonEmpty += 1;
143
+ const match = line.match(READ_GUTTER_LINE);
144
+ if (!match) {
145
+ if (!sawNonEmpty) {
146
+ return undefined;
147
+ }
148
+ stripped.push(line);
149
+ sawNonEmpty = true;
150
+ continue;
151
+ }
152
+ if (!sawNonEmpty) {
153
+ firstNonEmptyMatched = true;
154
+ }
155
+ sawNonEmpty = true;
156
+ matched += 1;
157
+ const lineNumber = Number.parseInt(match[1], 10);
158
+ if (startLine === undefined) {
159
+ startLine = lineNumber;
160
+ }
161
+ if (prevNumber !== undefined && lineNumber !== prevNumber + 1) {
162
+ sequential = false;
163
+ }
164
+ prevNumber = lineNumber;
165
+ stripped.push(match[2]);
166
+ }
167
+ if (!firstNonEmptyMatched || !sequential || nonEmpty === 0) {
168
+ return undefined;
169
+ }
170
+ // Sequential numbering from the first line is already a strong signal; the
171
+ // ratio only rejects source that has a couple of coincidental matches.
172
+ if (matched / nonEmpty < 0.5) {
173
+ return undefined;
174
+ }
175
+ return { content: stripped.join("\n"), startLine };
176
+ }
115
177
  export function truncateDiffText(text, maxChars = 12000) {
116
178
  if (typeof text !== "string") {
117
179
  return undefined;
@@ -0,0 +1,29 @@
1
+ import type { AgentProvider } from "./agent-sdk-types.js";
2
+ import type { StructuredGenerationProvider } from "./agent-response-loop.js";
3
+ import type { ProviderSnapshotManager } from "./provider-snapshot-manager.js";
4
+ export interface StructuredGenerationDaemonConfig {
5
+ metadataGeneration?: {
6
+ providers?: Array<{
7
+ provider: string;
8
+ model?: string;
9
+ thinkingOptionId?: string;
10
+ }>;
11
+ };
12
+ }
13
+ export interface StructuredGenerationProviderIdentifier {
14
+ modelSubstring: string;
15
+ thinkingOptionId?: string;
16
+ }
17
+ export declare const DEFAULT_STRUCTURED_GENERATION_PROVIDERS: readonly StructuredGenerationProviderIdentifier[];
18
+ export interface ResolveStructuredGenerationProvidersOptions {
19
+ cwd: string;
20
+ providerSnapshotManager: Pick<ProviderSnapshotManager, "listProviders">;
21
+ daemonConfig?: StructuredGenerationDaemonConfig | null;
22
+ currentSelection?: {
23
+ provider?: AgentProvider | null;
24
+ model?: string | null;
25
+ thinkingOptionId?: string | null;
26
+ };
27
+ }
28
+ export declare function resolveStructuredGenerationProviders(options: ResolveStructuredGenerationProvidersOptions): Promise<StructuredGenerationProvider[]>;
29
+ //# sourceMappingURL=structured-generation-providers.d.ts.map