@oh-my-pi/pi-coding-agent 5.6.77 → 5.7.68

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 (59) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +8 -8
  3. package/src/migrations.ts +1 -34
  4. package/src/utils/image-convert.ts +1 -1
  5. package/src/utils/image-resize.ts +2 -2
  6. package/src/vendor/photon/LICENSE.md +201 -0
  7. package/src/vendor/photon/README.md +158 -0
  8. package/src/vendor/photon/index.d.ts +3013 -0
  9. package/src/vendor/photon/index.js +4461 -0
  10. package/src/vendor/photon/photon_rs_bg.wasm +0 -0
  11. package/src/vendor/photon/photon_rs_bg.wasm.b64.js +1 -0
  12. package/src/vendor/photon/photon_rs_bg.wasm.d.ts +193 -0
  13. package/src/core/python-executor-display.test.ts +0 -42
  14. package/src/core/python-executor-lifecycle.test.ts +0 -99
  15. package/src/core/python-executor-mapping.test.ts +0 -41
  16. package/src/core/python-executor-per-call.test.ts +0 -49
  17. package/src/core/python-executor-session.test.ts +0 -103
  18. package/src/core/python-executor-streaming.test.ts +0 -77
  19. package/src/core/python-executor-timeout.test.ts +0 -35
  20. package/src/core/python-executor.lifecycle.test.ts +0 -139
  21. package/src/core/python-executor.result.test.ts +0 -49
  22. package/src/core/python-executor.test.ts +0 -180
  23. package/src/core/python-kernel-display.test.ts +0 -54
  24. package/src/core/python-kernel-env.test.ts +0 -138
  25. package/src/core/python-kernel-session.test.ts +0 -87
  26. package/src/core/python-kernel-ws.test.ts +0 -104
  27. package/src/core/python-kernel.lifecycle.test.ts +0 -249
  28. package/src/core/python-kernel.test.ts +0 -461
  29. package/src/core/python-modules.test.ts +0 -102
  30. package/src/core/python-prelude.test.ts +0 -140
  31. package/src/core/settings-manager-python.test.ts +0 -23
  32. package/src/core/streaming-output.test.ts +0 -26
  33. package/src/core/system-prompt.python.test.ts +0 -17
  34. package/src/core/tools/index.test.ts +0 -212
  35. package/src/core/tools/python-execution.test.ts +0 -68
  36. package/src/core/tools/python-fallback.test.ts +0 -72
  37. package/src/core/tools/python-renderer.test.ts +0 -36
  38. package/src/core/tools/python-tool-mode.test.ts +0 -43
  39. package/src/core/tools/python.test.ts +0 -121
  40. package/src/core/tools/schema-validation.test.ts +0 -530
  41. package/src/core/tools/web-scrapers/academic.test.ts +0 -239
  42. package/src/core/tools/web-scrapers/business.test.ts +0 -82
  43. package/src/core/tools/web-scrapers/dev-platforms.test.ts +0 -254
  44. package/src/core/tools/web-scrapers/documentation.test.ts +0 -85
  45. package/src/core/tools/web-scrapers/finance-media.test.ts +0 -144
  46. package/src/core/tools/web-scrapers/git-hosting.test.ts +0 -272
  47. package/src/core/tools/web-scrapers/media.test.ts +0 -138
  48. package/src/core/tools/web-scrapers/package-managers-2.test.ts +0 -199
  49. package/src/core/tools/web-scrapers/package-managers.test.ts +0 -171
  50. package/src/core/tools/web-scrapers/package-registries.test.ts +0 -259
  51. package/src/core/tools/web-scrapers/research.test.ts +0 -107
  52. package/src/core/tools/web-scrapers/security.test.ts +0 -103
  53. package/src/core/tools/web-scrapers/social-extended.test.ts +0 -192
  54. package/src/core/tools/web-scrapers/social.test.ts +0 -259
  55. package/src/core/tools/web-scrapers/stackexchange.test.ts +0 -120
  56. package/src/core/tools/web-scrapers/standards.test.ts +0 -122
  57. package/src/core/tools/web-scrapers/wikipedia.test.ts +0 -73
  58. package/src/core/tools/web-scrapers/youtube.test.ts +0 -198
  59. package/src/discovery/helpers.test.ts +0 -131
@@ -1,144 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { handleArtifactHub } from "./artifacthub";
3
- import { handleCoinGecko } from "./coingecko";
4
- import { handleDiscogs } from "./discogs";
5
-
6
- const SKIP = !process.env.WEB_FETCH_INTEGRATION;
7
-
8
- describe.skipIf(SKIP)("handleCoinGecko", () => {
9
- it("returns null for non-CoinGecko URLs", async () => {
10
- const result = await handleCoinGecko("https://example.com", 20);
11
- expect(result).toBeNull();
12
- });
13
-
14
- it("returns null for CoinGecko homepage", async () => {
15
- const result = await handleCoinGecko("https://www.coingecko.com/", 20);
16
- expect(result).toBeNull();
17
- });
18
-
19
- it("returns null for CoinGecko categories page", async () => {
20
- const result = await handleCoinGecko("https://www.coingecko.com/en/categories", 20);
21
- expect(result).toBeNull();
22
- });
23
-
24
- it("fetches Bitcoin data", async () => {
25
- const result = await handleCoinGecko("https://www.coingecko.com/en/coins/bitcoin", 20);
26
- expect(result).not.toBeNull();
27
- expect(result?.method).toBe("coingecko");
28
- expect(result?.content).toContain("Bitcoin");
29
- expect(result?.content).toContain("BTC");
30
- expect(result?.content).toContain("Price");
31
- expect(result?.contentType).toBe("text/markdown");
32
- expect(result?.fetchedAt).toBeTruthy();
33
- expect(result?.truncated).toBeDefined();
34
- });
35
-
36
- it("fetches Ethereum data", async () => {
37
- const result = await handleCoinGecko("https://www.coingecko.com/en/coins/ethereum", 20);
38
- expect(result).not.toBeNull();
39
- expect(result?.method).toBe("coingecko");
40
- expect(result?.content).toContain("Ethereum");
41
- expect(result?.content).toContain("ETH");
42
- expect(result?.content).toContain("Market Cap");
43
- expect(result?.truncated).toBeDefined();
44
- });
45
-
46
- it("handles URL without locale prefix", async () => {
47
- const result = await handleCoinGecko("https://www.coingecko.com/coins/bitcoin", 20);
48
- expect(result).not.toBeNull();
49
- expect(result?.method).toBe("coingecko");
50
- });
51
- });
52
-
53
- describe.skipIf(SKIP)("handleDiscogs", () => {
54
- it("returns null for non-Discogs URLs", async () => {
55
- const result = await handleDiscogs("https://example.com", 20);
56
- expect(result).toBeNull();
57
- });
58
-
59
- it("returns null for Discogs homepage", async () => {
60
- const result = await handleDiscogs("https://www.discogs.com/", 20);
61
- expect(result).toBeNull();
62
- });
63
-
64
- it("returns null for Discogs search page", async () => {
65
- const result = await handleDiscogs("https://www.discogs.com/search/", 20);
66
- expect(result).toBeNull();
67
- });
68
-
69
- it("fetches Daft Punk Discovery release", async () => {
70
- // Release 249504: Daft Punk - Discovery
71
- const result = await handleDiscogs("https://www.discogs.com/release/249504-Daft-Punk-Discovery", 20);
72
- expect(result).not.toBeNull();
73
- expect(result?.method).toBe("discogs");
74
- expect(result?.content).toContain("Daft Punk");
75
- expect(result?.content).toContain("Discovery");
76
- expect(result?.content).toContain("Tracklist");
77
- expect(result?.contentType).toBe("text/markdown");
78
- expect(result?.fetchedAt).toBeTruthy();
79
- expect(result?.truncated).toBeDefined();
80
- });
81
-
82
- it("fetches master release", async () => {
83
- // Master 33395: Daft Punk - Discovery (master)
84
- const result = await handleDiscogs("https://www.discogs.com/master/33395-Daft-Punk-Discovery", 20);
85
- expect(result).not.toBeNull();
86
- expect(result?.method).toBe("discogs");
87
- expect(result?.content).toContain("Daft Punk");
88
- expect(result?.content).toContain("Master Release");
89
- expect(result?.truncated).toBeDefined();
90
- });
91
-
92
- it("handles release URL with just ID", async () => {
93
- const result = await handleDiscogs("https://www.discogs.com/release/249504", 20);
94
- expect(result).not.toBeNull();
95
- expect(result?.method).toBe("discogs");
96
- });
97
- });
98
-
99
- describe.skipIf(SKIP)("handleArtifactHub", () => {
100
- it("returns null for non-ArtifactHub URLs", async () => {
101
- const result = await handleArtifactHub("https://example.com", 20);
102
- expect(result).toBeNull();
103
- });
104
-
105
- it("returns null for ArtifactHub homepage", async () => {
106
- const result = await handleArtifactHub("https://artifacthub.io/", 20);
107
- expect(result).toBeNull();
108
- });
109
-
110
- it("returns null for ArtifactHub search page", async () => {
111
- const result = await handleArtifactHub("https://artifacthub.io/packages/search", 20);
112
- expect(result).toBeNull();
113
- });
114
-
115
- it("fetches bitnami/nginx helm chart", async () => {
116
- const result = await handleArtifactHub("https://artifacthub.io/packages/helm/bitnami/nginx", 20);
117
- expect(result).not.toBeNull();
118
- expect(result?.method).toBe("artifacthub");
119
- expect(result?.content).toContain("nginx");
120
- expect(result?.content).toContain("Helm Chart");
121
- expect(result?.content).toContain("Version");
122
- expect(result?.contentType).toBe("text/markdown");
123
- expect(result?.fetchedAt).toBeTruthy();
124
- expect(result?.truncated).toBeDefined();
125
- });
126
-
127
- it("fetches prometheus-community/prometheus helm chart", async () => {
128
- const result = await handleArtifactHub(
129
- "https://artifacthub.io/packages/helm/prometheus-community/prometheus",
130
- 20,
131
- );
132
- expect(result).not.toBeNull();
133
- expect(result?.method).toBe("artifacthub");
134
- expect(result?.content).toContain("prometheus");
135
- expect(result?.content).toContain("Repository");
136
- expect(result?.truncated).toBeDefined();
137
- });
138
-
139
- it("handles www subdomain", async () => {
140
- const result = await handleArtifactHub("https://www.artifacthub.io/packages/helm/bitnami/nginx", 20);
141
- expect(result).not.toBeNull();
142
- expect(result?.method).toBe("artifacthub");
143
- });
144
- });
@@ -1,272 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { handleGitHub } from "./github";
3
- import { handleGitHubGist } from "./github-gist";
4
-
5
- const SKIP = !process.env.WEB_FETCH_INTEGRATION;
6
-
7
- // =============================================================================
8
- // GitHub Tests
9
- // =============================================================================
10
-
11
- describe.skipIf(SKIP)("handleGitHub", () => {
12
- it("returns null for non-GitHub URLs", async () => {
13
- const result = await handleGitHub("https://example.com", 10000);
14
- expect(result).toBeNull();
15
- });
16
-
17
- it("returns null for other git hosting domains", async () => {
18
- const result = await handleGitHub("https://gitlab.com/user/repo", 10000);
19
- expect(result).toBeNull();
20
- });
21
-
22
- it("fetches repository root", async () => {
23
- const result = await handleGitHub("https://github.com/facebook/react", 20000);
24
- if (result !== null) {
25
- expect(result.method).toBe("github-repo");
26
- expect(result.contentType).toBe("text/markdown");
27
- expect(result.content).toContain("facebook/react");
28
- expect(result.content).toContain("Stars:");
29
- expect(result.content).toContain("Forks:");
30
- }
31
- expect(result).toBeDefined();
32
- });
33
-
34
- it("fetches another repository", async () => {
35
- const result = await handleGitHub("https://github.com/microsoft/typescript", 20000);
36
- if (result !== null) {
37
- expect(result.method).toBe("github-repo");
38
- // GitHub returns "TypeScript" with capital T
39
- expect(result.content).toContain("microsoft/TypeScript");
40
- }
41
- expect(result).toBeDefined();
42
- });
43
-
44
- it("fetches file blob", async () => {
45
- const result = await handleGitHub("https://github.com/facebook/react/blob/main/README.md", 20000);
46
- expect(result).not.toBeNull();
47
- expect(result?.method).toBe("github-raw");
48
- expect(result?.contentType).toBe("text/plain");
49
- expect(result?.content.length).toBeGreaterThan(0);
50
- });
51
-
52
- it("fetches file blob from specific branch", async () => {
53
- const result = await handleGitHub("https://github.com/facebook/react/blob/main/package.json", 20000);
54
- expect(result).not.toBeNull();
55
- expect(result?.method).toBe("github-raw");
56
- expect(result?.content.length).toBeGreaterThan(0);
57
- });
58
-
59
- it("fetches directory tree", async () => {
60
- const result = await handleGitHub("https://github.com/facebook/react/tree/main/packages", 20000);
61
- if (result !== null) {
62
- expect(result.method).toBe("github-tree");
63
- expect(result.contentType).toBe("text/markdown");
64
- expect(result.content).toContain("facebook/react");
65
- expect(result.content).toContain("Contents");
66
- }
67
- expect(result).toBeDefined();
68
- });
69
-
70
- it("fetches directory tree from root", async () => {
71
- const result = await handleGitHub("https://github.com/facebook/react/tree/main", 20000);
72
- if (result !== null) {
73
- expect(result.method).toBe("github-tree");
74
- expect(result.content).toContain("facebook/react");
75
- }
76
- expect(result).toBeDefined();
77
- });
78
-
79
- it("fetches issue", async () => {
80
- const result = await handleGitHub("https://github.com/facebook/react/issues/1", 20000);
81
- if (result !== null) {
82
- expect(result.method).toBe("github-issue");
83
- expect(result.contentType).toBe("text/markdown");
84
- expect(result.content.length).toBeGreaterThan(0);
85
- }
86
- expect(result).toBeDefined();
87
- });
88
-
89
- it("fetches pull request", async () => {
90
- const result = await handleGitHub("https://github.com/facebook/react/pull/1", 20000);
91
- if (result !== null) {
92
- expect(result.method).toBe("github-pr");
93
- expect(result.contentType).toBe("text/markdown");
94
- expect(result.content.length).toBeGreaterThan(0);
95
- }
96
- expect(result).toBeDefined();
97
- });
98
-
99
- it("fetches issues list", async () => {
100
- const result = await handleGitHub("https://github.com/facebook/react/issues", 20000);
101
- if (result !== null) {
102
- expect(result.method).toBe("github-issues");
103
- expect(result.contentType).toBe("text/markdown");
104
- expect(result.content.length).toBeGreaterThan(0);
105
- }
106
- expect(result).toBeDefined();
107
- });
108
-
109
- it("handles repository with underscore in name", async () => {
110
- const result = await handleGitHub("https://github.com/rust-lang/rust-analyzer", 20000);
111
- if (result !== null) {
112
- expect(result.method).toBe("github-repo");
113
- }
114
- expect(result).toBeDefined();
115
- });
116
-
117
- it("handles repository with dash in name", async () => {
118
- const result = await handleGitHub("https://github.com/vercel/next.js", 20000);
119
- if (result !== null) {
120
- expect(result.method).toBe("github-repo");
121
- }
122
- expect(result).toBeDefined();
123
- });
124
-
125
- it("returns null for invalid URL structure", async () => {
126
- const result = await handleGitHub("https://github.com/", 10000);
127
- expect(result).toBeNull();
128
- });
129
-
130
- it("returns null for single path segment", async () => {
131
- const result = await handleGitHub("https://github.com/facebook", 10000);
132
- expect(result).toBeNull();
133
- });
134
-
135
- it("handles pulls list endpoint", async () => {
136
- const result = await handleGitHub("https://github.com/facebook/react/pulls", 20000);
137
- // Should be handled as pulls list but currently falls back to null
138
- // This tests the actual behavior
139
- expect(result).toBeDefined();
140
- });
141
-
142
- it("fetches file with path containing multiple directories", async () => {
143
- const result = await handleGitHub(
144
- "https://github.com/facebook/react/blob/main/packages/react/package.json",
145
- 20000,
146
- );
147
- expect(result).not.toBeNull();
148
- expect(result?.method).toBe("github-raw");
149
- });
150
-
151
- it("fetches deeply nested directory", async () => {
152
- const result = await handleGitHub("https://github.com/facebook/react/tree/main/packages/react/src", 20000);
153
- if (result !== null) {
154
- expect(result.method).toBe("github-tree");
155
- }
156
- expect(result).toBeDefined();
157
- });
158
-
159
- it("returns null for discussion URLs", async () => {
160
- const result = await handleGitHub("https://github.com/facebook/react/discussions", 10000);
161
- // Discussions not fully implemented, should return null
162
- expect(result).toBeDefined();
163
- });
164
-
165
- it("handles trailing slash in repository URL", async () => {
166
- const result = await handleGitHub("https://github.com/facebook/react/", 20000);
167
- if (result !== null) {
168
- expect(result.method).toBe("github-repo");
169
- }
170
- expect(result).toBeDefined();
171
- });
172
- });
173
-
174
- // =============================================================================
175
- // GitHub Gist Tests
176
- // =============================================================================
177
-
178
- describe.skipIf(SKIP)("handleGitHubGist", () => {
179
- it("returns null for non-gist URLs", async () => {
180
- const result = await handleGitHubGist("https://example.com", 10000);
181
- expect(result).toBeNull();
182
- });
183
-
184
- it("returns null for github.com URLs", async () => {
185
- const result = await handleGitHubGist("https://github.com/user/repo", 10000);
186
- expect(result).toBeNull();
187
- });
188
-
189
- it("returns null for gist.github.com root", async () => {
190
- const result = await handleGitHubGist("https://gist.github.com/", 10000);
191
- expect(result).toBeNull();
192
- });
193
-
194
- it("fetches a public gist with username", async () => {
195
- // Using a valid public gist ID (may change but structure should be consistent)
196
- const result = await handleGitHubGist("https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88", 20000);
197
- if (result !== null) {
198
- expect(result.method).toBe("github-gist");
199
- expect(result.contentType).toBe("text/markdown");
200
- expect(result.content).toContain("Gist by");
201
- expect(result.content).toContain("Created:");
202
- expect(result.content).toContain("Files:");
203
- }
204
- expect(result).toBeDefined();
205
- });
206
-
207
- it("fetches a public gist without username in URL", async () => {
208
- // Same gist, accessed via short URL (without username)
209
- const result = await handleGitHubGist("https://gist.github.com/edf814aeee85062bc9b9830aeaf27b88", 20000);
210
- if (result !== null) {
211
- expect(result.method).toBe("github-gist");
212
- expect(result.content).toContain("Gist by");
213
- }
214
- expect(result).toBeDefined();
215
- });
216
-
217
- it("returns null for invalid gist ID format", async () => {
218
- const result = await handleGitHubGist("https://gist.github.com/invalid-gist-id!", 10000);
219
- expect(result).toBeNull();
220
- });
221
-
222
- it("returns null for non-hexadecimal gist ID", async () => {
223
- const result = await handleGitHubGist("https://gist.github.com/notahexstring123", 10000);
224
- expect(result).toBeNull();
225
- });
226
-
227
- it("handles gist URL with trailing slash", async () => {
228
- const result = await handleGitHubGist("https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88/", 20000);
229
- if (result !== null) {
230
- expect(result.method).toBe("github-gist");
231
- }
232
- expect(result).toBeDefined();
233
- });
234
-
235
- it("handles gist with revision hash", async () => {
236
- const result = await handleGitHubGist(
237
- "https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88/abc123",
238
- 20000,
239
- );
240
- // Should handle revision hash in URL path
241
- expect(result).toBeDefined();
242
- });
243
-
244
- it("formats gist content as markdown with code blocks", async () => {
245
- const result = await handleGitHubGist("https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88", 20000);
246
- if (result !== null) {
247
- expect(result.content).toContain("```");
248
- expect(result.content).toContain("---");
249
- }
250
- expect(result).toBeDefined();
251
- });
252
-
253
- it("includes file metadata", async () => {
254
- const result = await handleGitHubGist("https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88", 20000);
255
- if (result !== null) {
256
- expect(result.content).toContain("Created:");
257
- expect(result.content).toContain("Updated:");
258
- }
259
- expect(result).toBeDefined();
260
- });
261
-
262
- it("returns null for nonexistent gist", async () => {
263
- const result = await handleGitHubGist("https://gist.github.com/0000000000000000000000000000000000000000", 20000);
264
- expect(result).toBeNull();
265
- });
266
-
267
- it("handles API rate limiting gracefully", async () => {
268
- // This test just ensures no errors are thrown
269
- const result = await handleGitHubGist("https://gist.github.com/gaearon/edf814aeee85062bc9b9830aeaf27b88", 5000);
270
- expect(result).toBeDefined();
271
- });
272
- });
@@ -1,138 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { handleHuggingFace } from "./huggingface";
3
- import { handleSpotify } from "./spotify";
4
- import { handleVimeo } from "./vimeo";
5
-
6
- const SKIP = !process.env.WEB_FETCH_INTEGRATION;
7
-
8
- describe.skipIf(SKIP)("handleVimeo", () => {
9
- it("returns null for non-Vimeo URLs", async () => {
10
- const result = await handleVimeo("https://example.com", 10);
11
- expect(result).toBeNull();
12
- });
13
-
14
- it("returns null for invalid Vimeo URLs", async () => {
15
- const result = await handleVimeo("https://vimeo.com/invalid", 10);
16
- expect(result).toBeNull();
17
- });
18
-
19
- it("fetches video metadata via oEmbed", async () => {
20
- const result = await handleVimeo("https://vimeo.com/1084537", 20);
21
- expect(result).not.toBeNull();
22
- expect(result?.method).toBe("vimeo");
23
- expect(result?.contentType).toBe("text/markdown");
24
- expect(result?.content).toContain("Video ID");
25
- expect(result?.notes).toContain("Fetched via Vimeo oEmbed API");
26
- });
27
-
28
- it("handles player.vimeo.com URLs", async () => {
29
- const result = await handleVimeo("https://player.vimeo.com/video/1084537", 20);
30
- expect(result).not.toBeNull();
31
- expect(result?.method).toBe("vimeo");
32
- expect(result?.content).toContain("Video ID");
33
- });
34
-
35
- it("handles vimeo.com/user/video format", async () => {
36
- const result = await handleVimeo("https://vimeo.com/staffpicks/1084537", 20);
37
- expect(result).not.toBeNull();
38
- expect(result?.method).toBe("vimeo");
39
- });
40
- });
41
-
42
- describe.skipIf(SKIP)("handleSpotify", () => {
43
- it("returns null for non-Spotify URLs", async () => {
44
- const result = await handleSpotify("https://example.com", 10);
45
- expect(result).toBeNull();
46
- });
47
-
48
- it("returns null for invalid Spotify URLs", async () => {
49
- const result = await handleSpotify("https://open.spotify.com/invalid/xyz", 10);
50
- expect(result).toBeNull();
51
- });
52
-
53
- it("identifies track URLs", async () => {
54
- const result = await handleSpotify("https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT", 20);
55
- expect(result).not.toBeNull();
56
- expect(result?.method).toBe("spotify");
57
- expect(result?.contentType).toBe("text/markdown");
58
- expect(result?.content).toContain("Type");
59
- expect(result?.content).toContain("track");
60
- });
61
-
62
- it("identifies album URLs", async () => {
63
- const result = await handleSpotify("https://open.spotify.com/album/2ODvWsOgouMbaA5xf0RkJe", 20);
64
- expect(result).not.toBeNull();
65
- expect(result?.method).toBe("spotify");
66
- expect(result?.content).toContain("album");
67
- });
68
-
69
- it("identifies playlist URLs", async () => {
70
- const result = await handleSpotify("https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M", 20);
71
- expect(result).not.toBeNull();
72
- expect(result?.method).toBe("spotify");
73
- expect(result?.content).toContain("playlist");
74
- });
75
-
76
- it("identifies podcast episode URLs", async () => {
77
- const result = await handleSpotify("https://open.spotify.com/episode/0Q86acNRm6V9GYx55SXKwf", 20);
78
- expect(result).not.toBeNull();
79
- expect(result?.method).toBe("spotify");
80
- expect(result?.content).toContain("podcast-episode");
81
- });
82
-
83
- it("identifies podcast show URLs", async () => {
84
- const result = await handleSpotify("https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL", 20);
85
- expect(result).not.toBeNull();
86
- expect(result?.method).toBe("spotify");
87
- expect(result?.content).toContain("podcast-show");
88
- });
89
- });
90
-
91
- describe.skipIf(SKIP)("handleHuggingFace", () => {
92
- it("returns null for non-HF URLs", async () => {
93
- const result = await handleHuggingFace("https://example.com", 10);
94
- expect(result).toBeNull();
95
- });
96
-
97
- it("returns null for invalid HF URLs", async () => {
98
- const result = await handleHuggingFace("https://huggingface.co", 10);
99
- expect(result).toBeNull();
100
- });
101
-
102
- it("fetches model info", async () => {
103
- const result = await handleHuggingFace("https://huggingface.co/bert-base-uncased", 20);
104
- expect(result).not.toBeNull();
105
- expect(result?.method).toBe("huggingface");
106
- expect(result?.contentType).toBe("text/markdown");
107
- expect(result?.content).toContain("bert-base-uncased");
108
- });
109
-
110
- it("fetches dataset info", async () => {
111
- const result = await handleHuggingFace("https://huggingface.co/datasets/squad", 20);
112
- expect(result).not.toBeNull();
113
- expect(result?.method).toBe("huggingface");
114
- expect(result?.content).toContain("squad");
115
- });
116
-
117
- it("fetches space info", async () => {
118
- const result = await handleHuggingFace("https://huggingface.co/spaces/gradio/hello_world", 20);
119
- expect(result).not.toBeNull();
120
- expect(result?.method).toBe("huggingface");
121
- expect(result?.content).toContain("gradio/hello_world");
122
- });
123
-
124
- it("fetches model without org prefix", async () => {
125
- // Some models like bert-base-uncased don't have an org prefix
126
- const result = await handleHuggingFace("https://huggingface.co/bert-base-uncased", 20);
127
- expect(result).not.toBeNull();
128
- expect(result?.method).toBe("huggingface");
129
- expect(result?.content).toContain("bert-base-uncased");
130
- });
131
-
132
- it("handles org/model format", async () => {
133
- const result = await handleHuggingFace("https://huggingface.co/google/bert_uncased_L-2_H-128_A-2", 20);
134
- expect(result).not.toBeNull();
135
- expect(result?.method).toBe("huggingface");
136
- expect(result?.content).toContain("google/bert_uncased_L-2_H-128_A-2");
137
- });
138
- });