ruby_llm 1.2.0 → 1.3.0rc1

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -133
  3. data/lib/ruby_llm/active_record/acts_as.rb +212 -33
  4. data/lib/ruby_llm/aliases.json +48 -6
  5. data/lib/ruby_llm/attachments/audio.rb +12 -0
  6. data/lib/ruby_llm/attachments/image.rb +9 -0
  7. data/lib/ruby_llm/attachments/pdf.rb +9 -0
  8. data/lib/ruby_llm/attachments.rb +78 -0
  9. data/lib/ruby_llm/chat.rb +22 -19
  10. data/lib/ruby_llm/configuration.rb +30 -1
  11. data/lib/ruby_llm/connection.rb +95 -0
  12. data/lib/ruby_llm/content.rb +51 -72
  13. data/lib/ruby_llm/context.rb +30 -0
  14. data/lib/ruby_llm/embedding.rb +13 -5
  15. data/lib/ruby_llm/error.rb +1 -1
  16. data/lib/ruby_llm/image.rb +13 -5
  17. data/lib/ruby_llm/message.rb +12 -4
  18. data/lib/ruby_llm/mime_types.rb +713 -0
  19. data/lib/ruby_llm/model_info.rb +208 -27
  20. data/lib/ruby_llm/models.json +25766 -2154
  21. data/lib/ruby_llm/models.rb +95 -14
  22. data/lib/ruby_llm/provider.rb +48 -90
  23. data/lib/ruby_llm/providers/anthropic/capabilities.rb +76 -13
  24. data/lib/ruby_llm/providers/anthropic/chat.rb +7 -14
  25. data/lib/ruby_llm/providers/anthropic/media.rb +44 -34
  26. data/lib/ruby_llm/providers/anthropic/models.rb +15 -15
  27. data/lib/ruby_llm/providers/anthropic/tools.rb +2 -2
  28. data/lib/ruby_llm/providers/anthropic.rb +3 -3
  29. data/lib/ruby_llm/providers/bedrock/capabilities.rb +61 -2
  30. data/lib/ruby_llm/providers/bedrock/chat.rb +30 -73
  31. data/lib/ruby_llm/providers/bedrock/media.rb +56 -0
  32. data/lib/ruby_llm/providers/bedrock/models.rb +50 -58
  33. data/lib/ruby_llm/providers/bedrock/streaming/base.rb +16 -0
  34. data/lib/ruby_llm/providers/bedrock.rb +14 -25
  35. data/lib/ruby_llm/providers/deepseek/capabilities.rb +35 -2
  36. data/lib/ruby_llm/providers/deepseek.rb +3 -3
  37. data/lib/ruby_llm/providers/gemini/capabilities.rb +84 -3
  38. data/lib/ruby_llm/providers/gemini/chat.rb +8 -37
  39. data/lib/ruby_llm/providers/gemini/embeddings.rb +18 -34
  40. data/lib/ruby_llm/providers/gemini/images.rb +2 -2
  41. data/lib/ruby_llm/providers/gemini/media.rb +39 -110
  42. data/lib/ruby_llm/providers/gemini/models.rb +16 -22
  43. data/lib/ruby_llm/providers/gemini/tools.rb +1 -1
  44. data/lib/ruby_llm/providers/gemini.rb +3 -3
  45. data/lib/ruby_llm/providers/ollama/chat.rb +28 -0
  46. data/lib/ruby_llm/providers/ollama/media.rb +44 -0
  47. data/lib/ruby_llm/providers/ollama.rb +34 -0
  48. data/lib/ruby_llm/providers/openai/capabilities.rb +78 -3
  49. data/lib/ruby_llm/providers/openai/chat.rb +6 -4
  50. data/lib/ruby_llm/providers/openai/embeddings.rb +8 -12
  51. data/lib/ruby_llm/providers/openai/media.rb +38 -21
  52. data/lib/ruby_llm/providers/openai/models.rb +16 -17
  53. data/lib/ruby_llm/providers/openai/tools.rb +9 -5
  54. data/lib/ruby_llm/providers/openai.rb +7 -5
  55. data/lib/ruby_llm/providers/openrouter/models.rb +88 -0
  56. data/lib/ruby_llm/providers/openrouter.rb +31 -0
  57. data/lib/ruby_llm/stream_accumulator.rb +4 -4
  58. data/lib/ruby_llm/streaming.rb +3 -3
  59. data/lib/ruby_llm/utils.rb +22 -0
  60. data/lib/ruby_llm/version.rb +1 -1
  61. data/lib/ruby_llm.rb +15 -5
  62. data/lib/tasks/models.rake +69 -33
  63. data/lib/tasks/models_docs.rake +164 -121
  64. data/lib/tasks/vcr.rake +4 -2
  65. metadata +23 -14
  66. data/lib/tasks/browser_helper.rb +0 -97
  67. data/lib/tasks/capability_generator.rb +0 -123
  68. data/lib/tasks/capability_scraper.rb +0 -224
  69. data/lib/tasks/cli_helper.rb +0 -22
  70. data/lib/tasks/code_validator.rb +0 -29
  71. data/lib/tasks/model_updater.rb +0 -66
@@ -0,0 +1,713 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This MIME type implementation is based on Rack::Mime
4
+ # Copyright (c) 2007-2022 The Rack Contributors
5
+ # Released under the MIT License - https://github.com/rack/rack/blob/main/MIT-LICENSE
6
+
7
+ module RubyLLM
8
+ # MimeTypes module provides methods to handle MIME types
9
+ module MimeTypes
10
+ module_function
11
+
12
+ # Returns String with mime type if found, otherwise use +fallback+.
13
+ # +ext+ should be filename extension in the '.ext' format that
14
+ # File.extname(file) returns.
15
+ # +fallback+ may be any object
16
+ def mime_type(ext, fallback = 'application/octet-stream')
17
+ MIME_TYPES.fetch(ext.to_s.downcase, fallback)
18
+ end
19
+
20
+ # Detect if content is an image based on extension or MIME type
21
+ # @param identifier [String] File extension, path, or MIME type
22
+ # @return [Boolean] true if content is an image
23
+ def image?(identifier)
24
+ type = identifier.include?('/') ? identifier : mime_type(".#{identifier.to_s.downcase.delete('.')}")
25
+ type.start_with?('image/')
26
+ end
27
+
28
+ # Detect if content is audio based on extension or MIME type
29
+ # @param identifier [String] File extension, path, or MIME type
30
+ # @return [Boolean] true if content is audio
31
+ def audio?(identifier)
32
+ type = identifier.include?('/') ? identifier : mime_type(".#{identifier.to_s.downcase.delete('.')}")
33
+ type.start_with?('audio/')
34
+ end
35
+
36
+ # Detect if content is a PDF based on extension or MIME type
37
+ # @param identifier [String] File extension, path, or MIME type
38
+ # @return [Boolean] true if content is a PDF
39
+ def pdf?(identifier)
40
+ type = identifier.include?('/') ? identifier : mime_type(".#{identifier.to_s.downcase.delete('.')}")
41
+ type == 'application/pdf'
42
+ end
43
+
44
+ # Extract extension from filename or path
45
+ # @param path [String] File path or name
46
+ # @return [String] Extension with leading dot
47
+ def extension(path)
48
+ File.extname(path.to_s.downcase)
49
+ end
50
+
51
+ # Extract MIME type from file path
52
+ # @param path [String] File path
53
+ # @return [String] MIME type
54
+ def detect_from_path(path)
55
+ mime_type(extension(path))
56
+ end
57
+
58
+ # Find extension for a MIME type
59
+ # @param mime_type [String] MIME type to lookup
60
+ # @return [String, nil] Extension with leading dot, or nil if not found
61
+ def extension_for_mime_type(mime)
62
+ MIME_TYPES.invert[mime]
63
+ end
64
+
65
+ # List of most common mime-types, selected various sources
66
+ # according to their usefulness in a webserving scope for Ruby
67
+ # users.
68
+ #
69
+ # Original source: Rack::Mime::MIME_TYPES
70
+ MIME_TYPES = { # rubocop:disable Metrics/CollectionLiteralLength
71
+ '.123' => 'application/vnd.lotus-1-2-3',
72
+ '.3dml' => 'text/vnd.in3d.3dml',
73
+ '.3g2' => 'video/3gpp2',
74
+ '.3gp' => 'video/3gpp',
75
+ '.a' => 'application/octet-stream',
76
+ '.acc' => 'application/vnd.americandynamics.acc',
77
+ '.ace' => 'application/x-ace-compressed',
78
+ '.acu' => 'application/vnd.acucobol',
79
+ '.aep' => 'application/vnd.audiograph',
80
+ '.afp' => 'application/vnd.ibm.modcap',
81
+ '.ai' => 'application/postscript',
82
+ '.aif' => 'audio/x-aiff',
83
+ '.aiff' => 'audio/x-aiff',
84
+ '.ami' => 'application/vnd.amiga.ami',
85
+ '.apng' => 'image/apng',
86
+ '.appcache' => 'text/cache-manifest',
87
+ '.apr' => 'application/vnd.lotus-approach',
88
+ '.asc' => 'application/pgp-signature',
89
+ '.asf' => 'video/x-ms-asf',
90
+ '.asm' => 'text/x-asm',
91
+ '.aso' => 'application/vnd.accpac.simply.aso',
92
+ '.asx' => 'video/x-ms-asf',
93
+ '.atc' => 'application/vnd.acucorp',
94
+ '.atom' => 'application/atom+xml',
95
+ '.atomcat' => 'application/atomcat+xml',
96
+ '.atomsvc' => 'application/atomsvc+xml',
97
+ '.atx' => 'application/vnd.antix.game-component',
98
+ '.au' => 'audio/basic',
99
+ '.avi' => 'video/x-msvideo',
100
+ '.avif' => 'image/avif',
101
+ '.bat' => 'application/x-msdownload',
102
+ '.bcpio' => 'application/x-bcpio',
103
+ '.bdm' => 'application/vnd.syncml.dm+wbxml',
104
+ '.bh2' => 'application/vnd.fujitsu.oasysprs',
105
+ '.bin' => 'application/octet-stream',
106
+ '.bmi' => 'application/vnd.bmi',
107
+ '.bmp' => 'image/bmp',
108
+ '.box' => 'application/vnd.previewsystems.box',
109
+ '.btif' => 'image/prs.btif',
110
+ '.bz' => 'application/x-bzip',
111
+ '.bz2' => 'application/x-bzip2',
112
+ '.c' => 'text/x-c',
113
+ '.c4g' => 'application/vnd.clonk.c4group',
114
+ '.cab' => 'application/vnd.ms-cab-compressed',
115
+ '.cc' => 'text/x-c',
116
+ '.ccxml' => 'application/ccxml+xml',
117
+ '.cdbcmsg' => 'application/vnd.contact.cmsg',
118
+ '.cdkey' => 'application/vnd.mediastation.cdkey',
119
+ '.cdx' => 'chemical/x-cdx',
120
+ '.cdxml' => 'application/vnd.chemdraw+xml',
121
+ '.cdy' => 'application/vnd.cinderella',
122
+ '.cer' => 'application/pkix-cert',
123
+ '.cgm' => 'image/cgm',
124
+ '.chat' => 'application/x-chat',
125
+ '.chm' => 'application/vnd.ms-htmlhelp',
126
+ '.chrt' => 'application/vnd.kde.kchart',
127
+ '.cif' => 'chemical/x-cif',
128
+ '.cii' => 'application/vnd.anser-web-certificate-issue-initiation',
129
+ '.cil' => 'application/vnd.ms-artgalry',
130
+ '.cla' => 'application/vnd.claymore',
131
+ '.class' => 'application/octet-stream',
132
+ '.clkk' => 'application/vnd.crick.clicker.keyboard',
133
+ '.clkp' => 'application/vnd.crick.clicker.palette',
134
+ '.clkt' => 'application/vnd.crick.clicker.template',
135
+ '.clkw' => 'application/vnd.crick.clicker.wordbank',
136
+ '.clkx' => 'application/vnd.crick.clicker',
137
+ '.clp' => 'application/x-msclip',
138
+ '.cmc' => 'application/vnd.cosmocaller',
139
+ '.cmdf' => 'chemical/x-cmdf',
140
+ '.cml' => 'chemical/x-cml',
141
+ '.cmp' => 'application/vnd.yellowriver-custom-menu',
142
+ '.cmx' => 'image/x-cmx',
143
+ '.com' => 'application/x-msdownload',
144
+ '.conf' => 'text/plain',
145
+ '.cpio' => 'application/x-cpio',
146
+ '.cpp' => 'text/x-c',
147
+ '.cpt' => 'application/mac-compactpro',
148
+ '.crd' => 'application/x-mscardfile',
149
+ '.crl' => 'application/pkix-crl',
150
+ '.crt' => 'application/x-x509-ca-cert',
151
+ '.csh' => 'application/x-csh',
152
+ '.csml' => 'chemical/x-csml',
153
+ '.csp' => 'application/vnd.commonspace',
154
+ '.css' => 'text/css',
155
+ '.csv' => 'text/csv',
156
+ '.curl' => 'application/vnd.curl',
157
+ '.cww' => 'application/prs.cww',
158
+ '.cxx' => 'text/x-c',
159
+ '.daf' => 'application/vnd.mobius.daf',
160
+ '.davmount' => 'application/davmount+xml',
161
+ '.dcr' => 'application/x-director',
162
+ '.dd2' => 'application/vnd.oma.dd2+xml',
163
+ '.ddd' => 'application/vnd.fujixerox.ddd',
164
+ '.deb' => 'application/x-debian-package',
165
+ '.der' => 'application/x-x509-ca-cert',
166
+ '.dfac' => 'application/vnd.dreamfactory',
167
+ '.diff' => 'text/x-diff',
168
+ '.dis' => 'application/vnd.mobius.dis',
169
+ '.djv' => 'image/vnd.djvu',
170
+ '.djvu' => 'image/vnd.djvu',
171
+ '.dll' => 'application/x-msdownload',
172
+ '.dmg' => 'application/octet-stream',
173
+ '.dna' => 'application/vnd.dna',
174
+ '.doc' => 'application/msword',
175
+ '.docm' => 'application/vnd.ms-word.document.macroEnabled.12',
176
+ '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
177
+ '.dot' => 'application/msword',
178
+ '.dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
179
+ '.dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
180
+ '.dp' => 'application/vnd.osgi.dp',
181
+ '.dpg' => 'application/vnd.dpgraph',
182
+ '.dsc' => 'text/prs.lines.tag',
183
+ '.dtd' => 'application/xml-dtd',
184
+ '.dts' => 'audio/vnd.dts',
185
+ '.dtshd' => 'audio/vnd.dts.hd',
186
+ '.dv' => 'video/x-dv',
187
+ '.dvi' => 'application/x-dvi',
188
+ '.dwf' => 'model/vnd.dwf',
189
+ '.dwg' => 'image/vnd.dwg',
190
+ '.dxf' => 'image/vnd.dxf',
191
+ '.dxp' => 'application/vnd.spotfire.dxp',
192
+ '.ear' => 'application/java-archive',
193
+ '.ecelp4800' => 'audio/vnd.nuera.ecelp4800',
194
+ '.ecelp7470' => 'audio/vnd.nuera.ecelp7470',
195
+ '.ecelp9600' => 'audio/vnd.nuera.ecelp9600',
196
+ '.ecma' => 'application/ecmascript',
197
+ '.edm' => 'application/vnd.novadigm.edm',
198
+ '.edx' => 'application/vnd.novadigm.edx',
199
+ '.efif' => 'application/vnd.picsel',
200
+ '.ei6' => 'application/vnd.pg.osasli',
201
+ '.eml' => 'message/rfc822',
202
+ '.eol' => 'audio/vnd.digital-winds',
203
+ '.eot' => 'application/vnd.ms-fontobject',
204
+ '.eps' => 'application/postscript',
205
+ '.es3' => 'application/vnd.eszigno3+xml',
206
+ '.esf' => 'application/vnd.epson.esf',
207
+ '.etx' => 'text/x-setext',
208
+ '.exe' => 'application/x-msdownload',
209
+ '.ext' => 'application/vnd.novadigm.ext',
210
+ '.ez' => 'application/andrew-inset',
211
+ '.ez2' => 'application/vnd.ezpix-album',
212
+ '.ez3' => 'application/vnd.ezpix-package',
213
+ '.f' => 'text/x-fortran',
214
+ '.f77' => 'text/x-fortran',
215
+ '.f90' => 'text/x-fortran',
216
+ '.fbs' => 'image/vnd.fastbidsheet',
217
+ '.fdf' => 'application/vnd.fdf',
218
+ '.fe_launch' => 'application/vnd.denovo.fcselayout-link',
219
+ '.fg5' => 'application/vnd.fujitsu.oasysgp',
220
+ '.fli' => 'video/x-fli',
221
+ '.flif' => 'image/flif',
222
+ '.flo' => 'application/vnd.micrografx.flo',
223
+ '.flv' => 'video/x-flv',
224
+ '.flw' => 'application/vnd.kde.kivio',
225
+ '.flx' => 'text/vnd.fmi.flexstor',
226
+ '.fly' => 'text/vnd.fly',
227
+ '.fm' => 'application/vnd.framemaker',
228
+ '.fnc' => 'application/vnd.frogans.fnc',
229
+ '.for' => 'text/x-fortran',
230
+ '.fpx' => 'image/vnd.fpx',
231
+ '.fsc' => 'application/vnd.fsc.weblaunch',
232
+ '.fst' => 'image/vnd.fst',
233
+ '.ftc' => 'application/vnd.fluxtime.clip',
234
+ '.fti' => 'application/vnd.anser-web-funds-transfer-initiation',
235
+ '.fvt' => 'video/vnd.fvt',
236
+ '.fzs' => 'application/vnd.fuzzysheet',
237
+ '.g3' => 'image/g3fax',
238
+ '.gac' => 'application/vnd.groove-account',
239
+ '.gdl' => 'model/vnd.gdl',
240
+ '.gem' => 'application/octet-stream',
241
+ '.gemspec' => 'text/x-script.ruby',
242
+ '.ghf' => 'application/vnd.groove-help',
243
+ '.gif' => 'image/gif',
244
+ '.gim' => 'application/vnd.groove-identity-message',
245
+ '.gmx' => 'application/vnd.gmx',
246
+ '.gph' => 'application/vnd.flographit',
247
+ '.gqf' => 'application/vnd.grafeq',
248
+ '.gram' => 'application/srgs',
249
+ '.grv' => 'application/vnd.groove-injector',
250
+ '.grxml' => 'application/srgs+xml',
251
+ '.gtar' => 'application/x-gtar',
252
+ '.gtm' => 'application/vnd.groove-tool-message',
253
+ '.gtw' => 'model/vnd.gtw',
254
+ '.gv' => 'text/vnd.graphviz',
255
+ '.gz' => 'application/x-gzip',
256
+ '.h' => 'text/x-c',
257
+ '.h261' => 'video/h261',
258
+ '.h263' => 'video/h263',
259
+ '.h264' => 'video/h264',
260
+ '.hbci' => 'application/vnd.hbci',
261
+ '.hdf' => 'application/x-hdf',
262
+ '.heic' => 'image/heic',
263
+ '.heics' => 'image/heic-sequence',
264
+ '.heif' => 'image/heif',
265
+ '.heifs' => 'image/heif-sequence',
266
+ '.hh' => 'text/x-c',
267
+ '.hlp' => 'application/winhlp',
268
+ '.hpgl' => 'application/vnd.hp-hpgl',
269
+ '.hpid' => 'application/vnd.hp-hpid',
270
+ '.hps' => 'application/vnd.hp-hps',
271
+ '.hqx' => 'application/mac-binhex40',
272
+ '.htc' => 'text/x-component',
273
+ '.htke' => 'application/vnd.kenameaapp',
274
+ '.htm' => 'text/html',
275
+ '.html' => 'text/html',
276
+ '.hvd' => 'application/vnd.yamaha.hv-dic',
277
+ '.hvp' => 'application/vnd.yamaha.hv-voice',
278
+ '.hvs' => 'application/vnd.yamaha.hv-script',
279
+ '.icc' => 'application/vnd.iccprofile',
280
+ '.ice' => 'x-conference/x-cooltalk',
281
+ '.ico' => 'image/vnd.microsoft.icon',
282
+ '.ics' => 'text/calendar',
283
+ '.ief' => 'image/ief',
284
+ '.ifb' => 'text/calendar',
285
+ '.ifm' => 'application/vnd.shana.informed.formdata',
286
+ '.igl' => 'application/vnd.igloader',
287
+ '.igs' => 'model/iges',
288
+ '.igx' => 'application/vnd.micrografx.igx',
289
+ '.iif' => 'application/vnd.shana.informed.interchange',
290
+ '.imp' => 'application/vnd.accpac.simply.imp',
291
+ '.ims' => 'application/vnd.ms-ims',
292
+ '.ipk' => 'application/vnd.shana.informed.package',
293
+ '.irm' => 'application/vnd.ibm.rights-management',
294
+ '.irp' => 'application/vnd.irepository.package+xml',
295
+ '.iso' => 'application/octet-stream',
296
+ '.itp' => 'application/vnd.shana.informed.formtemplate',
297
+ '.ivp' => 'application/vnd.immervision-ivp',
298
+ '.ivu' => 'application/vnd.immervision-ivu',
299
+ '.jad' => 'text/vnd.sun.j2me.app-descriptor',
300
+ '.jam' => 'application/vnd.jam',
301
+ '.jar' => 'application/java-archive',
302
+ '.java' => 'text/x-java-source',
303
+ '.jisp' => 'application/vnd.jisp',
304
+ '.jlt' => 'application/vnd.hp-jlyt',
305
+ '.jnlp' => 'application/x-java-jnlp-file',
306
+ '.joda' => 'application/vnd.joost.joda-archive',
307
+ '.jp2' => 'image/jp2',
308
+ '.jpeg' => 'image/jpeg',
309
+ '.jpg' => 'image/jpeg',
310
+ '.jpgv' => 'video/jpeg',
311
+ '.jpm' => 'video/jpm',
312
+ '.js' => 'text/javascript',
313
+ '.json' => 'application/json',
314
+ '.karbon' => 'application/vnd.kde.karbon',
315
+ '.kfo' => 'application/vnd.kde.kformula',
316
+ '.kia' => 'application/vnd.kidspiration',
317
+ '.kml' => 'application/vnd.google-earth.kml+xml',
318
+ '.kmz' => 'application/vnd.google-earth.kmz',
319
+ '.kne' => 'application/vnd.kinar',
320
+ '.kon' => 'application/vnd.kde.kontour',
321
+ '.kpr' => 'application/vnd.kde.kpresenter',
322
+ '.ksp' => 'application/vnd.kde.kspread',
323
+ '.ktz' => 'application/vnd.kahootz',
324
+ '.kwd' => 'application/vnd.kde.kword',
325
+ '.latex' => 'application/x-latex',
326
+ '.lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
327
+ '.lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
328
+ '.les' => 'application/vnd.hhe.lesson-player',
329
+ '.link66' => 'application/vnd.route66.link66+xml',
330
+ '.log' => 'text/plain',
331
+ '.lostxml' => 'application/lost+xml',
332
+ '.lrm' => 'application/vnd.ms-lrm',
333
+ '.ltf' => 'application/vnd.frogans.ltf',
334
+ '.lvp' => 'audio/vnd.lucent.voice',
335
+ '.lwp' => 'application/vnd.lotus-wordpro',
336
+ '.m3u' => 'audio/x-mpegurl',
337
+ '.m3u8' => 'application/x-mpegurl',
338
+ '.m4a' => 'audio/mp4a-latm',
339
+ '.m4v' => 'video/mp4',
340
+ '.ma' => 'application/mathematica',
341
+ '.mag' => 'application/vnd.ecowin.chart',
342
+ '.man' => 'text/troff',
343
+ '.manifest' => 'text/cache-manifest',
344
+ '.mathml' => 'application/mathml+xml',
345
+ '.mbk' => 'application/vnd.mobius.mbk',
346
+ '.mbox' => 'application/mbox',
347
+ '.mc1' => 'application/vnd.medcalcdata',
348
+ '.mcd' => 'application/vnd.mcd',
349
+ '.mdb' => 'application/x-msaccess',
350
+ '.mdi' => 'image/vnd.ms-modi',
351
+ '.mdoc' => 'text/troff',
352
+ '.me' => 'text/troff',
353
+ '.mfm' => 'application/vnd.mfmp',
354
+ '.mgz' => 'application/vnd.proteus.magazine',
355
+ '.mid' => 'audio/midi',
356
+ '.midi' => 'audio/midi',
357
+ '.mif' => 'application/vnd.mif',
358
+ '.mime' => 'message/rfc822',
359
+ '.mj2' => 'video/mj2',
360
+ '.mjs' => 'text/javascript',
361
+ '.mlp' => 'application/vnd.dolby.mlp',
362
+ '.mmd' => 'application/vnd.chipnuts.karaoke-mmd',
363
+ '.mmf' => 'application/vnd.smaf',
364
+ '.mml' => 'application/mathml+xml',
365
+ '.mmr' => 'image/vnd.fujixerox.edmics-mmr',
366
+ '.mng' => 'video/x-mng',
367
+ '.mny' => 'application/x-msmoney',
368
+ '.mov' => 'video/quicktime',
369
+ '.movie' => 'video/x-sgi-movie',
370
+ '.mp3' => 'audio/mpeg',
371
+ '.mp4' => 'video/mp4',
372
+ '.mp4a' => 'audio/mp4',
373
+ '.mp4s' => 'application/mp4',
374
+ '.mp4v' => 'video/mp4',
375
+ '.mpc' => 'application/vnd.mophun.certificate',
376
+ '.mpd' => 'application/dash+xml',
377
+ '.mpeg' => 'video/mpeg',
378
+ '.mpg' => 'video/mpeg',
379
+ '.mpga' => 'audio/mpeg',
380
+ '.mpkg' => 'application/vnd.apple.installer+xml',
381
+ '.mpm' => 'application/vnd.blueice.multipass',
382
+ '.mpn' => 'application/vnd.mophun.application',
383
+ '.mpp' => 'application/vnd.ms-project',
384
+ '.mpy' => 'application/vnd.ibm.minipay',
385
+ '.mqy' => 'application/vnd.mobius.mqy',
386
+ '.mrc' => 'application/marc',
387
+ '.ms' => 'text/troff',
388
+ '.mscml' => 'application/mediaservercontrol+xml',
389
+ '.mseq' => 'application/vnd.mseq',
390
+ '.msf' => 'application/vnd.epson.msf',
391
+ '.msh' => 'model/mesh',
392
+ '.msi' => 'application/x-msdownload',
393
+ '.msl' => 'application/vnd.mobius.msl',
394
+ '.msty' => 'application/vnd.muvee.style',
395
+ '.mts' => 'model/vnd.mts',
396
+ '.mus' => 'application/vnd.musician',
397
+ '.mvb' => 'application/x-msmediaview',
398
+ '.mwf' => 'application/vnd.mfer',
399
+ '.mxf' => 'application/mxf',
400
+ '.mxl' => 'application/vnd.recordare.musicxml',
401
+ '.mxml' => 'application/xv+xml',
402
+ '.mxs' => 'application/vnd.triscape.mxs',
403
+ '.mxu' => 'video/vnd.mpegurl',
404
+ '.n' => 'application/vnd.nokia.n-gage.symbian.install',
405
+ '.nc' => 'application/x-netcdf',
406
+ '.ngdat' => 'application/vnd.nokia.n-gage.data',
407
+ '.nlu' => 'application/vnd.neurolanguage.nlu',
408
+ '.nml' => 'application/vnd.enliven',
409
+ '.nnd' => 'application/vnd.noblenet-directory',
410
+ '.nns' => 'application/vnd.noblenet-sealer',
411
+ '.nnw' => 'application/vnd.noblenet-web',
412
+ '.npx' => 'image/vnd.net-fpx',
413
+ '.nsf' => 'application/vnd.lotus-notes',
414
+ '.oa2' => 'application/vnd.fujitsu.oasys2',
415
+ '.oa3' => 'application/vnd.fujitsu.oasys3',
416
+ '.oas' => 'application/vnd.fujitsu.oasys',
417
+ '.obd' => 'application/x-msbinder',
418
+ '.oda' => 'application/oda',
419
+ '.odc' => 'application/vnd.oasis.opendocument.chart',
420
+ '.odf' => 'application/vnd.oasis.opendocument.formula',
421
+ '.odg' => 'application/vnd.oasis.opendocument.graphics',
422
+ '.odi' => 'application/vnd.oasis.opendocument.image',
423
+ '.odp' => 'application/vnd.oasis.opendocument.presentation',
424
+ '.ods' => 'application/vnd.oasis.opendocument.spreadsheet',
425
+ '.odt' => 'application/vnd.oasis.opendocument.text',
426
+ '.oga' => 'audio/ogg',
427
+ '.ogg' => 'application/ogg',
428
+ '.ogv' => 'video/ogg',
429
+ '.ogx' => 'application/ogg',
430
+ '.org' => 'application/vnd.lotus-organizer',
431
+ '.otc' => 'application/vnd.oasis.opendocument.chart-template',
432
+ '.otf' => 'font/otf',
433
+ '.otg' => 'application/vnd.oasis.opendocument.graphics-template',
434
+ '.oth' => 'application/vnd.oasis.opendocument.text-web',
435
+ '.oti' => 'application/vnd.oasis.opendocument.image-template',
436
+ '.otm' => 'application/vnd.oasis.opendocument.text-master',
437
+ '.ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
438
+ '.ott' => 'application/vnd.oasis.opendocument.text-template',
439
+ '.oxt' => 'application/vnd.openofficeorg.extension',
440
+ '.p' => 'text/x-pascal',
441
+ '.p10' => 'application/pkcs10',
442
+ '.p12' => 'application/x-pkcs12',
443
+ '.p7b' => 'application/x-pkcs7-certificates',
444
+ '.p7m' => 'application/pkcs7-mime',
445
+ '.p7r' => 'application/x-pkcs7-certreqresp',
446
+ '.p7s' => 'application/pkcs7-signature',
447
+ '.pas' => 'text/x-pascal',
448
+ '.pbd' => 'application/vnd.powerbuilder6',
449
+ '.pbm' => 'image/x-portable-bitmap',
450
+ '.pcl' => 'application/vnd.hp-pcl',
451
+ '.pclxl' => 'application/vnd.hp-pclxl',
452
+ '.pcx' => 'image/x-pcx',
453
+ '.pdb' => 'chemical/x-pdb',
454
+ '.pdf' => 'application/pdf',
455
+ '.pem' => 'application/x-x509-ca-cert',
456
+ '.pfr' => 'application/font-tdpfr',
457
+ '.pgm' => 'image/x-portable-graymap',
458
+ '.pgn' => 'application/x-chess-pgn',
459
+ '.pgp' => 'application/pgp-encrypted',
460
+ '.pic' => 'image/x-pict',
461
+ '.pict' => 'image/pict',
462
+ '.pkg' => 'application/octet-stream',
463
+ '.pki' => 'application/pkixcmp',
464
+ '.pkipath' => 'application/pkix-pkipath',
465
+ '.pl' => 'text/x-script.perl',
466
+ '.plb' => 'application/vnd.3gpp.pic-bw-large',
467
+ '.plc' => 'application/vnd.mobius.plc',
468
+ '.plf' => 'application/vnd.pocketlearn',
469
+ '.pls' => 'application/pls+xml',
470
+ '.pm' => 'text/x-script.perl-module',
471
+ '.pml' => 'application/vnd.ctc-posml',
472
+ '.png' => 'image/png',
473
+ '.pnm' => 'image/x-portable-anymap',
474
+ '.pntg' => 'image/x-macpaint',
475
+ '.portpkg' => 'application/vnd.macports.portpkg',
476
+ '.pot' => 'application/vnd.ms-powerpoint',
477
+ '.potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
478
+ '.potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
479
+ '.ppa' => 'application/vnd.ms-powerpoint',
480
+ '.ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
481
+ '.ppd' => 'application/vnd.cups-ppd',
482
+ '.ppm' => 'image/x-portable-pixmap',
483
+ '.pps' => 'application/vnd.ms-powerpoint',
484
+ '.ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
485
+ '.ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
486
+ '.ppt' => 'application/vnd.ms-powerpoint',
487
+ '.pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
488
+ '.pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
489
+ '.prc' => 'application/vnd.palm',
490
+ '.pre' => 'application/vnd.lotus-freelance',
491
+ '.prf' => 'application/pics-rules',
492
+ '.ps' => 'application/postscript',
493
+ '.psb' => 'application/vnd.3gpp.pic-bw-small',
494
+ '.psd' => 'image/vnd.adobe.photoshop',
495
+ '.ptid' => 'application/vnd.pvi.ptid1',
496
+ '.pub' => 'application/x-mspublisher',
497
+ '.pvb' => 'application/vnd.3gpp.pic-bw-var',
498
+ '.pwn' => 'application/vnd.3m.post-it-notes',
499
+ '.py' => 'text/x-script.python',
500
+ '.pya' => 'audio/vnd.ms-playready.media.pya',
501
+ '.pyv' => 'video/vnd.ms-playready.media.pyv',
502
+ '.qam' => 'application/vnd.epson.quickanime',
503
+ '.qbo' => 'application/vnd.intu.qbo',
504
+ '.qfx' => 'application/vnd.intu.qfx',
505
+ '.qps' => 'application/vnd.publishare-delta-tree',
506
+ '.qt' => 'video/quicktime',
507
+ '.qtif' => 'image/x-quicktime',
508
+ '.qxd' => 'application/vnd.quark.quarkxpress',
509
+ '.ra' => 'audio/x-pn-realaudio',
510
+ '.rake' => 'text/x-script.ruby',
511
+ '.ram' => 'audio/x-pn-realaudio',
512
+ '.rar' => 'application/x-rar-compressed',
513
+ '.ras' => 'image/x-cmu-raster',
514
+ '.rb' => 'text/x-script.ruby',
515
+ '.rcprofile' => 'application/vnd.ipunplugged.rcprofile',
516
+ '.rdf' => 'application/rdf+xml',
517
+ '.rdz' => 'application/vnd.data-vision.rdz',
518
+ '.rep' => 'application/vnd.businessobjects',
519
+ '.rgb' => 'image/x-rgb',
520
+ '.rif' => 'application/reginfo+xml',
521
+ '.rl' => 'application/resource-lists+xml',
522
+ '.rlc' => 'image/vnd.fujixerox.edmics-rlc',
523
+ '.rld' => 'application/resource-lists-diff+xml',
524
+ '.rm' => 'application/vnd.rn-realmedia',
525
+ '.rmp' => 'audio/x-pn-realaudio-plugin',
526
+ '.rms' => 'application/vnd.jcp.javame.midlet-rms',
527
+ '.rnc' => 'application/relax-ng-compact-syntax',
528
+ '.roff' => 'text/troff',
529
+ '.rpm' => 'application/x-redhat-package-manager',
530
+ '.rpss' => 'application/vnd.nokia.radio-presets',
531
+ '.rpst' => 'application/vnd.nokia.radio-preset',
532
+ '.rq' => 'application/sparql-query',
533
+ '.rs' => 'application/rls-services+xml',
534
+ '.rsd' => 'application/rsd+xml',
535
+ '.rss' => 'application/rss+xml',
536
+ '.rtf' => 'application/rtf',
537
+ '.rtx' => 'text/richtext',
538
+ '.ru' => 'text/x-script.ruby',
539
+ '.s' => 'text/x-asm',
540
+ '.saf' => 'application/vnd.yamaha.smaf-audio',
541
+ '.sbml' => 'application/sbml+xml',
542
+ '.sc' => 'application/vnd.ibm.secure-container',
543
+ '.scd' => 'application/x-msschedule',
544
+ '.scm' => 'application/vnd.lotus-screencam',
545
+ '.scq' => 'application/scvp-cv-request',
546
+ '.scs' => 'application/scvp-cv-response',
547
+ '.sdkm' => 'application/vnd.solent.sdkm+xml',
548
+ '.sdp' => 'application/sdp',
549
+ '.see' => 'application/vnd.seemail',
550
+ '.sema' => 'application/vnd.sema',
551
+ '.semd' => 'application/vnd.semd',
552
+ '.semf' => 'application/vnd.semf',
553
+ '.setpay' => 'application/set-payment-initiation',
554
+ '.setreg' => 'application/set-registration-initiation',
555
+ '.sfd' => 'application/vnd.hydrostatix.sof-data',
556
+ '.sfs' => 'application/vnd.spotfire.sfs',
557
+ '.sgm' => 'text/sgml',
558
+ '.sgml' => 'text/sgml',
559
+ '.sh' => 'application/x-sh',
560
+ '.shar' => 'application/x-shar',
561
+ '.shf' => 'application/shf+xml',
562
+ '.sig' => 'application/pgp-signature',
563
+ '.sit' => 'application/x-stuffit',
564
+ '.sitx' => 'application/x-stuffitx',
565
+ '.skp' => 'application/vnd.koan',
566
+ '.slt' => 'application/vnd.epson.salt',
567
+ '.smi' => 'application/smil+xml',
568
+ '.snd' => 'audio/basic',
569
+ '.so' => 'application/octet-stream',
570
+ '.spf' => 'application/vnd.yamaha.smaf-phrase',
571
+ '.spl' => 'application/x-futuresplash',
572
+ '.spot' => 'text/vnd.in3d.spot',
573
+ '.spp' => 'application/scvp-vp-response',
574
+ '.spq' => 'application/scvp-vp-request',
575
+ '.src' => 'application/x-wais-source',
576
+ '.srt' => 'text/srt',
577
+ '.srx' => 'application/sparql-results+xml',
578
+ '.sse' => 'application/vnd.kodak-descriptor',
579
+ '.ssf' => 'application/vnd.epson.ssf',
580
+ '.ssml' => 'application/ssml+xml',
581
+ '.stf' => 'application/vnd.wt.stf',
582
+ '.stk' => 'application/hyperstudio',
583
+ '.str' => 'application/vnd.pg.format',
584
+ '.sus' => 'application/vnd.sus-calendar',
585
+ '.sv4cpio' => 'application/x-sv4cpio',
586
+ '.sv4crc' => 'application/x-sv4crc',
587
+ '.svd' => 'application/vnd.svd',
588
+ '.svg' => 'image/svg+xml',
589
+ '.svgz' => 'image/svg+xml',
590
+ '.swf' => 'application/x-shockwave-flash',
591
+ '.swi' => 'application/vnd.arastra.swi',
592
+ '.t' => 'text/troff',
593
+ '.tao' => 'application/vnd.tao.intent-module-archive',
594
+ '.tar' => 'application/x-tar',
595
+ '.tbz' => 'application/x-bzip-compressed-tar',
596
+ '.tcap' => 'application/vnd.3gpp2.tcap',
597
+ '.tcl' => 'application/x-tcl',
598
+ '.tex' => 'application/x-tex',
599
+ '.texi' => 'application/x-texinfo',
600
+ '.texinfo' => 'application/x-texinfo',
601
+ '.text' => 'text/plain',
602
+ '.tif' => 'image/tiff',
603
+ '.tiff' => 'image/tiff',
604
+ '.tmo' => 'application/vnd.tmobile-livetv',
605
+ '.torrent' => 'application/x-bittorrent',
606
+ '.tpl' => 'application/vnd.groove-tool-template',
607
+ '.tpt' => 'application/vnd.trid.tpt',
608
+ '.tr' => 'text/troff',
609
+ '.tra' => 'application/vnd.trueapp',
610
+ '.trm' => 'application/x-msterminal',
611
+ '.ts' => 'video/mp2t',
612
+ '.tsv' => 'text/tab-separated-values',
613
+ '.ttf' => 'font/ttf',
614
+ '.twd' => 'application/vnd.simtech-mindmapper',
615
+ '.txd' => 'application/vnd.genomatix.tuxedo',
616
+ '.txf' => 'application/vnd.mobius.txf',
617
+ '.txt' => 'text/plain',
618
+ '.ufd' => 'application/vnd.ufdl',
619
+ '.umj' => 'application/vnd.umajin',
620
+ '.unityweb' => 'application/vnd.unity',
621
+ '.uoml' => 'application/vnd.uoml+xml',
622
+ '.uri' => 'text/uri-list',
623
+ '.ustar' => 'application/x-ustar',
624
+ '.utz' => 'application/vnd.uiq.theme',
625
+ '.uu' => 'text/x-uuencode',
626
+ '.vcd' => 'application/x-cdlink',
627
+ '.vcf' => 'text/x-vcard',
628
+ '.vcg' => 'application/vnd.groove-vcard',
629
+ '.vcs' => 'text/x-vcalendar',
630
+ '.vcx' => 'application/vnd.vcx',
631
+ '.vis' => 'application/vnd.visionary',
632
+ '.viv' => 'video/vnd.vivo',
633
+ '.vrml' => 'model/vrml',
634
+ '.vsd' => 'application/vnd.visio',
635
+ '.vsf' => 'application/vnd.vsf',
636
+ '.vtt' => 'text/vtt',
637
+ '.vtu' => 'model/vnd.vtu',
638
+ '.vxml' => 'application/voicexml+xml',
639
+ '.war' => 'application/java-archive',
640
+ '.wasm' => 'application/wasm',
641
+ '.wav' => 'audio/x-wav',
642
+ '.wax' => 'audio/x-ms-wax',
643
+ '.wbmp' => 'image/vnd.wap.wbmp',
644
+ '.wbs' => 'application/vnd.criticaltools.wbs+xml',
645
+ '.wbxml' => 'application/vnd.wap.wbxml',
646
+ '.webm' => 'video/webm',
647
+ '.webp' => 'image/webp',
648
+ '.wm' => 'video/x-ms-wm',
649
+ '.wma' => 'audio/x-ms-wma',
650
+ '.wmd' => 'application/x-ms-wmd',
651
+ '.wmf' => 'application/x-msmetafile',
652
+ '.wml' => 'text/vnd.wap.wml',
653
+ '.wmlc' => 'application/vnd.wap.wmlc',
654
+ '.wmls' => 'text/vnd.wap.wmlscript',
655
+ '.wmlsc' => 'application/vnd.wap.wmlscriptc',
656
+ '.wmv' => 'video/x-ms-wmv',
657
+ '.wmx' => 'video/x-ms-wmx',
658
+ '.wmz' => 'application/x-ms-wmz',
659
+ '.woff' => 'font/woff',
660
+ '.woff2' => 'font/woff2',
661
+ '.wpd' => 'application/vnd.wordperfect',
662
+ '.wpl' => 'application/vnd.ms-wpl',
663
+ '.wps' => 'application/vnd.ms-works',
664
+ '.wqd' => 'application/vnd.wqd',
665
+ '.wri' => 'application/x-mswrite',
666
+ '.wrl' => 'model/vrml',
667
+ '.wsdl' => 'application/wsdl+xml',
668
+ '.wspolicy' => 'application/wspolicy+xml',
669
+ '.wtb' => 'application/vnd.webturbo',
670
+ '.wvx' => 'video/x-ms-wvx',
671
+ '.x3d' => 'application/vnd.hzn-3d-crossword',
672
+ '.xar' => 'application/vnd.xara',
673
+ '.xbd' => 'application/vnd.fujixerox.docuworks.binder',
674
+ '.xbm' => 'image/x-xbitmap',
675
+ '.xdm' => 'application/vnd.syncml.dm+xml',
676
+ '.xdp' => 'application/vnd.adobe.xdp+xml',
677
+ '.xdw' => 'application/vnd.fujixerox.docuworks',
678
+ '.xenc' => 'application/xenc+xml',
679
+ '.xer' => 'application/patch-ops-error+xml',
680
+ '.xfdf' => 'application/vnd.adobe.xfdf',
681
+ '.xfdl' => 'application/vnd.xfdl',
682
+ '.xhtml' => 'application/xhtml+xml',
683
+ '.xif' => 'image/vnd.xiff',
684
+ '.xla' => 'application/vnd.ms-excel',
685
+ '.xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
686
+ '.xls' => 'application/vnd.ms-excel',
687
+ '.xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
688
+ '.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
689
+ '.xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
690
+ '.xlt' => 'application/vnd.ms-excel',
691
+ '.xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
692
+ '.xml' => 'application/xml',
693
+ '.xo' => 'application/vnd.olpc-sugar',
694
+ '.xop' => 'application/xop+xml',
695
+ '.xpm' => 'image/x-xpixmap',
696
+ '.xpr' => 'application/vnd.is-xpr',
697
+ '.xps' => 'application/vnd.ms-xpsdocument',
698
+ '.xpw' => 'application/vnd.intercon.formnet',
699
+ '.xsl' => 'application/xml',
700
+ '.xslt' => 'application/xslt+xml',
701
+ '.xsm' => 'application/vnd.syncml+xml',
702
+ '.xspf' => 'application/xspf+xml',
703
+ '.xul' => 'application/vnd.mozilla.xul+xml',
704
+ '.xwd' => 'image/x-xwindowdump',
705
+ '.xyz' => 'chemical/x-xyz',
706
+ '.yaml' => 'text/yaml',
707
+ '.yml' => 'text/yaml',
708
+ '.zaz' => 'application/vnd.zzazz.deck+xml',
709
+ '.zip' => 'application/zip',
710
+ '.zmm' => 'application/vnd.handheld-entertainment+xml'
711
+ }.freeze
712
+ end
713
+ end