@oh-my-pi/pi-coding-agent 11.0.3 → 11.2.0

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 (143) hide show
  1. package/CHANGELOG.md +199 -49
  2. package/README.md +1 -1
  3. package/docs/config-usage.md +3 -4
  4. package/docs/sdk.md +6 -5
  5. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  6. package/examples/sdk/README.md +1 -1
  7. package/package.json +19 -11
  8. package/src/cli/args.ts +11 -94
  9. package/src/cli/config-cli.ts +1 -1
  10. package/src/cli/file-processor.ts +3 -3
  11. package/src/cli/oclif-help.ts +26 -0
  12. package/src/cli/web-search-cli.ts +148 -0
  13. package/src/cli.ts +8 -2
  14. package/src/commands/commit.ts +36 -0
  15. package/src/commands/config.ts +51 -0
  16. package/src/commands/grep.ts +41 -0
  17. package/src/commands/index/index.ts +136 -0
  18. package/src/commands/jupyter.ts +32 -0
  19. package/src/commands/plugin.ts +70 -0
  20. package/src/commands/setup.ts +39 -0
  21. package/src/commands/shell.ts +29 -0
  22. package/src/commands/stats.ts +29 -0
  23. package/src/commands/update.ts +21 -0
  24. package/src/commands/web-search.ts +50 -0
  25. package/src/commit/agentic/index.ts +3 -2
  26. package/src/commit/agentic/tools/analyze-file.ts +1 -3
  27. package/src/commit/git/errors.ts +4 -6
  28. package/src/commit/pipeline.ts +3 -2
  29. package/src/config/keybindings.ts +1 -3
  30. package/src/config/model-registry.ts +89 -162
  31. package/src/config/settings-schema.ts +10 -0
  32. package/src/config.ts +202 -132
  33. package/src/exa/mcp-client.ts +8 -41
  34. package/src/export/html/index.ts +1 -1
  35. package/src/extensibility/extensions/loader.ts +7 -10
  36. package/src/extensibility/extensions/runner.ts +5 -15
  37. package/src/extensibility/extensions/types.ts +1 -1
  38. package/src/extensibility/hooks/runner.ts +6 -9
  39. package/src/index.ts +0 -1
  40. package/src/ipy/kernel.ts +10 -22
  41. package/src/lsp/clients/biome-client.ts +4 -7
  42. package/src/lsp/clients/lsp-linter-client.ts +4 -6
  43. package/src/lsp/index.ts +5 -4
  44. package/src/lsp/utils.ts +18 -0
  45. package/src/main.ts +86 -181
  46. package/src/mcp/json-rpc.ts +2 -2
  47. package/src/mcp/transports/http.ts +12 -49
  48. package/src/modes/components/armin.ts +1 -3
  49. package/src/modes/components/assistant-message.ts +4 -4
  50. package/src/modes/components/bash-execution.ts +5 -3
  51. package/src/modes/components/branch-summary-message.ts +1 -3
  52. package/src/modes/components/compaction-summary-message.ts +1 -3
  53. package/src/modes/components/custom-message.ts +4 -5
  54. package/src/modes/components/extensions/extension-dashboard.ts +10 -16
  55. package/src/modes/components/extensions/extension-list.ts +5 -5
  56. package/src/modes/components/footer.ts +1 -4
  57. package/src/modes/components/hook-editor.ts +7 -32
  58. package/src/modes/components/hook-message.ts +4 -5
  59. package/src/modes/components/model-selector.ts +2 -2
  60. package/src/modes/components/plugin-settings.ts +16 -20
  61. package/src/modes/components/python-execution.ts +5 -5
  62. package/src/modes/components/session-selector.ts +6 -7
  63. package/src/modes/components/settings-defs.ts +49 -40
  64. package/src/modes/components/settings-selector.ts +8 -17
  65. package/src/modes/components/skill-message.ts +1 -3
  66. package/src/modes/components/status-line-segment-editor.ts +1 -3
  67. package/src/modes/components/status-line.ts +1 -3
  68. package/src/modes/components/todo-reminder.ts +5 -7
  69. package/src/modes/components/tree-selector.ts +10 -12
  70. package/src/modes/components/ttsr-notification.ts +1 -3
  71. package/src/modes/components/user-message-selector.ts +2 -4
  72. package/src/modes/components/welcome.ts +6 -18
  73. package/src/modes/controllers/event-controller.ts +1 -0
  74. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  75. package/src/modes/controllers/input-controller.ts +7 -34
  76. package/src/modes/controllers/selector-controller.ts +3 -3
  77. package/src/modes/interactive-mode.ts +27 -1
  78. package/src/modes/rpc/rpc-client.ts +2 -5
  79. package/src/modes/rpc/rpc-mode.ts +2 -2
  80. package/src/modes/theme/theme.ts +2 -6
  81. package/src/modes/types.ts +1 -0
  82. package/src/modes/utils/ui-helpers.ts +6 -1
  83. package/src/patch/index.ts +1 -4
  84. package/src/prompts/agents/explore.md +1 -0
  85. package/src/prompts/agents/frontmatter.md +2 -1
  86. package/src/prompts/agents/init.md +1 -0
  87. package/src/prompts/agents/plan.md +1 -0
  88. package/src/prompts/agents/reviewer.md +1 -0
  89. package/src/prompts/system/subagent-submit-reminder.md +2 -0
  90. package/src/prompts/system/subagent-system-prompt.md +2 -0
  91. package/src/prompts/system/subagent-user-prompt.md +8 -0
  92. package/src/prompts/system/system-prompt.md +5 -3
  93. package/src/prompts/system/web-search.md +6 -4
  94. package/src/prompts/tools/task.md +216 -163
  95. package/src/sdk.ts +11 -110
  96. package/src/session/agent-session.ts +117 -83
  97. package/src/session/auth-storage.ts +10 -51
  98. package/src/session/messages.ts +17 -3
  99. package/src/session/session-manager.ts +30 -30
  100. package/src/session/streaming-output.ts +1 -1
  101. package/src/ssh/ssh-executor.ts +6 -3
  102. package/src/task/agents.ts +2 -0
  103. package/src/task/discovery.ts +1 -1
  104. package/src/task/executor.ts +5 -10
  105. package/src/task/index.ts +43 -23
  106. package/src/task/render.ts +67 -64
  107. package/src/task/template.ts +17 -34
  108. package/src/task/types.ts +49 -22
  109. package/src/tools/ask.ts +1 -3
  110. package/src/tools/bash.ts +1 -4
  111. package/src/tools/browser.ts +5 -7
  112. package/src/tools/exit-plan-mode.ts +1 -4
  113. package/src/tools/fetch.ts +1 -3
  114. package/src/tools/find.ts +4 -3
  115. package/src/tools/gemini-image.ts +24 -55
  116. package/src/tools/grep.ts +4 -4
  117. package/src/tools/index.ts +12 -14
  118. package/src/tools/notebook.ts +1 -5
  119. package/src/tools/python.ts +4 -3
  120. package/src/tools/read.ts +2 -4
  121. package/src/tools/render-utils.ts +23 -0
  122. package/src/tools/ssh.ts +8 -12
  123. package/src/tools/todo-write.ts +1 -4
  124. package/src/tools/tool-errors.ts +1 -4
  125. package/src/tools/write.ts +1 -3
  126. package/src/utils/external-editor.ts +59 -0
  127. package/src/utils/file-mentions.ts +39 -1
  128. package/src/utils/image-convert.ts +1 -1
  129. package/src/utils/image-resize.ts +4 -4
  130. package/src/web/search/auth.ts +3 -33
  131. package/src/web/search/index.ts +73 -139
  132. package/src/web/search/provider.ts +58 -0
  133. package/src/web/search/providers/anthropic.ts +53 -14
  134. package/src/web/search/providers/base.ts +22 -0
  135. package/src/web/search/providers/codex.ts +38 -16
  136. package/src/web/search/providers/exa.ts +30 -6
  137. package/src/web/search/providers/gemini.ts +56 -20
  138. package/src/web/search/providers/jina.ts +28 -5
  139. package/src/web/search/providers/perplexity.ts +103 -36
  140. package/src/web/search/render.ts +84 -74
  141. package/src/web/search/types.ts +285 -59
  142. package/src/migrations.ts +0 -175
  143. package/src/session/storage-migration.ts +0 -173
@@ -3,8 +3,10 @@
3
3
  *
4
4
  * Tree-based rendering with collapsed/expanded states for web search results.
5
5
  */
6
+
7
+ import { getSearchProvider } from "@oh-my-pi/pi-coding-agent/web/search/provider";
6
8
  import type { Component } from "@oh-my-pi/pi-tui";
7
- import { Text } from "@oh-my-pi/pi-tui";
9
+ import { Text, visibleWidth, wrapTextWithAnsi } from "@oh-my-pi/pi-tui";
8
10
  import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
9
11
  import type { Theme } from "../../modes/theme/theme";
10
12
  import {
@@ -20,7 +22,7 @@ import {
20
22
  truncateToWidth,
21
23
  } from "../../tools/render-utils";
22
24
  import { renderOutputBlock, renderStatusLine, renderTreeList } from "../../tui";
23
- import type { WebSearchResponse } from "./types";
25
+ import type { SearchResponse } from "./types";
24
26
 
25
27
  const MAX_COLLAPSED_ANSWER_LINES = PREVIEW_LIMITS.COLLAPSED_LINES;
26
28
  const MAX_EXPANDED_ANSWER_LINES = PREVIEW_LIMITS.EXPANDED_LINES;
@@ -60,17 +62,22 @@ function renderFallbackText(contentText: string, expanded: boolean, theme: Theme
60
62
  return new Text(text, 0, 0);
61
63
  }
62
64
 
63
- export interface WebSearchRenderDetails {
64
- response: WebSearchResponse;
65
+ export interface SearchRenderDetails {
66
+ response: SearchResponse;
65
67
  error?: string;
66
68
  }
67
69
 
68
70
  /** Render web search result with tree-based layout */
69
- export function renderWebSearchResult(
70
- result: { content: Array<{ type: string; text?: string }>; details?: WebSearchRenderDetails },
71
+ export function renderSearchResult(
72
+ result: { content: Array<{ type: string; text?: string }>; details?: SearchRenderDetails },
71
73
  options: RenderResultOptions,
72
74
  theme: Theme,
73
- args?: { query?: string; provider?: string },
75
+ args?: {
76
+ query?: string;
77
+ provider?: string;
78
+ allowLongAnswer?: boolean;
79
+ maxAnswerLines?: number;
80
+ },
74
81
  ): Component {
75
82
  const { expanded } = options;
76
83
  const details = result.details;
@@ -90,10 +97,6 @@ export function renderWebSearchResult(
90
97
  const sourceCount = sources.length;
91
98
  const citations = Array.isArray(response.citations) ? response.citations : [];
92
99
  const citationCount = citations.length;
93
- const related = Array.isArray(response.relatedQuestions)
94
- ? response.relatedQuestions.filter(item => typeof item === "string")
95
- : [];
96
- const relatedCount = related.length;
97
100
  const searchQueries = Array.isArray(response.searchQueries)
98
101
  ? response.searchQueries.filter(item => typeof item === "string")
99
102
  : [];
@@ -102,20 +105,21 @@ export function renderWebSearchResult(
102
105
  // Get answer text
103
106
  const answerText = typeof response.answer === "string" ? response.answer.trim() : "";
104
107
  const contentText = answerText || rawText;
105
- const totalAnswerLines = contentText ? contentText.split("\n").filter(l => l.trim()).length : 0;
108
+ const answerLines = contentText
109
+ ? contentText
110
+ .split("\n")
111
+ .filter(l => l.trim())
112
+ .map(l => l.trim())
113
+ : [];
114
+ const totalAnswerLines = answerLines.length;
106
115
  const answerLimit = expanded ? MAX_EXPANDED_ANSWER_LINES : MAX_COLLAPSED_ANSWER_LINES;
107
- const answerPreview = contentText ? getPreviewLines(contentText, answerLimit, MAX_ANSWER_LINE_LEN) : [];
116
+ const answerPreview = contentText
117
+ ? args?.allowLongAnswer
118
+ ? answerLines.slice(0, args.maxAnswerLines ?? answerLines.length)
119
+ : getPreviewLines(contentText, answerLimit, MAX_ANSWER_LINE_LEN)
120
+ : [];
108
121
 
109
- const providerLabel =
110
- provider === "anthropic"
111
- ? "Anthropic"
112
- : provider === "perplexity"
113
- ? "Perplexity"
114
- : provider === "exa"
115
- ? "Exa"
116
- : provider === "jina"
117
- ? "Jina"
118
- : "Unknown";
122
+ const providerLabel = provider !== "none" ? getSearchProvider(provider).label : "None";
119
123
  const queryPreview = args?.query
120
124
  ? truncateToWidth(args.query, 80)
121
125
  : searchQueries[0]
@@ -132,20 +136,6 @@ export function renderWebSearchResult(
132
136
  );
133
137
 
134
138
  const remainingAnswer = totalAnswerLines - answerPreview.length;
135
- const answerLines = answerPreview.length > 0 ? answerPreview : ["No answer text returned"];
136
- const answerTree = renderTreeList(
137
- {
138
- items: answerLines,
139
- expanded: true,
140
- maxCollapsed: answerLines.length,
141
- itemType: "line",
142
- renderItem: line => (line === "No answer text returned" ? theme.fg("muted", line) : theme.fg("dim", line)),
143
- },
144
- theme,
145
- );
146
- if (remainingAnswer > 0) {
147
- answerTree.push(theme.fg("muted", formatMoreItems(remainingAnswer, "line")));
148
- }
149
139
 
150
140
  const sourceTree = renderTreeList(
151
141
  {
@@ -185,28 +175,12 @@ export function renderWebSearchResult(
185
175
  theme,
186
176
  );
187
177
 
188
- const relatedLines = related.length > 0 ? related : ["No related questions"];
189
- const relatedTree = renderTreeList(
190
- {
191
- items: relatedLines,
192
- expanded,
193
- maxCollapsed: MAX_COLLAPSED_ITEMS,
194
- itemType: "question",
195
- renderItem: line => theme.fg("muted", line === "No related questions" ? line : `${theme.format.dash} ${line}`),
196
- },
197
- theme,
198
- );
199
- if (!expanded && relatedCount > MAX_COLLAPSED_ITEMS) {
200
- relatedTree.push(theme.fg("muted", formatMoreItems(relatedCount - MAX_COLLAPSED_ITEMS, "question")));
201
- }
202
-
203
178
  const metaLines: string[] = [];
204
179
  metaLines.push(`${theme.fg("muted", "Provider:")} ${theme.fg("text", providerLabel)}`);
205
180
  if (response.model) metaLines.push(`${theme.fg("muted", "Model:")} ${theme.fg("text", response.model)}`);
206
181
  metaLines.push(`${theme.fg("muted", "Sources:")} ${theme.fg("text", String(sourceCount))}`);
207
182
  if (citationCount > 0)
208
183
  metaLines.push(`${theme.fg("muted", "Citations:")} ${theme.fg("text", String(citationCount))}`);
209
- if (relatedCount > 0) metaLines.push(`${theme.fg("muted", "Related:")} ${theme.fg("text", String(relatedCount))}`);
210
184
  if (response.usage) {
211
185
  const usageParts: string[] = [];
212
186
  if (response.usage.inputTokens !== undefined) usageParts.push(`in ${response.usage.inputTokens}`);
@@ -228,30 +202,66 @@ export function renderWebSearchResult(
228
202
  metaLines.push(`${theme.fg("muted", "Queries:")} ${theme.fg("text", queryList.join("; "))}${suffix}`);
229
203
  }
230
204
 
231
- const sections = [
232
- ...(queryPreview
233
- ? [
234
- {
235
- lines: [`${theme.fg("muted", "Query:")} ${theme.fg("text", queryPreview)}`],
236
- },
237
- ]
238
- : []),
239
- { label: theme.fg("toolTitle", "Answer"), lines: answerTree },
240
- {
241
- label: theme.fg("toolTitle", "Sources"),
242
- lines: sourceTree.length > 0 ? sourceTree : [theme.fg("muted", "No sources returned")],
243
- },
244
- { label: theme.fg("toolTitle", "Related"), lines: relatedTree },
245
- { label: theme.fg("toolTitle", "Metadata"), lines: metaLines },
246
- ];
247
-
248
205
  return {
249
206
  render: (width: number) =>
250
207
  renderOutputBlock(
251
208
  {
252
209
  header,
253
210
  state: sourceCount > 0 ? "success" : "warning",
254
- sections,
211
+ sections: [
212
+ ...(queryPreview
213
+ ? [
214
+ {
215
+ lines: [`${theme.fg("muted", "Query:")} ${theme.fg("text", queryPreview)}`],
216
+ },
217
+ ]
218
+ : []),
219
+ {
220
+ label: theme.fg("toolTitle", "Answer"),
221
+ lines: (() => {
222
+ const state = sourceCount > 0 ? "success" : "warning";
223
+ const borderColor: "warning" | "dim" = state === "warning" ? "warning" : "dim";
224
+ const border = (text: string) => theme.fg(borderColor, text);
225
+ const contentPrefix = border(`${theme.boxSharp.vertical} `);
226
+ const contentSuffix = border(theme.boxSharp.vertical);
227
+ const contentWidth = Math.max(
228
+ 0,
229
+ width - visibleWidth(contentPrefix) - visibleWidth(contentSuffix),
230
+ );
231
+ const answerTreeLines = answerPreview.length > 0 ? answerPreview : ["No answer text returned"];
232
+ const answerTree = renderTreeList(
233
+ {
234
+ items: answerTreeLines,
235
+ expanded: true,
236
+ maxCollapsed: answerTreeLines.length,
237
+ itemType: "line",
238
+ renderItem: (line, context) => {
239
+ const coloredLine =
240
+ line === "No answer text returned"
241
+ ? theme.fg("muted", line)
242
+ : theme.fg("dim", line);
243
+ if (!args?.allowLongAnswer) {
244
+ return coloredLine;
245
+ }
246
+ const prefixWidth = visibleWidth(context.continuePrefix);
247
+ const wrapWidth = Math.max(10, contentWidth - prefixWidth);
248
+ return wrapTextWithAnsi(coloredLine, wrapWidth);
249
+ },
250
+ },
251
+ theme,
252
+ );
253
+ if (remainingAnswer > 0) {
254
+ answerTree.push(theme.fg("muted", formatMoreItems(remainingAnswer, "line")));
255
+ }
256
+ return answerTree;
257
+ })(),
258
+ },
259
+ {
260
+ label: theme.fg("toolTitle", "Sources"),
261
+ lines: sourceTree.length > 0 ? sourceTree : [theme.fg("muted", "No sources returned")],
262
+ },
263
+ { label: theme.fg("toolTitle", "Metadata"), lines: metaLines },
264
+ ],
255
265
  width,
256
266
  },
257
267
  theme,
@@ -261,7 +271,7 @@ export function renderWebSearchResult(
261
271
  }
262
272
 
263
273
  /** Render web search call (query preview) */
264
- export function renderWebSearchCall(
274
+ export function renderSearchCall(
265
275
  args: { query: string; provider?: string; [key: string]: unknown },
266
276
  theme: Theme,
267
277
  ): Component {
@@ -272,7 +282,7 @@ export function renderWebSearchCall(
272
282
  }
273
283
 
274
284
  export const webSearchToolRenderer = {
275
- renderCall: renderWebSearchCall,
276
- renderResult: renderWebSearchResult,
285
+ renderCall: renderSearchCall,
286
+ renderResult: renderSearchResult,
277
287
  mergeCallAndResult: true,
278
288
  };
@@ -5,10 +5,10 @@
5
5
  */
6
6
 
7
7
  /** Supported web search providers */
8
- export type WebSearchProvider = "exa" | "jina" | "anthropic" | "perplexity" | "gemini" | "codex";
8
+ export type SearchProviderId = "exa" | "jina" | "anthropic" | "perplexity" | "gemini" | "codex";
9
9
 
10
10
  /** Source returned by search (all providers) */
11
- export interface WebSearchSource {
11
+ export interface SearchSource {
12
12
  title: string;
13
13
  url: string;
14
14
  snippet?: string;
@@ -20,14 +20,14 @@ export interface WebSearchSource {
20
20
  }
21
21
 
22
22
  /** Citation with text reference (anthropic, perplexity) */
23
- export interface WebSearchCitation {
23
+ export interface SearchCitation {
24
24
  url: string;
25
25
  title: string;
26
26
  citedText?: string;
27
27
  }
28
28
 
29
29
  /** Usage metrics */
30
- export interface WebSearchUsage {
30
+ export interface SearchUsage {
31
31
  inputTokens?: number;
32
32
  outputTokens?: number;
33
33
  /** Anthropic: number of web search requests made */
@@ -37,20 +37,20 @@ export interface WebSearchUsage {
37
37
  }
38
38
 
39
39
  /** Unified response across providers */
40
- export interface WebSearchResponse {
41
- provider: WebSearchProvider;
40
+ export interface SearchResponse {
41
+ provider: SearchProviderId | "none";
42
42
  /** Synthesized answer text (anthropic, perplexity) */
43
43
  answer?: string;
44
44
  /** Search result sources */
45
- sources: WebSearchSource[];
45
+ sources: SearchSource[];
46
46
  /** Text citations with context */
47
- citations?: WebSearchCitation[];
48
- /** Follow-up questions (perplexity) */
49
- relatedQuestions?: string[];
47
+ citations?: SearchCitation[];
50
48
  /** Intermediate search queries (anthropic) */
51
49
  searchQueries?: string[];
50
+ /** Follow-up question suggestions (provider-dependent) */
51
+ relatedQuestions?: string[];
52
52
  /** Token usage metrics */
53
- usage?: WebSearchUsage;
53
+ usage?: SearchUsage;
54
54
  /** Model used */
55
55
  model?: string;
56
56
  /** Request ID for debugging */
@@ -58,15 +58,14 @@ export interface WebSearchResponse {
58
58
  }
59
59
 
60
60
  /** Provider-specific error with optional HTTP status */
61
- export class WebSearchProviderError extends Error {
62
- provider: WebSearchProvider;
63
- status?: number;
64
-
65
- constructor(provider: WebSearchProvider, message: string, status?: number) {
61
+ export class SearchProviderError extends Error {
62
+ constructor(
63
+ public readonly provider: SearchProviderId,
64
+ message: string,
65
+ public readonly status?: number,
66
+ ) {
66
67
  super(message);
67
- this.name = "WebSearchProviderError";
68
- this.provider = provider;
69
- this.status = status;
68
+ this.name = "SearchProviderError";
70
69
  }
71
70
  }
72
71
 
@@ -89,7 +88,7 @@ export interface ModelsJson {
89
88
  >;
90
89
  }
91
90
 
92
- /** auth.json structure for OAuth credentials */
91
+ /** OAuth credential for Anthropic API access */
93
92
  export interface AnthropicOAuthCredential {
94
93
  type: "oauth";
95
94
  access: string;
@@ -98,14 +97,8 @@ export interface AnthropicOAuthCredential {
98
97
  expires: number;
99
98
  }
100
99
 
101
- export type AnthropicAuthJsonEntry = AnthropicOAuthCredential | AnthropicOAuthCredential[];
102
-
103
- export interface AuthJson {
104
- anthropic?: AnthropicAuthJsonEntry;
105
- }
106
-
107
100
  /** Anthropic API response types */
108
- export interface AnthropicWebSearchResult {
101
+ export interface AnthropicSearchResult {
109
102
  type: "web_search_result";
110
103
  title: string;
111
104
  url: string;
@@ -132,7 +125,7 @@ export interface AnthropicContentBlock {
132
125
  /** Tool input (for type="server_tool_use") */
133
126
  input?: { query: string };
134
127
  /** Search results (for type="web_search_tool_result") */
135
- content?: AnthropicWebSearchResult[];
128
+ content?: AnthropicSearchResult[];
136
129
  }
137
130
 
138
131
  export interface AnthropicApiResponse {
@@ -149,51 +142,284 @@ export interface AnthropicApiResponse {
149
142
  }
150
143
 
151
144
  /** Perplexity API types */
152
- export interface PerplexityMessage {
153
- role: "system" | "user" | "assistant";
154
- content: string;
145
+ export type PerplexityChatMessageRole = "system" | "user" | "assistant" | "tool";
146
+
147
+ export interface PerplexityUrl {
148
+ url: string;
149
+ }
150
+
151
+ export interface PerplexityVideoUrl {
152
+ url: string;
153
+ frame_interval?: string | number;
154
+ }
155
+
156
+ export interface PerplexityContentTextChunk {
157
+ type: "text";
158
+ text: string;
159
+ }
160
+
161
+ export interface PerplexityContentImageChunk {
162
+ type: "image_url";
163
+ image_url: PerplexityUrl | string;
164
+ }
165
+
166
+ export interface PerplexityContentFileChunk {
167
+ type: "file_url";
168
+ file_url: PerplexityUrl | string;
169
+ file_name?: string | null;
170
+ }
171
+
172
+ export interface PerplexityContentPdfChunk {
173
+ type: "pdf_url";
174
+ pdf_url: PerplexityUrl | string;
175
+ }
176
+
177
+ export interface PerplexityContentVideoChunk {
178
+ type: "video_url";
179
+ video_url: PerplexityVideoUrl | string;
180
+ }
181
+
182
+ export type PerplexityContentChunk =
183
+ | PerplexityContentTextChunk
184
+ | PerplexityContentImageChunk
185
+ | PerplexityContentFileChunk
186
+ | PerplexityContentPdfChunk
187
+ | PerplexityContentVideoChunk;
188
+
189
+ export interface PerplexitySearchStepDetails {
190
+ search_results: PerplexitySearchResult[];
191
+ search_keywords: string[];
192
+ }
193
+
194
+ export interface PerplexityFetchUrlContentStepDetails {
195
+ contents: PerplexitySearchResult[];
196
+ }
197
+
198
+ export interface PerplexityExecutePythonStepDetails {
199
+ code: string;
200
+ result: string;
201
+ }
202
+
203
+ export interface PerplexityReasoningStepInput {
204
+ thought: string;
205
+ type?: string | null;
206
+ web_search?: PerplexitySearchStepDetails | null;
207
+ fetch_url_content?: PerplexityFetchUrlContentStepDetails | null;
208
+ execute_python?: PerplexityExecutePythonStepDetails | null;
209
+ }
210
+
211
+ export interface PerplexityReasoningStepOutput {
212
+ thought: string;
213
+ type?: string | null;
214
+ web_search?: PerplexitySearchStepDetails | null;
215
+ fetch_url_content?: PerplexityFetchUrlContentStepDetails | null;
216
+ execute_python?: PerplexityExecutePythonStepDetails | null;
217
+ }
218
+
219
+ export interface PerplexityToolCallFunction {
220
+ name?: string | null;
221
+ arguments?: string | null;
222
+ }
223
+
224
+ export interface PerplexityToolCall {
225
+ id?: string | null;
226
+ type?: "function" | null;
227
+ function?: PerplexityToolCallFunction | null;
228
+ }
229
+
230
+ export interface PerplexityMessageInput {
231
+ role: PerplexityChatMessageRole;
232
+ content: string | PerplexityContentChunk[] | null;
233
+ reasoning_steps?: PerplexityReasoningStepInput[] | null;
234
+ tool_calls?: PerplexityToolCall[] | null;
235
+ tool_call_id?: string | null;
236
+ }
237
+
238
+ export interface PerplexityMessageOutput {
239
+ role: PerplexityChatMessageRole;
240
+ content: string | PerplexityContentChunk[] | null;
241
+ reasoning_steps?: PerplexityReasoningStepOutput[] | null;
242
+ tool_calls?: PerplexityToolCall[] | null;
243
+ tool_call_id?: string | null;
244
+ }
245
+
246
+ export type PerplexityMessage = PerplexityMessageInput;
247
+
248
+ export interface PerplexityResponseFormatText {
249
+ type: "text";
250
+ }
251
+
252
+ export interface PerplexityJSONSchema {
253
+ schema: Record<string, unknown>;
254
+ name?: string | null;
255
+ description?: string | null;
256
+ strict?: boolean | null;
257
+ }
258
+
259
+ export interface PerplexityResponseFormatJSONSchema {
260
+ type: "json_schema";
261
+ json_schema: PerplexityJSONSchema;
262
+ }
263
+
264
+ export interface PerplexityRegexSchema {
265
+ regex: string;
266
+ name?: string | null;
267
+ description?: string | null;
268
+ strict?: boolean | null;
269
+ }
270
+
271
+ export interface PerplexityResponseFormatRegex {
272
+ type: "regex";
273
+ regex: PerplexityRegexSchema;
274
+ }
275
+
276
+ export type PerplexityResponseFormat =
277
+ | PerplexityResponseFormatText
278
+ | PerplexityResponseFormatJSONSchema
279
+ | PerplexityResponseFormatRegex;
280
+
281
+ export interface PerplexityParameterSpec {
282
+ type: string;
283
+ properties: Record<string, unknown>;
284
+ required?: string[] | null;
285
+ additional_properties?: boolean | null;
286
+ }
287
+
288
+ export interface PerplexityFunctionSpec {
289
+ name: string;
290
+ description: string;
291
+ parameters: PerplexityParameterSpec;
292
+ strict?: boolean | null;
293
+ }
294
+
295
+ export interface PerplexityToolSpec {
296
+ type: "function";
297
+ function: PerplexityFunctionSpec;
298
+ }
299
+
300
+ export interface PerplexityUserLocation {
301
+ latitude?: number | null;
302
+ longitude?: number | null;
303
+ country?: string | null;
304
+ city?: string | null;
305
+ region?: string | null;
306
+ }
307
+
308
+ export interface PerplexitySearchOptions {
309
+ search_context_size?: "low" | "medium" | "high";
310
+ search_type?: "fast" | "pro" | "auto" | null;
311
+ user_location?: PerplexityUserLocation | null;
312
+ image_results_enhanced_relevance?: boolean;
155
313
  }
156
314
 
157
315
  export interface PerplexityRequest {
316
+ max_tokens?: number | null;
317
+ temperature?: number | null;
318
+ n?: number | null;
158
319
  model: string;
159
- messages: PerplexityMessage[];
160
- temperature?: number;
161
- max_tokens?: number;
162
- search_domain_filter?: string[];
163
- search_recency_filter?: "day" | "week" | "month" | "year";
164
- return_images?: boolean;
165
- return_related_questions?: boolean;
166
- web_search_options?: {
167
- search_context_size?: "low" | "medium" | "high";
168
- };
320
+ stream?: boolean | null;
321
+ stop?: string | string[] | null;
322
+ cum_logprobs?: boolean | null;
323
+ logprobs?: boolean | null;
324
+ top_logprobs?: number | null;
325
+ best_of?: number | null;
326
+ response_metadata?: Record<string, unknown> | null;
327
+ response_format?: PerplexityResponseFormat | null;
328
+ diverse_first_token?: boolean | null;
329
+ _inputs?: number[] | null;
330
+ _prompt_token_length?: number | null;
331
+ messages: PerplexityMessageInput[];
332
+ tools?: PerplexityToolSpec[] | null;
333
+ tool_choice?: "none" | "auto" | "required" | null;
334
+ parallel_tool_calls?: boolean | null;
335
+ web_search_options?: PerplexitySearchOptions;
336
+ search_mode?: "web" | "academic" | "sec" | null;
337
+ return_images?: boolean | null;
338
+ return_related_questions?: boolean | null;
339
+ num_search_results?: number;
340
+ num_images?: number;
341
+ enable_search_classifier?: boolean | null;
342
+ disable_search?: boolean | null;
343
+ search_domain_filter?: string[] | null;
344
+ search_language_filter?: string[] | null;
345
+ search_tenant?: string | null;
346
+ ranking_model?: string | null;
347
+ latitude?: number | null;
348
+ longitude?: number | null;
349
+ country?: string | null;
350
+ search_recency_filter?: "hour" | "day" | "week" | "month" | "year" | null;
351
+ search_after_date_filter?: string | null;
352
+ search_before_date_filter?: string | null;
353
+ last_updated_before_filter?: string | null;
354
+ last_updated_after_filter?: string | null;
355
+ image_format_filter?: string[] | null;
356
+ image_domain_filter?: string[] | null;
357
+ safe_search?: boolean | null;
358
+ file_workspace_id?: string | null;
359
+ updated_before_timestamp?: number | null;
360
+ updated_after_timestamp?: number | null;
361
+ search_internal_properties?: Record<string, unknown> | null;
362
+ use_threads?: boolean | null;
363
+ thread_id?: string | null;
364
+ stream_mode?: "full" | "concise";
365
+ _debug_pro_search?: boolean;
366
+ has_image_url?: boolean;
367
+ reasoning_effort?: "minimal" | "low" | "medium" | "high" | null;
368
+ language_preference?: string | null;
369
+ user_original_query?: string | null;
370
+ _force_new_agent?: boolean | null;
169
371
  }
170
372
 
171
373
  export interface PerplexitySearchResult {
172
374
  title: string;
173
375
  url: string;
174
- date?: string;
376
+ date?: string | null;
377
+ last_updated?: string | null;
175
378
  snippet?: string;
379
+ source?: "web" | "attachment";
380
+ }
381
+
382
+ export interface PerplexityCost {
383
+ input_tokens_cost: number;
384
+ output_tokens_cost: number;
385
+ reasoning_tokens_cost?: number | null;
386
+ request_cost?: number | null;
387
+ citation_tokens_cost?: number | null;
388
+ search_queries_cost?: number | null;
389
+ total_cost: number;
390
+ }
391
+
392
+ export interface PerplexityUsageInfo {
393
+ prompt_tokens: number;
394
+ completion_tokens: number;
395
+ total_tokens: number;
396
+ search_context_size?: string | null;
397
+ citation_tokens?: number | null;
398
+ num_search_queries?: number | null;
399
+ reasoning_tokens?: number | null;
400
+ cost: PerplexityCost;
401
+ }
402
+
403
+ export type PerplexityCompletionResponseType = "message" | "info" | "end_of_stream";
404
+
405
+ export type PerplexityCompletionResponseStatus = "PENDING" | "COMPLETED";
406
+
407
+ export interface PerplexityChoice {
408
+ index: number;
409
+ finish_reason?: "stop" | "length" | null;
410
+ message: PerplexityMessageOutput;
411
+ delta: PerplexityMessageOutput;
176
412
  }
177
413
 
178
414
  export interface PerplexityResponse {
179
415
  id: string;
180
416
  model: string;
181
417
  created: number;
182
- usage: {
183
- prompt_tokens: number;
184
- completion_tokens: number;
185
- total_tokens: number;
186
- search_context_size?: string;
187
- };
188
- citations?: string[];
189
- search_results?: PerplexitySearchResult[];
190
- related_questions?: string[];
191
- choices: Array<{
192
- index: number;
193
- finish_reason: string;
194
- message: {
195
- role: string;
196
- content: string;
197
- };
198
- }>;
418
+ usage?: PerplexityUsageInfo | null;
419
+ object?: string;
420
+ choices: PerplexityChoice[];
421
+ citations?: string[] | null;
422
+ search_results?: PerplexitySearchResult[] | null;
423
+ type?: PerplexityCompletionResponseType | null;
424
+ status?: PerplexityCompletionResponseStatus | null;
199
425
  }