@hasna/connectors 0.4.2 → 0.5.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 (205) hide show
  1. package/bin/index.js +113 -1
  2. package/bin/mcp.js +113 -1
  3. package/bin/serve.js +112 -0
  4. package/connectors/connect-assemblyai/.env.example +11 -0
  5. package/connectors/connect-assemblyai/CLAUDE.md +128 -0
  6. package/connectors/connect-assemblyai/README.md +193 -0
  7. package/connectors/connect-assemblyai/package.json +50 -0
  8. package/connectors/connect-assemblyai/src/api/client.ts +192 -0
  9. package/connectors/connect-assemblyai/src/api/index.ts +71 -0
  10. package/connectors/connect-assemblyai/src/cli/index.ts +384 -0
  11. package/connectors/connect-assemblyai/src/index.ts +19 -0
  12. package/connectors/connect-assemblyai/src/types/index.ts +277 -0
  13. package/connectors/connect-assemblyai/src/utils/config.ts +103 -0
  14. package/connectors/connect-assemblyai/src/utils/output.ts +119 -0
  15. package/connectors/connect-assemblyai/tsconfig.json +16 -0
  16. package/connectors/connect-baseten/.env.example +11 -0
  17. package/connectors/connect-baseten/CLAUDE.md +128 -0
  18. package/connectors/connect-baseten/README.md +193 -0
  19. package/connectors/connect-baseten/package.json +51 -0
  20. package/connectors/connect-baseten/src/api/client.ts +71 -0
  21. package/connectors/connect-baseten/src/api/index.ts +40 -0
  22. package/connectors/connect-baseten/src/cli/index.ts +244 -0
  23. package/connectors/connect-baseten/src/index.ts +19 -0
  24. package/connectors/connect-baseten/src/types/index.ts +55 -0
  25. package/connectors/connect-baseten/src/utils/config.ts +103 -0
  26. package/connectors/connect-baseten/src/utils/output.ts +119 -0
  27. package/connectors/connect-baseten/tsconfig.json +16 -0
  28. package/connectors/connect-cerebras/.env.example +11 -0
  29. package/connectors/connect-cerebras/CLAUDE.md +128 -0
  30. package/connectors/connect-cerebras/README.md +193 -0
  31. package/connectors/connect-cerebras/package.json +51 -0
  32. package/connectors/connect-cerebras/src/api/client.ts +64 -0
  33. package/connectors/connect-cerebras/src/api/index.ts +32 -0
  34. package/connectors/connect-cerebras/src/cli/index.ts +244 -0
  35. package/connectors/connect-cerebras/src/index.ts +19 -0
  36. package/connectors/connect-cerebras/src/types/index.ts +65 -0
  37. package/connectors/connect-cerebras/src/utils/config.ts +103 -0
  38. package/connectors/connect-cerebras/src/utils/output.ts +119 -0
  39. package/connectors/connect-cerebras/tsconfig.json +16 -0
  40. package/connectors/connect-cohere/.env.example +11 -0
  41. package/connectors/connect-cohere/CLAUDE.md +128 -0
  42. package/connectors/connect-cohere/README.md +193 -0
  43. package/connectors/connect-cohere/package.json +53 -0
  44. package/connectors/connect-cohere/src/api/client.ts +109 -0
  45. package/connectors/connect-cohere/src/api/index.ts +59 -0
  46. package/connectors/connect-cohere/src/cli/index.ts +255 -0
  47. package/connectors/connect-cohere/src/index.ts +19 -0
  48. package/connectors/connect-cohere/src/types/index.ts +132 -0
  49. package/connectors/connect-cohere/src/utils/config.ts +197 -0
  50. package/connectors/connect-cohere/src/utils/output.ts +119 -0
  51. package/connectors/connect-cohere/tsconfig.json +16 -0
  52. package/connectors/connect-deepgram/.env.example +11 -0
  53. package/connectors/connect-deepgram/CLAUDE.md +128 -0
  54. package/connectors/connect-deepgram/README.md +193 -0
  55. package/connectors/connect-deepgram/package.json +51 -0
  56. package/connectors/connect-deepgram/src/api/client.ts +235 -0
  57. package/connectors/connect-deepgram/src/api/index.ts +57 -0
  58. package/connectors/connect-deepgram/src/cli/index.ts +339 -0
  59. package/connectors/connect-deepgram/src/index.ts +19 -0
  60. package/connectors/connect-deepgram/src/types/index.ts +232 -0
  61. package/connectors/connect-deepgram/src/utils/config.ts +103 -0
  62. package/connectors/connect-deepgram/src/utils/output.ts +119 -0
  63. package/connectors/connect-deepgram/tsconfig.json +16 -0
  64. package/connectors/connect-deepseek/.env.example +11 -0
  65. package/connectors/connect-deepseek/CLAUDE.md +128 -0
  66. package/connectors/connect-deepseek/README.md +193 -0
  67. package/connectors/connect-deepseek/package.json +51 -0
  68. package/connectors/connect-deepseek/src/api/client.ts +108 -0
  69. package/connectors/connect-deepseek/src/api/index.ts +36 -0
  70. package/connectors/connect-deepseek/src/cli/index.ts +167 -0
  71. package/connectors/connect-deepseek/src/index.ts +19 -0
  72. package/connectors/connect-deepseek/src/types/index.ts +72 -0
  73. package/connectors/connect-deepseek/src/utils/config.ts +103 -0
  74. package/connectors/connect-deepseek/src/utils/output.ts +119 -0
  75. package/connectors/connect-deepseek/tsconfig.json +16 -0
  76. package/connectors/connect-fal/.env.example +11 -0
  77. package/connectors/connect-fal/CLAUDE.md +128 -0
  78. package/connectors/connect-fal/README.md +193 -0
  79. package/connectors/connect-fal/package.json +51 -0
  80. package/connectors/connect-fal/src/api/client.ts +172 -0
  81. package/connectors/connect-fal/src/api/index.ts +55 -0
  82. package/connectors/connect-fal/src/cli/index.ts +341 -0
  83. package/connectors/connect-fal/src/index.ts +19 -0
  84. package/connectors/connect-fal/src/types/index.ts +135 -0
  85. package/connectors/connect-fal/src/utils/config.ts +103 -0
  86. package/connectors/connect-fal/src/utils/output.ts +119 -0
  87. package/connectors/connect-fal/tsconfig.json +16 -0
  88. package/connectors/connect-fireworks/.env.example +11 -0
  89. package/connectors/connect-fireworks/CLAUDE.md +128 -0
  90. package/connectors/connect-fireworks/README.md +193 -0
  91. package/connectors/connect-fireworks/package.json +51 -0
  92. package/connectors/connect-fireworks/src/api/client.ts +63 -0
  93. package/connectors/connect-fireworks/src/api/index.ts +36 -0
  94. package/connectors/connect-fireworks/src/cli/index.ts +244 -0
  95. package/connectors/connect-fireworks/src/index.ts +19 -0
  96. package/connectors/connect-fireworks/src/types/index.ts +70 -0
  97. package/connectors/connect-fireworks/src/utils/config.ts +103 -0
  98. package/connectors/connect-fireworks/src/utils/output.ts +119 -0
  99. package/connectors/connect-fireworks/tsconfig.json +16 -0
  100. package/connectors/connect-groq/.env.example +11 -0
  101. package/connectors/connect-groq/CLAUDE.md +128 -0
  102. package/connectors/connect-groq/README.md +193 -0
  103. package/connectors/connect-groq/package.json +52 -0
  104. package/connectors/connect-groq/src/api/client.ts +108 -0
  105. package/connectors/connect-groq/src/api/index.ts +36 -0
  106. package/connectors/connect-groq/src/cli/index.ts +171 -0
  107. package/connectors/connect-groq/src/index.ts +19 -0
  108. package/connectors/connect-groq/src/types/index.ts +69 -0
  109. package/connectors/connect-groq/src/utils/config.ts +103 -0
  110. package/connectors/connect-groq/src/utils/output.ts +119 -0
  111. package/connectors/connect-groq/tsconfig.json +16 -0
  112. package/connectors/connect-luma/.env.example +11 -0
  113. package/connectors/connect-luma/CLAUDE.md +128 -0
  114. package/connectors/connect-luma/README.md +193 -0
  115. package/connectors/connect-luma/package.json +53 -0
  116. package/connectors/connect-luma/src/api/client.ts +85 -0
  117. package/connectors/connect-luma/src/api/index.ts +44 -0
  118. package/connectors/connect-luma/src/cli/index.ts +300 -0
  119. package/connectors/connect-luma/src/index.ts +19 -0
  120. package/connectors/connect-luma/src/types/index.ts +60 -0
  121. package/connectors/connect-luma/src/utils/config.ts +103 -0
  122. package/connectors/connect-luma/src/utils/output.ts +119 -0
  123. package/connectors/connect-luma/tsconfig.json +16 -0
  124. package/connectors/connect-modal/.env.example +11 -0
  125. package/connectors/connect-modal/CLAUDE.md +128 -0
  126. package/connectors/connect-modal/README.md +193 -0
  127. package/connectors/connect-modal/package.json +51 -0
  128. package/connectors/connect-modal/src/api/client.ts +119 -0
  129. package/connectors/connect-modal/src/api/index.ts +69 -0
  130. package/connectors/connect-modal/src/cli/index.ts +224 -0
  131. package/connectors/connect-modal/src/index.ts +21 -0
  132. package/connectors/connect-modal/src/types/index.ts +60 -0
  133. package/connectors/connect-modal/src/utils/config.ts +114 -0
  134. package/connectors/connect-modal/src/utils/output.ts +119 -0
  135. package/connectors/connect-modal/tsconfig.json +16 -0
  136. package/connectors/connect-perplexity/.env.example +4 -0
  137. package/connectors/connect-perplexity/CLAUDE.md +156 -0
  138. package/connectors/connect-perplexity/README.md +184 -0
  139. package/connectors/connect-perplexity/package.json +58 -0
  140. package/connectors/connect-perplexity/scripts/publish.ts +210 -0
  141. package/connectors/connect-perplexity/src/api/client.ts +119 -0
  142. package/connectors/connect-perplexity/src/api/example.ts +118 -0
  143. package/connectors/connect-perplexity/src/api/index.ts +48 -0
  144. package/connectors/connect-perplexity/src/cli/index.ts +421 -0
  145. package/connectors/connect-perplexity/src/index.ts +24 -0
  146. package/connectors/connect-perplexity/src/types/index.ts +140 -0
  147. package/connectors/connect-perplexity/src/utils/config.ts +208 -0
  148. package/connectors/connect-perplexity/src/utils/output.ts +119 -0
  149. package/connectors/connect-perplexity/tsconfig.json +16 -0
  150. package/connectors/connect-replicate/.env.example +11 -0
  151. package/connectors/connect-replicate/CLAUDE.md +128 -0
  152. package/connectors/connect-replicate/README.md +193 -0
  153. package/connectors/connect-replicate/package.json +51 -0
  154. package/connectors/connect-replicate/src/api/client.ts +109 -0
  155. package/connectors/connect-replicate/src/api/index.ts +71 -0
  156. package/connectors/connect-replicate/src/cli/index.ts +250 -0
  157. package/connectors/connect-replicate/src/index.ts +19 -0
  158. package/connectors/connect-replicate/src/types/index.ts +85 -0
  159. package/connectors/connect-replicate/src/utils/config.ts +103 -0
  160. package/connectors/connect-replicate/src/utils/output.ts +119 -0
  161. package/connectors/connect-replicate/tsconfig.json +16 -0
  162. package/connectors/connect-roboflow/.env.example +11 -0
  163. package/connectors/connect-roboflow/CLAUDE.md +272 -0
  164. package/connectors/connect-roboflow/README.md +193 -0
  165. package/connectors/connect-roboflow/package.json +51 -0
  166. package/connectors/connect-roboflow/scripts/release.ts +179 -0
  167. package/connectors/connect-roboflow/src/api/client.ts +213 -0
  168. package/connectors/connect-roboflow/src/api/example.ts +48 -0
  169. package/connectors/connect-roboflow/src/api/index.ts +51 -0
  170. package/connectors/connect-roboflow/src/cli/index.ts +254 -0
  171. package/connectors/connect-roboflow/src/index.ts +103 -0
  172. package/connectors/connect-roboflow/src/types/index.ts +237 -0
  173. package/connectors/connect-roboflow/src/utils/auth.ts +274 -0
  174. package/connectors/connect-roboflow/src/utils/bulk.ts +212 -0
  175. package/connectors/connect-roboflow/src/utils/config.ts +326 -0
  176. package/connectors/connect-roboflow/src/utils/output.ts +175 -0
  177. package/connectors/connect-roboflow/src/utils/settings.ts +114 -0
  178. package/connectors/connect-roboflow/src/utils/storage.ts +198 -0
  179. package/connectors/connect-roboflow/tsconfig.json +16 -0
  180. package/connectors/connect-runway/.env.example +11 -0
  181. package/connectors/connect-runway/CLAUDE.md +128 -0
  182. package/connectors/connect-runway/README.md +193 -0
  183. package/connectors/connect-runway/package.json +52 -0
  184. package/connectors/connect-runway/src/api/client.ts +78 -0
  185. package/connectors/connect-runway/src/api/index.ts +40 -0
  186. package/connectors/connect-runway/src/cli/index.ts +283 -0
  187. package/connectors/connect-runway/src/index.ts +19 -0
  188. package/connectors/connect-runway/src/types/index.ts +52 -0
  189. package/connectors/connect-runway/src/utils/config.ts +103 -0
  190. package/connectors/connect-runway/src/utils/output.ts +119 -0
  191. package/connectors/connect-runway/tsconfig.json +16 -0
  192. package/connectors/connect-together/.env.example +11 -0
  193. package/connectors/connect-together/CLAUDE.md +128 -0
  194. package/connectors/connect-together/README.md +193 -0
  195. package/connectors/connect-together/package.json +52 -0
  196. package/connectors/connect-together/src/api/client.ts +106 -0
  197. package/connectors/connect-together/src/api/index.ts +47 -0
  198. package/connectors/connect-together/src/cli/index.ts +228 -0
  199. package/connectors/connect-together/src/index.ts +19 -0
  200. package/connectors/connect-together/src/types/index.ts +91 -0
  201. package/connectors/connect-together/src/utils/config.ts +142 -0
  202. package/connectors/connect-together/src/utils/output.ts +119 -0
  203. package/connectors/connect-together/tsconfig.json +16 -0
  204. package/dist/index.js +112 -0
  205. package/package.json +1 -1
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Auto-versioning publish script
4
+ * - Fetches current npm version
5
+ * - Auto-bumps patch version if local version <= npm version
6
+ * - Creates git tag
7
+ * - Publishes to npm
8
+ */
9
+
10
+ import { $ } from 'bun';
11
+ import { readFileSync, writeFileSync } from 'fs';
12
+ import { join } from 'path';
13
+
14
+ interface PackageJson {
15
+ name: string;
16
+ version: string;
17
+ [key: string]: unknown;
18
+ }
19
+
20
+ type BumpType = 'patch' | 'minor' | 'major';
21
+
22
+ function parseVersion(version: string): { major: number; minor: number; patch: number } {
23
+ const [major, minor, patch] = version.split('.').map(Number);
24
+ return { major, minor, patch };
25
+ }
26
+
27
+ function bumpVersion(version: string, type: BumpType = 'patch'): string {
28
+ const { major, minor, patch } = parseVersion(version);
29
+
30
+ switch (type) {
31
+ case 'major':
32
+ return `${major + 1}.0.0`;
33
+ case 'minor':
34
+ return `${major}.${minor + 1}.0`;
35
+ case 'patch':
36
+ default:
37
+ return `${major}.${minor}.${patch + 1}`;
38
+ }
39
+ }
40
+
41
+ function compareVersions(a: string, b: string): number {
42
+ const vA = parseVersion(a);
43
+ const vB = parseVersion(b);
44
+
45
+ if (vA.major !== vB.major) return vA.major - vB.major;
46
+ if (vA.minor !== vB.minor) return vA.minor - vB.minor;
47
+ return vA.patch - vB.patch;
48
+ }
49
+
50
+ async function getNpmVersion(packageName: string): Promise<string | null> {
51
+ try {
52
+ const result = await $`npm view ${packageName} version 2>/dev/null`.text();
53
+ return result.trim() || null;
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
58
+
59
+ async function hasUncommittedChanges(): Promise<boolean> {
60
+ try {
61
+ const result = await $`git status --porcelain`.text();
62
+ return result.trim().length > 0;
63
+ } catch {
64
+ return false;
65
+ }
66
+ }
67
+
68
+ async function isGitRepo(): Promise<boolean> {
69
+ try {
70
+ await $`git rev-parse --git-dir 2>/dev/null`.text();
71
+ return true;
72
+ } catch {
73
+ return false;
74
+ }
75
+ }
76
+
77
+ async function createGitTag(version: string, packageName: string): Promise<boolean> {
78
+ const tagName = `${packageName}@${version}`;
79
+
80
+ try {
81
+ // Check if tag already exists
82
+ const existingTags = await $`git tag -l ${tagName}`.text();
83
+ if (existingTags.trim()) {
84
+ console.log(`⚠️ Tag ${tagName} already exists, skipping tag creation`);
85
+ return true;
86
+ }
87
+
88
+ await $`git tag -a ${tagName} -m "Release ${tagName}"`;
89
+ console.log(`✅ Created git tag: ${tagName}`);
90
+ return true;
91
+ } catch (error) {
92
+ console.error(`❌ Failed to create git tag: ${error}`);
93
+ return false;
94
+ }
95
+ }
96
+
97
+ async function commitVersionBump(version: string, packageName: string): Promise<boolean> {
98
+ try {
99
+ await $`git add package.json`;
100
+ await $`git commit -m "chore(${packageName}): bump version to ${version}"`;
101
+ console.log(`✅ Committed version bump`);
102
+ return true;
103
+ } catch (error) {
104
+ console.error(`❌ Failed to commit: ${error}`);
105
+ return false;
106
+ }
107
+ }
108
+
109
+ async function main() {
110
+ const args = process.argv.slice(2);
111
+ const bumpType = (args.find(a => ['patch', 'minor', 'major'].includes(a)) || 'patch') as BumpType;
112
+ const skipGit = args.includes('--skip-git');
113
+ const dryRun = args.includes('--dry-run');
114
+ const force = args.includes('--force');
115
+
116
+ // Read package.json
117
+ const pkgPath = join(process.cwd(), 'package.json');
118
+ const pkg: PackageJson = JSON.parse(readFileSync(pkgPath, 'utf-8'));
119
+
120
+ console.log(`\n📦 Publishing ${pkg.name}\n`);
121
+
122
+ // Get current npm version
123
+ const npmVersion = await getNpmVersion(pkg.name);
124
+ let newVersion = pkg.version;
125
+
126
+ if (npmVersion) {
127
+ console.log(`📌 Current npm version: ${npmVersion}`);
128
+ console.log(`📌 Local version: ${pkg.version}`);
129
+
130
+ // Check if we need to bump
131
+ if (compareVersions(pkg.version, npmVersion) <= 0) {
132
+ newVersion = bumpVersion(npmVersion, bumpType);
133
+ console.log(`🔄 Auto-bumping to: ${newVersion}`);
134
+ } else {
135
+ console.log(`✅ Local version is ahead, using: ${pkg.version}`);
136
+ }
137
+ } else {
138
+ console.log(`📌 Package not yet published to npm`);
139
+ console.log(`📌 Using local version: ${pkg.version}`);
140
+ }
141
+
142
+ // Update package.json if version changed
143
+ if (newVersion !== pkg.version) {
144
+ if (dryRun) {
145
+ console.log(`\n🧪 DRY RUN: Would update version to ${newVersion}`);
146
+ } else {
147
+ pkg.version = newVersion;
148
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
149
+ console.log(`✅ Updated package.json to version ${newVersion}`);
150
+ }
151
+ }
152
+
153
+ // Git operations
154
+ const isGit = await isGitRepo();
155
+
156
+ if (isGit && !skipGit) {
157
+ const hasChanges = await hasUncommittedChanges();
158
+
159
+ if (hasChanges && newVersion !== pkg.version) {
160
+ if (dryRun) {
161
+ console.log(`🧪 DRY RUN: Would commit version bump`);
162
+ } else {
163
+ await commitVersionBump(newVersion, pkg.name.replace('@hasna/', ''));
164
+ }
165
+ }
166
+
167
+ if (dryRun) {
168
+ console.log(`🧪 DRY RUN: Would create tag ${pkg.name}@${newVersion}`);
169
+ } else {
170
+ await createGitTag(newVersion, pkg.name.replace('@hasna/', ''));
171
+ }
172
+ }
173
+
174
+ // Build
175
+ console.log(`\n🔨 Building...`);
176
+ if (!dryRun) {
177
+ await $`bun run build`;
178
+ } else {
179
+ console.log(`🧪 DRY RUN: Would run build`);
180
+ }
181
+
182
+ // Publish
183
+ console.log(`\n🚀 Publishing to npm...`);
184
+ if (dryRun) {
185
+ console.log(`🧪 DRY RUN: Would publish ${pkg.name}@${newVersion}`);
186
+ } else {
187
+ try {
188
+ await $`npm publish`;
189
+ console.log(`\n✅ Successfully published ${pkg.name}@${newVersion}`);
190
+ } catch (error) {
191
+ console.error(`\n❌ Publish failed: ${error}`);
192
+ process.exit(1);
193
+ }
194
+ }
195
+
196
+ // Push tags
197
+ if (isGit && !skipGit && !dryRun) {
198
+ console.log(`\n📤 Pushing tags to remote...`);
199
+ try {
200
+ await $`git push --tags`;
201
+ console.log(`✅ Pushed tags to remote`);
202
+ } catch {
203
+ console.log(`⚠️ Could not push tags (no remote or not configured)`);
204
+ }
205
+ }
206
+
207
+ console.log(`\n✨ Done!\n`);
208
+ }
209
+
210
+ main().catch(console.error);
@@ -0,0 +1,119 @@
1
+ import type { PerplexityConfig, OutputFormat } from '../types';
2
+ import { PerplexityApiError } from '../types';
3
+
4
+ const DEFAULT_BASE_URL = 'https://api.perplexity.ai';
5
+
6
+ export interface RequestOptions {
7
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
8
+ params?: Record<string, string | number | boolean | undefined>;
9
+ body?: Record<string, unknown> | unknown[] | string;
10
+ headers?: Record<string, string>;
11
+ format?: OutputFormat;
12
+ }
13
+
14
+ export class PerplexityClient {
15
+ private readonly apiKey: string;
16
+ private readonly baseUrl: string;
17
+
18
+ constructor(config: PerplexityConfig) {
19
+ if (!config.apiKey) {
20
+ throw new Error('API key is required');
21
+ }
22
+ this.apiKey = config.apiKey;
23
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
24
+ }
25
+
26
+ private buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {
27
+ const url = new URL(`${this.baseUrl}${path}`);
28
+
29
+ if (params) {
30
+ Object.entries(params).forEach(([key, value]) => {
31
+ if (value !== undefined && value !== null && value !== '') {
32
+ url.searchParams.append(key, String(value));
33
+ }
34
+ });
35
+ }
36
+
37
+ return url.toString();
38
+ }
39
+
40
+ /**
41
+ * Make an authenticated request to the Perplexity API
42
+ */
43
+ async request<T>(path: string, options: RequestOptions = {}): Promise<T> {
44
+ const { method = 'GET', params, body, headers = {} } = options;
45
+
46
+ const url = this.buildUrl(path, params);
47
+
48
+ const requestHeaders: Record<string, string> = {
49
+ 'Authorization': `Bearer ${this.apiKey}`,
50
+ 'Accept': 'application/json',
51
+ ...headers,
52
+ };
53
+
54
+ if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
55
+ requestHeaders['Content-Type'] = 'application/json';
56
+ }
57
+
58
+ const fetchOptions: RequestInit = {
59
+ method,
60
+ headers: requestHeaders,
61
+ };
62
+
63
+ if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
64
+ fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
65
+ }
66
+
67
+ const response = await fetch(url, fetchOptions);
68
+
69
+ // Handle 204 No Content
70
+ if (response.status === 204) {
71
+ return {} as T;
72
+ }
73
+
74
+ // Parse response
75
+ let data: unknown;
76
+ const contentType = response.headers.get('content-type') || '';
77
+
78
+ if (contentType.includes('application/json')) {
79
+ const text = await response.text();
80
+ if (text) {
81
+ try {
82
+ data = JSON.parse(text);
83
+ } catch {
84
+ data = text;
85
+ }
86
+ }
87
+ } else {
88
+ data = await response.text();
89
+ }
90
+
91
+ // Handle errors
92
+ if (!response.ok) {
93
+ const errorMessage = typeof data === 'object' && data !== null
94
+ ? JSON.stringify(data)
95
+ : String(data || response.statusText);
96
+ throw new PerplexityApiError(errorMessage, response.status);
97
+ }
98
+
99
+ return data as T;
100
+ }
101
+
102
+ async get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T> {
103
+ return this.request<T>(path, { method: 'GET', params });
104
+ }
105
+
106
+ async post<T>(path: string, body?: Record<string, unknown> | unknown[] | string | object, params?: Record<string, string | number | boolean | undefined>): Promise<T> {
107
+ return this.request<T>(path, { method: 'POST', body: body as Record<string, unknown>, params });
108
+ }
109
+
110
+ /**
111
+ * Get a preview of the API key (for display/debugging)
112
+ */
113
+ getApiKeyPreview(): string {
114
+ if (this.apiKey.length > 10) {
115
+ return `${this.apiKey.substring(0, 6)}...${this.apiKey.substring(this.apiKey.length - 4)}`;
116
+ }
117
+ return '***';
118
+ }
119
+ }
@@ -0,0 +1,118 @@
1
+ import type { PerplexityClient } from './client';
2
+ import type {
3
+ ChatCompletionRequest,
4
+ ChatCompletionResponse,
5
+ ChatMessage,
6
+ PerplexityModel,
7
+ } from '../types';
8
+
9
+ export interface ChatOptions {
10
+ model?: PerplexityModel;
11
+ maxTokens?: number;
12
+ temperature?: number;
13
+ topP?: number;
14
+ topK?: number;
15
+ presencePenalty?: number;
16
+ frequencyPenalty?: number;
17
+ searchDomainFilter?: string[];
18
+ returnImages?: boolean;
19
+ returnRelatedQuestions?: boolean;
20
+ searchRecencyFilter?: 'month' | 'week' | 'day' | 'hour';
21
+ systemPrompt?: string;
22
+ }
23
+
24
+ /**
25
+ * Chat Completions API
26
+ */
27
+ export class ChatApi {
28
+ constructor(private readonly client: PerplexityClient) {}
29
+
30
+ /**
31
+ * Create a chat completion
32
+ */
33
+ async create(
34
+ messages: ChatMessage[],
35
+ options: ChatOptions = {}
36
+ ): Promise<ChatCompletionResponse> {
37
+ const request: ChatCompletionRequest = {
38
+ model: options.model || 'sonar',
39
+ messages,
40
+ stream: false,
41
+ };
42
+
43
+ if (options.maxTokens !== undefined) request.max_tokens = options.maxTokens;
44
+ if (options.temperature !== undefined) request.temperature = options.temperature;
45
+ if (options.topP !== undefined) request.top_p = options.topP;
46
+ if (options.topK !== undefined) request.top_k = options.topK;
47
+ if (options.presencePenalty !== undefined) request.presence_penalty = options.presencePenalty;
48
+ if (options.frequencyPenalty !== undefined) request.frequency_penalty = options.frequencyPenalty;
49
+ if (options.searchDomainFilter !== undefined) request.search_domain_filter = options.searchDomainFilter;
50
+ if (options.returnImages !== undefined) request.return_images = options.returnImages;
51
+ if (options.returnRelatedQuestions !== undefined) request.return_related_questions = options.returnRelatedQuestions;
52
+ if (options.searchRecencyFilter !== undefined) request.search_recency_filter = options.searchRecencyFilter;
53
+
54
+ return this.client.post<ChatCompletionResponse>('/chat/completions', request);
55
+ }
56
+
57
+ /**
58
+ * Simple ask method - send a single question and get an answer
59
+ */
60
+ async ask(
61
+ question: string,
62
+ options: ChatOptions = {}
63
+ ): Promise<ChatCompletionResponse> {
64
+ const messages: ChatMessage[] = [];
65
+
66
+ if (options.systemPrompt) {
67
+ messages.push({ role: 'system', content: options.systemPrompt });
68
+ }
69
+
70
+ messages.push({ role: 'user', content: question });
71
+
72
+ return this.create(messages, options);
73
+ }
74
+
75
+ /**
76
+ * Search the web and get an answer grounded in search results
77
+ */
78
+ async search(
79
+ query: string,
80
+ options: Omit<ChatOptions, 'systemPrompt'> & { recency?: 'month' | 'week' | 'day' | 'hour' } = {}
81
+ ): Promise<ChatCompletionResponse> {
82
+ const { recency, ...restOptions } = options;
83
+
84
+ return this.ask(query, {
85
+ ...restOptions,
86
+ searchRecencyFilter: recency,
87
+ systemPrompt: 'You are a helpful search assistant. Provide accurate, well-researched answers based on the most recent and relevant information available.',
88
+ });
89
+ }
90
+
91
+ /**
92
+ * Deep research on a topic
93
+ */
94
+ async research(
95
+ topic: string,
96
+ options: Omit<ChatOptions, 'model' | 'systemPrompt'> = {}
97
+ ): Promise<ChatCompletionResponse> {
98
+ return this.ask(topic, {
99
+ ...options,
100
+ model: 'sonar-deep-research',
101
+ systemPrompt: 'You are a research assistant. Provide comprehensive, well-cited analysis on the given topic.',
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Reasoning task
107
+ */
108
+ async reason(
109
+ prompt: string,
110
+ options: Omit<ChatOptions, 'model' | 'systemPrompt'> = {}
111
+ ): Promise<ChatCompletionResponse> {
112
+ return this.ask(prompt, {
113
+ ...options,
114
+ model: 'sonar-reasoning-pro',
115
+ systemPrompt: 'You are a logical reasoning assistant. Think through problems step by step and provide well-reasoned answers.',
116
+ });
117
+ }
118
+ }
@@ -0,0 +1,48 @@
1
+ import type { PerplexityConfig } from '../types';
2
+ import { PerplexityClient } from './client';
3
+ import { ChatApi } from './example';
4
+
5
+ /**
6
+ * Perplexity AI API Client
7
+ */
8
+ export class Perplexity {
9
+ private readonly client: PerplexityClient;
10
+
11
+ // API modules
12
+ public readonly chat: ChatApi;
13
+
14
+ constructor(config: PerplexityConfig) {
15
+ this.client = new PerplexityClient(config);
16
+ this.chat = new ChatApi(this.client);
17
+ }
18
+
19
+ /**
20
+ * Create a client from environment variables
21
+ * Looks for PERPLEXITY_API_KEY
22
+ */
23
+ static fromEnv(): Perplexity {
24
+ const apiKey = process.env.PERPLEXITY_API_KEY;
25
+
26
+ if (!apiKey) {
27
+ throw new Error('PERPLEXITY_API_KEY environment variable is required');
28
+ }
29
+ return new Perplexity({ apiKey });
30
+ }
31
+
32
+ /**
33
+ * Get a preview of the API key (for debugging)
34
+ */
35
+ getApiKeyPreview(): string {
36
+ return this.client.getApiKeyPreview();
37
+ }
38
+
39
+ /**
40
+ * Get the underlying client for direct API access
41
+ */
42
+ getClient(): PerplexityClient {
43
+ return this.client;
44
+ }
45
+ }
46
+
47
+ export { PerplexityClient } from './client';
48
+ export { ChatApi } from './example';