pi-provider-kimi-code 0.6.2 → 0.6.5

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.
package/src/payload.ts CHANGED
@@ -6,7 +6,7 @@ import type { CacheRetention, ThinkingLevel } from "@earendil-works/pi-ai";
6
6
  import type { KimiResolvedModelConfig, ModelReasoningEntry } from "./config.ts";
7
7
 
8
8
  import { getBaseUrl } from "./constants.ts";
9
- import { getCommonHeaders } from "./device.ts";
9
+ import { getKimiProviderHeaders } from "./device.ts";
10
10
  import { optimizeToolSchemas } from "./schema-dedup.ts";
11
11
 
12
12
  // =============================================================================
@@ -116,7 +116,7 @@ export async function uploadKimiFile(
116
116
  try {
117
117
  const response = await fetch(uploadUrl, {
118
118
  method: "POST",
119
- headers: { Authorization: `Bearer ${apiKey}`, ...getCommonHeaders() },
119
+ headers: { ...getKimiProviderHeaders(), Authorization: `Bearer ${apiKey}` },
120
120
  body: formData,
121
121
  });
122
122
  if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
@@ -425,7 +425,19 @@ export async function applyKimiPayloadMutations(
425
425
  : { include_usage: true };
426
426
  }
427
427
 
428
- // 5. Normalize deprecated max_tokens (OpenAI path only — Anthropic
428
+ // 5. Spread extra_body into the top-level payload before normalization and
429
+ // config caps. Top-level fields retain precedence over extra_body.
430
+ if (isRecord(payload.extra_body)) {
431
+ const extraBody = payload.extra_body as JsonRecord;
432
+ delete payload.extra_body;
433
+ for (const [key, value] of Object.entries(extraBody)) {
434
+ if (payload[key] === undefined) {
435
+ payload[key] = value;
436
+ }
437
+ }
438
+ }
439
+
440
+ // 6. Normalize deprecated max_tokens (OpenAI path only — Anthropic
429
441
  // /messages uses max_tokens natively).
430
442
  if (ctx.api === "openai-completions") {
431
443
  if (payload.max_completion_tokens === undefined && typeof payload.max_tokens === "number") {
@@ -438,44 +450,45 @@ export async function applyKimiPayloadMutations(
438
450
  if (generation.temperature !== undefined) payload.temperature = generation.temperature;
439
451
  if (generation.topP !== undefined) payload.top_p = generation.topP;
440
452
  if (generation.maxCompletionTokens !== undefined) {
441
- payload.max_completion_tokens = generation.maxCompletionTokens;
453
+ const maxTokensKey = ctx.api === "anthropic-messages" ? "max_tokens" : "max_completion_tokens";
454
+ const currentMaxTokens = payload[maxTokensKey];
455
+ payload[maxTokensKey] =
456
+ typeof currentMaxTokens === "number"
457
+ ? Math.min(currentMaxTokens, generation.maxCompletionTokens)
458
+ : generation.maxCompletionTokens;
442
459
  }
443
460
 
444
- // 5. Spread extra_body into top-level payload before reasoning mapping,
445
- // matching upstream (Kimi expects thinking etc. at the root).
446
- if (isRecord(payload.extra_body)) {
447
- const extraBody = payload.extra_body as JsonRecord;
448
- delete payload.extra_body;
449
- for (const [key, value] of Object.entries(extraBody)) {
450
- if (payload[key] === undefined) {
451
- payload[key] = value;
452
- }
453
- }
461
+ // 7. Reasoning effort mapping. Kimi now accepts effort only inside the
462
+ // thinking object, and only for values advertised by the model catalog.
463
+ delete payload.reasoning_effort;
464
+ if (ctx.modelConfig.supportsThinkingType === "no") {
465
+ delete payload.thinking;
454
466
  }
455
-
456
- // 6. Reasoning effort mapping. Merges into any existing top-level thinking
457
- // field (which may have come from extra_body above).
458
467
  const resolvedReasoning = resolveThinkingLevel(ctx);
459
468
  if (resolvedReasoning) {
460
469
  const mapped = resolveReasoningForLevel(resolvedReasoning, ctx.modelConfig);
461
470
  if (mapped) {
462
- if (mapped.effort !== null) {
463
- payload.reasoning_effort = mapped.effort;
464
- } else {
465
- delete payload.reasoning_effort;
466
- }
467
471
  const oldThinking = isRecord(payload.thinking) ? payload.thinking : {};
468
- payload.thinking = {
472
+ const thinking: JsonRecord = {
469
473
  ...oldThinking,
470
474
  type: mapped.enabled ? "enabled" : "disabled",
471
475
  };
476
+ delete thinking.effort;
477
+ if (!mapped.enabled) delete thinking.keep;
478
+ const effort = ctx.reasoning
479
+ ? mapped.effort
480
+ : (ctx.modelConfig.defaultEffort ?? mapped.effort);
481
+ if (mapped.enabled && effort !== null && ctx.modelConfig.supportEfforts?.includes(effort)) {
482
+ thinking.effort = effort;
483
+ }
472
484
  if (mapped.enabled && ctx.modelConfig.thinkingKeep) {
473
- (payload.thinking as JsonRecord).keep = ctx.modelConfig.thinkingKeep;
485
+ thinking.keep = ctx.modelConfig.thinkingKeep;
474
486
  }
487
+ payload.thinking = thinking;
475
488
  }
476
489
  }
477
490
 
478
- // 7. K2.7 Code API constraints: the server rejects non-default values for
491
+ // 8. K2.7 Code API constraints: the server rejects non-default values for
479
492
  // temperature (must be 1.0) and top_p (must be 0.95), and tool_choice
480
493
  // "required" / function-specific when thinking is enabled (always-on).
481
494
  if (payload.temperature !== undefined && payload.temperature !== 1) {
@@ -0,0 +1,24 @@
1
+ export async function isKimiProjectConfigApproved(ctx: unknown, cwd: string): Promise<boolean> {
2
+ const check = (ctx as { isProjectTrusted?: () => boolean } | undefined)?.isProjectTrusted;
3
+ if (typeof check !== "function") return true;
4
+
5
+ let sessionTrusted: boolean;
6
+ try {
7
+ sessionTrusted = check.call(ctx);
8
+ } catch {
9
+ return false;
10
+ }
11
+ if (!sessionTrusted) return false;
12
+
13
+ const mod = (await import("@earendil-works/pi-coding-agent")) as unknown as {
14
+ ProjectTrustStore?: new (agentDir: string) => { get(cwd: string): boolean | null };
15
+ getAgentDir?: () => string;
16
+ };
17
+ if (!mod.ProjectTrustStore || !mod.getAgentDir) return true;
18
+
19
+ try {
20
+ return new mod.ProjectTrustStore(mod.getAgentDir()).get(cwd) === true;
21
+ } catch {
22
+ return false;
23
+ }
24
+ }
@@ -0,0 +1,204 @@
1
+ import os from "node:os";
2
+ import { relative } from "node:path";
3
+ import type { Theme } from "@earendil-works/pi-coding-agent";
4
+ import type { SettingsListTheme } from "@earendil-works/pi-tui";
5
+
6
+ import {
7
+ type KimiCodeConfig,
8
+ type KimiCodeConfigSources,
9
+ KIMI_TOOL_NAMES,
10
+ type KimiToolName,
11
+ getGlobalKimiCodeConfigPath,
12
+ getProjectKimiCodeConfigPath,
13
+ } from "./config.ts";
14
+ import { PROVIDER_VERSION } from "./constants.ts";
15
+ import type { KimiOAuthExtras } from "./models.ts";
16
+
17
+ export type KimiConfigScope = "project" | "home";
18
+
19
+ export function moonshotStatus(config: KimiCodeConfig): string {
20
+ return KIMI_TOOL_NAMES.map((toolName) => {
21
+ const tool = config.tools[toolName];
22
+ const enabled = tool.enabled ? "enabled" : "disabled";
23
+ const collapsed = tool.default_collapsed ? "collapsed" : "expanded";
24
+ return `${toolName}: ${enabled}, default ${collapsed}`;
25
+ }).join("\n");
26
+ }
27
+
28
+ export function toggleEnabled(config: KimiCodeConfig, toolName: KimiToolName): KimiCodeConfig {
29
+ return {
30
+ ...config,
31
+ tools: {
32
+ ...config.tools,
33
+ [toolName]: {
34
+ ...config.tools[toolName],
35
+ enabled: !config.tools[toolName].enabled,
36
+ },
37
+ },
38
+ };
39
+ }
40
+
41
+ export function toggleCollapsed(config: KimiCodeConfig, toolName: KimiToolName): KimiCodeConfig {
42
+ return {
43
+ ...config,
44
+ tools: {
45
+ ...config.tools,
46
+ [toolName]: {
47
+ ...config.tools[toolName],
48
+ default_collapsed: !config.tools[toolName].default_collapsed,
49
+ },
50
+ },
51
+ };
52
+ }
53
+
54
+ export function setProtocol(
55
+ config: KimiCodeConfig,
56
+ protocol: KimiCodeConfig["protocol"],
57
+ ): KimiCodeConfig {
58
+ return { ...config, protocol };
59
+ }
60
+
61
+ export function setUploadThreshold(config: KimiCodeConfig, thresholdBytes: number): KimiCodeConfig {
62
+ return { ...config, uploads: { ...config.uploads, thresholdBytes } };
63
+ }
64
+
65
+ export function buildKimiMainTitle(
66
+ config: KimiCodeConfig,
67
+ extras: KimiOAuthExtras,
68
+ sources: KimiCodeConfigSources,
69
+ ): string {
70
+ const modelName = extras.modelDisplay || "kimi-for-coding";
71
+ return [
72
+ `Kimi settings (provider v${PROVIDER_VERSION})`,
73
+ "",
74
+ `Model: ${modelName}`,
75
+ `Protocol: ${config.protocol} (${sources.protocol})`,
76
+ `Upload threshold: ${formatByteSize(config.uploads.thresholdBytes)} (${sources.uploads.thresholdBytes})`,
77
+ "",
78
+ "Effective tools:",
79
+ ...KIMI_TOOL_NAMES.map((toolName) => {
80
+ const enabled = config.tools[toolName].enabled ? "enabled" : "disabled";
81
+ return `- ${toolName}: ${enabled} (${sources.tools[toolName].enabled})`;
82
+ }),
83
+ ].join("\n");
84
+ }
85
+
86
+ export function buildConfigScopeTitle(
87
+ scope: KimiConfigScope,
88
+ config: KimiCodeConfig,
89
+ filePath: string,
90
+ ): string {
91
+ return [
92
+ `Edit ${scope} config`,
93
+ `File: ${filePath}`,
94
+ "",
95
+ formatProtocolStatus(config),
96
+ formatUploadThresholdStatus(config),
97
+ "",
98
+ moonshotStatus(config),
99
+ ].join("\n");
100
+ }
101
+
102
+ export function buildSettingsTheme(theme: Theme): SettingsListTheme {
103
+ return {
104
+ label: (text: string, selected: boolean) => (selected ? theme.fg("accent", text) : text),
105
+ value: (text: string, selected: boolean) =>
106
+ selected ? theme.bold(theme.fg("accent", text)) : theme.fg("muted", text),
107
+ description: (text: string) => theme.fg("dim", text),
108
+ cursor: theme.fg("accent", "> "),
109
+ hint: (text: string) => theme.fg("dim", text),
110
+ };
111
+ }
112
+
113
+ export function formatScopeDescription(
114
+ scope: KimiConfigScope,
115
+ cwd: string,
116
+ home = os.homedir(),
117
+ ): string {
118
+ const filePath =
119
+ scope === "project" ? getProjectKimiCodeConfigPath(cwd) : getGlobalKimiCodeConfigPath(home);
120
+ const displayPath = scope === "home" ? homeRelative(filePath, home) : relative(cwd, filePath);
121
+ return `Writes to the ${scope} config file: ${displayPath}`;
122
+ }
123
+
124
+ export function homeRelative(filePath: string, home = os.homedir()): string {
125
+ const normalizedHome = home.replace(/[\\/]+$/, "");
126
+ if (filePath === normalizedHome) return "~";
127
+
128
+ const slashPrefix = `${normalizedHome}/`;
129
+ if (filePath.startsWith(slashPrefix)) return `~/${filePath.slice(slashPrefix.length)}`;
130
+
131
+ const backslashPrefix = `${normalizedHome}\\`;
132
+ if (filePath.startsWith(backslashPrefix)) return `~\\${filePath.slice(backslashPrefix.length)}`;
133
+
134
+ return filePath;
135
+ }
136
+
137
+ export function toolMenuItem(config: KimiCodeConfig, toolName: KimiToolName): string {
138
+ return `${toolName} -> ${formatToolStatus(config, toolName)}`;
139
+ }
140
+
141
+ export function protocolMenuItem(config: KimiCodeConfig): string {
142
+ return `Protocol -> ${config.protocol}`;
143
+ }
144
+
145
+ export function uploadThresholdMenuItem(config: KimiCodeConfig): string {
146
+ return `Upload threshold -> ${formatByteSize(config.uploads.thresholdBytes)}`;
147
+ }
148
+
149
+ export function formatByteSize(bytes: number): string {
150
+ const units = [
151
+ { suffix: "GiB", size: 1024 ** 3 },
152
+ { suffix: "MiB", size: 1024 ** 2 },
153
+ { suffix: "KiB", size: 1024 },
154
+ ];
155
+ for (const unit of units) {
156
+ if (bytes >= unit.size && bytes % unit.size === 0) {
157
+ return `${bytes / unit.size} ${unit.suffix}`;
158
+ }
159
+ }
160
+ for (const unit of units) {
161
+ if (bytes >= unit.size) {
162
+ return `${(bytes / unit.size).toFixed(2).replace(/\.00$/, "")} ${unit.suffix}`;
163
+ }
164
+ }
165
+ return `${bytes} B`;
166
+ }
167
+
168
+ export function parseByteSizeInput(input: string): number | undefined {
169
+ const match = input.trim().match(/^(\d+(?:\.\d+)?)\s*(b|bytes?|kib|kb|mib|mb|gib|gb)?$/i);
170
+ if (!match) return undefined;
171
+ const value = Number(match[1]);
172
+ if (!Number.isFinite(value) || value <= 0) return undefined;
173
+ const unit = (match[2] ?? "mib").toLowerCase();
174
+ const multipliers: Record<string, number> = {
175
+ b: 1,
176
+ byte: 1,
177
+ bytes: 1,
178
+ kib: 1024,
179
+ kb: 1000,
180
+ mib: 1024 ** 2,
181
+ mb: 1000 ** 2,
182
+ gib: 1024 ** 3,
183
+ gb: 1000 ** 3,
184
+ };
185
+ const multiplier = multipliers[unit];
186
+ if (!multiplier) return undefined;
187
+ const bytes = Math.round(value * multiplier);
188
+ return Number.isSafeInteger(bytes) && bytes > 0 ? bytes : undefined;
189
+ }
190
+
191
+ export function formatProtocolStatus(config: KimiCodeConfig): string {
192
+ return `protocol: ${config.protocol}`;
193
+ }
194
+
195
+ export function formatUploadThresholdStatus(config: KimiCodeConfig): string {
196
+ return `upload threshold: ${formatByteSize(config.uploads.thresholdBytes)}`;
197
+ }
198
+
199
+ export function formatToolStatus(config: KimiCodeConfig, toolName: KimiToolName): string {
200
+ const tool = config.tools[toolName];
201
+ const enabled = tool.enabled ? "enabled" : "disabled";
202
+ const collapsed = tool.default_collapsed ? "default collapsed" : "default expanded";
203
+ return `${enabled}, ${collapsed}`;
204
+ }
package/src/stream.ts CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  } from "./config.ts";
25
25
 
26
26
  import { ENV_KIMI_CODE_PROTOCOL, getApiProtocol, getBaseUrl } from "./constants.ts";
27
- import { getCommonHeaders } from "./device.ts";
27
+ import { getKimiProviderHeaders } from "./device.ts";
28
28
  import { isKimiAuthErrorMessage, refreshKimiAuthToken } from "./oauth.ts";
29
29
  import {
30
30
  type Uploader,
@@ -163,7 +163,7 @@ export function resolveKimiApiKey(apiKey: string | undefined): string {
163
163
  }
164
164
 
165
165
  export function mergeKimiRequestHeaders(headers?: Record<string, string>): Record<string, string> {
166
- return { ...getCommonHeaders(), ...headers };
166
+ return { ...getKimiProviderHeaders(), ...headers };
167
167
  }
168
168
 
169
169
  export function streamSimpleKimi(
@@ -192,8 +192,27 @@ export function streamSimpleKimi(
192
192
  protocol: ENV_KIMI_CODE_PROTOCOL,
193
193
  uploads: DEFAULT_KIMI_CODE_CONFIG.uploads,
194
194
  };
195
- const modelConfig = streamConfig.model;
196
- const apiProtocol = getApiProtocol(streamConfig.protocol);
195
+ const discoveredModel = model as Model<Api> & {
196
+ supportsThinkingType?: "only" | "no" | "both";
197
+ wireProtocol?: KimiCodeConfig["protocol"];
198
+ supportEfforts?: string[];
199
+ defaultEffort?: string;
200
+ };
201
+ const modelConfig: KimiResolvedModelConfig = {
202
+ ...streamConfig.model,
203
+ contextWindow: model.contextWindow,
204
+ maxTokens: model.maxTokens,
205
+ input: [...model.input],
206
+ reasoning: model.reasoning,
207
+ supportsThinkingType:
208
+ discoveredModel.supportsThinkingType ?? (model.reasoning ? undefined : "no"),
209
+ supportEfforts: discoveredModel.supportEfforts
210
+ ? [...discoveredModel.supportEfforts]
211
+ : undefined,
212
+ defaultEffort: discoveredModel.defaultEffort,
213
+ };
214
+ const wireProtocol = discoveredModel.wireProtocol ?? streamConfig.protocol;
215
+ const apiProtocol = getApiProtocol(wireProtocol);
197
216
  const originalOnPayload = options?.onPayload;
198
217
  // The pi-side model id ("kimi-for-coding") is what users select via /model
199
218
  // and what gets persisted into sessions. The wire model id discovered at
@@ -257,10 +276,10 @@ export function streamSimpleKimi(
257
276
  const runtimeModel = {
258
277
  ...model,
259
278
  api: apiProtocol,
260
- baseUrl: getBaseUrl(streamConfig.protocol),
279
+ baseUrl: getBaseUrl(wireProtocol),
261
280
  } as Model<Api>;
262
281
  const upstream =
263
- streamConfig.protocol === "openai"
282
+ wireProtocol === "openai"
264
283
  ? streamSimpleOpenAICompletions(
265
284
  runtimeModel as Model<"openai-completions">,
266
285
  context,
@@ -2,8 +2,8 @@ import { AuthStorage, type AgentToolResult } from "@earendil-works/pi-coding-age
2
2
  import { truncateToWidth } from "@earendil-works/pi-tui";
3
3
 
4
4
  import { PROVIDER_ID, getBaseUrl } from "../constants.ts";
5
- import { getCommonHeaders } from "../device.ts";
6
- import { refreshKimiAuthToken } from "../oauth.ts";
5
+ import { getKimiProviderHeaders } from "../device.ts";
6
+ import { KIMI_LOGIN_REQUIRED_MESSAGE, refreshKimiAuthToken } from "../oauth.ts";
7
7
 
8
8
  export const KIMI_TOOL_TIMEOUT_MS = 180_000;
9
9
 
@@ -67,7 +67,7 @@ export function getKimiDatasourceUrl(): string {
67
67
 
68
68
  export function buildHeaders(accessToken: string, toolCallId: string): Record<string, string> {
69
69
  return {
70
- ...getCommonHeaders(),
70
+ ...getKimiProviderHeaders(),
71
71
  Authorization: `Bearer ${accessToken}`,
72
72
  "Content-Type": "application/json",
73
73
  "X-Msh-Tool-Call-Id": toolCallId,
@@ -94,7 +94,9 @@ export async function fetchWithAuthRetry(
94
94
  if (response.status !== 401) return response;
95
95
 
96
96
  const refreshed = await deps.refreshAccessToken(accessToken);
97
- if (!refreshed || refreshed === accessToken) return response;
97
+ if (!refreshed || refreshed === accessToken) {
98
+ throw new Error(KIMI_LOGIN_REQUIRED_MESSAGE);
99
+ }
98
100
  return request(refreshed);
99
101
  }
100
102
 
@@ -17,20 +17,6 @@ import {
17
17
 
18
18
  export const moonshotSearchSchema = Type.Object({
19
19
  query: Type.String({ description: "The query text to search for." }),
20
- limit: Type.Optional(
21
- Type.Number({
22
- description: "The number of results to return.",
23
- default: 5,
24
- minimum: 1,
25
- maximum: 20,
26
- }),
27
- ),
28
- include_content: Type.Optional(
29
- Type.Boolean({
30
- description: "Whether to include fetched page content in the search results.",
31
- default: false,
32
- }),
33
- ),
34
20
  });
35
21
 
36
22
  export const moonshotFetchSchema = Type.Object({
@@ -44,7 +30,8 @@ export interface MoonshotSearchResult {
44
30
  url: string;
45
31
  title: string;
46
32
  snippet: string;
47
- content?: string;
33
+ date?: string;
34
+ siteName?: string;
48
35
  }
49
36
 
50
37
  export interface MoonshotFetchResult {
@@ -52,11 +39,6 @@ export interface MoonshotFetchResult {
52
39
  content: string;
53
40
  }
54
41
 
55
- function clampLimit(value: number | undefined): number {
56
- if (typeof value !== "number" || !Number.isFinite(value)) return 5;
57
- return Math.max(1, Math.min(20, Math.trunc(value)));
58
- }
59
-
60
42
  interface MoonshotSearchResponse {
61
43
  search_results?: unknown;
62
44
  }
@@ -66,7 +48,7 @@ function stringField(record: Record<string, unknown>, key: string): string {
66
48
  return typeof value === "string" ? value : "";
67
49
  }
68
50
 
69
- function mapSearchResults(value: unknown, includeContent: boolean): MoonshotSearchResult[] {
51
+ function mapSearchResults(value: unknown): MoonshotSearchResult[] {
70
52
  if (!Array.isArray(value)) return [];
71
53
  return value
72
54
  .filter((item): item is Record<string, unknown> => typeof item === "object" && item !== null)
@@ -76,9 +58,10 @@ function mapSearchResults(value: unknown, includeContent: boolean): MoonshotSear
76
58
  title: stringField(item, "title"),
77
59
  snippet: stringField(item, "snippet"),
78
60
  };
79
- if (includeContent) {
80
- result.content = stringField(item, "content");
81
- }
61
+ const date = stringField(item, "date");
62
+ if (date) result.date = date;
63
+ const siteName = stringField(item, "site_name");
64
+ if (siteName) result.siteName = siteName;
82
65
  return result;
83
66
  });
84
67
  }
@@ -130,8 +113,10 @@ export function buildMoonshotSearchTool(options: BuildKimiToolOptions = {}) {
130
113
  return defineTool({
131
114
  name: "moonshot_search",
132
115
  label: "Moonshot Search",
133
- description: "Search the web through Kimi Coding's server-side Moonshot search service.",
134
- promptSnippet: "Search the web with Kimi Coding's Moonshot search service",
116
+ description:
117
+ "Search the web through Kimi Coding. Results are summaries; use moonshot_fetch to read relevant pages.",
118
+ promptSnippet:
119
+ "Search the web with Kimi Coding, then fetch the few relevant result URLs before answering",
135
120
  parameters: moonshotSearchSchema,
136
121
 
137
122
  async execute(toolCallId, params, signal) {
@@ -142,20 +127,13 @@ export function buildMoonshotSearchTool(options: BuildKimiToolOptions = {}) {
142
127
  );
143
128
  }
144
129
 
145
- const limit = clampLimit(params.limit);
146
- const includeContent = params.include_content === true;
147
130
  const timeout = buildTimeoutSignal(signal);
148
131
  try {
149
132
  const response = await fetchWithAuthRetry(deps, accessToken, (token) =>
150
133
  deps.fetch(`${getKimiBaseV1()}/search`, {
151
134
  method: "POST",
152
135
  headers: buildHeaders(token, toolCallId),
153
- body: JSON.stringify({
154
- text_query: params.query,
155
- limit,
156
- enable_page_crawling: includeContent,
157
- timeout_seconds: 30,
158
- }),
136
+ body: JSON.stringify({ text_query: params.query }),
159
137
  signal: timeout.signal,
160
138
  }),
161
139
  );
@@ -168,7 +146,7 @@ export function buildMoonshotSearchTool(options: BuildKimiToolOptions = {}) {
168
146
  }
169
147
 
170
148
  const data = (await response.json()) as MoonshotSearchResponse;
171
- const results = mapSearchResults(data.search_results, includeContent);
149
+ const results = mapSearchResults(data.search_results);
172
150
  return {
173
151
  content: [{ type: "text", text: searchResultsText(results) }],
174
152
  details: results,