otherwise-cli 0.1.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 (81) hide show
  1. package/README.md +193 -0
  2. package/bin/otherwise.js +5 -0
  3. package/frontend/404.html +84 -0
  4. package/frontend/assets/OpenDyslexic3-Bold-CDyRs55Y.ttf +0 -0
  5. package/frontend/assets/OpenDyslexic3-Regular-CIBXa4WE.ttf +0 -0
  6. package/frontend/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  7. package/frontend/assets/conversational-worker-CeKiciGk.js +2929 -0
  8. package/frontend/assets/dictation-worker-D0aYfq8b.js +29 -0
  9. package/frontend/assets/gemini-color-CgSQmmva.png +0 -0
  10. package/frontend/assets/index-BLux5ps4.js +21 -0
  11. package/frontend/assets/index-Blh8_TEM.js +5272 -0
  12. package/frontend/assets/index-BpQ1PuKu.js +18 -0
  13. package/frontend/assets/index-Df737c8w.css +1 -0
  14. package/frontend/assets/index-xaYHL6wb.js +113 -0
  15. package/frontend/assets/ort-wasm-simd-threaded.asyncify-BynIiDiv.wasm +0 -0
  16. package/frontend/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm +0 -0
  17. package/frontend/assets/transformers-tULNc5V3.js +31 -0
  18. package/frontend/assets/tts-worker-DPJWqT7N.js +2899 -0
  19. package/frontend/assets/voice-mode-worker-GzvIE_uh.js +2927 -0
  20. package/frontend/assets/worker-2d5ABSLU.js +31 -0
  21. package/frontend/banner.png +0 -0
  22. package/frontend/favicon.svg +3 -0
  23. package/frontend/google55e5ec47ee14a5f8.html +1 -0
  24. package/frontend/index.html +234 -0
  25. package/frontend/manifest.json +17 -0
  26. package/frontend/pdf.worker.min.mjs +21 -0
  27. package/frontend/robots.txt +5 -0
  28. package/frontend/sitemap.xml +27 -0
  29. package/package.json +81 -0
  30. package/src/agent/index.js +1066 -0
  31. package/src/agent/location.js +51 -0
  32. package/src/agent/prompt.js +548 -0
  33. package/src/agent/tools.js +4372 -0
  34. package/src/browser/detect.js +68 -0
  35. package/src/browser/session.js +1109 -0
  36. package/src/config.js +137 -0
  37. package/src/email/client.js +503 -0
  38. package/src/index.js +557 -0
  39. package/src/inference/anthropic.js +113 -0
  40. package/src/inference/google.js +373 -0
  41. package/src/inference/index.js +81 -0
  42. package/src/inference/ollama.js +383 -0
  43. package/src/inference/openai.js +140 -0
  44. package/src/inference/openrouter.js +378 -0
  45. package/src/inference/xai.js +200 -0
  46. package/src/logBridge.js +9 -0
  47. package/src/models.js +146 -0
  48. package/src/remote/client.js +225 -0
  49. package/src/scheduler/cron.js +243 -0
  50. package/src/server.js +3876 -0
  51. package/src/storage/db.js +1135 -0
  52. package/src/storage/supabase.js +364 -0
  53. package/src/tunnel/cloudflare.js +241 -0
  54. package/src/ui/components/App.jsx +687 -0
  55. package/src/ui/components/BrowserSelect.jsx +111 -0
  56. package/src/ui/components/FilePicker.jsx +472 -0
  57. package/src/ui/components/Header.jsx +444 -0
  58. package/src/ui/components/HelpPanel.jsx +173 -0
  59. package/src/ui/components/HistoryPanel.jsx +158 -0
  60. package/src/ui/components/MessageList.jsx +235 -0
  61. package/src/ui/components/ModelSelector.jsx +304 -0
  62. package/src/ui/components/PromptInput.jsx +515 -0
  63. package/src/ui/components/StreamingResponse.jsx +134 -0
  64. package/src/ui/components/ThinkingIndicator.jsx +365 -0
  65. package/src/ui/components/ToolExecution.jsx +714 -0
  66. package/src/ui/components/index.js +82 -0
  67. package/src/ui/context/TerminalContext.jsx +150 -0
  68. package/src/ui/context/index.js +13 -0
  69. package/src/ui/hooks/index.js +16 -0
  70. package/src/ui/hooks/useChatState.js +675 -0
  71. package/src/ui/hooks/useCommands.js +280 -0
  72. package/src/ui/hooks/useFileAttachments.js +216 -0
  73. package/src/ui/hooks/useKeyboardShortcuts.js +173 -0
  74. package/src/ui/hooks/useNotifications.js +185 -0
  75. package/src/ui/hooks/useTerminalSize.js +151 -0
  76. package/src/ui/hooks/useWebSocket.js +273 -0
  77. package/src/ui/index.js +94 -0
  78. package/src/ui/ink-runner.js +22 -0
  79. package/src/ui/utils/formatters.js +424 -0
  80. package/src/ui/utils/index.js +6 -0
  81. package/src/ui/utils/markdown.js +166 -0
Binary file
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <text y=".9em" font-size="90">🤖</text>
3
+ </svg>
@@ -0,0 +1 @@
1
+ google-site-verification: google55e5ec47ee14a5f8.html
@@ -0,0 +1,234 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content, viewport-fit=cover"
8
+ />
9
+
10
+ <!-- Primary Meta Tags -->
11
+ <title>Otherwise</title>
12
+ <meta
13
+ name="title"
14
+ content="Otherwise | Local AI Models, ChatGPT, Claude & Gemini"
15
+ />
16
+ <meta
17
+ name="description"
18
+ content="Chat with AI models privately in your browser. Otherwise runs local AI models via WebGPU and supports ChatGPT, Claude, Gemini, Grok. No data leaves your device."
19
+ />
20
+ <meta
21
+ name="keywords"
22
+ content="AI chatbot, local AI, WebGPU, private AI, ChatGPT alternative, Claude AI, Gemini AI, free AI chat, transformers.js"
23
+ />
24
+ <meta name="author" content="Otherwise" />
25
+ <meta name="robots" content="index, follow" />
26
+
27
+ <!-- Favicon -->
28
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
29
+ <link rel="alternate icon" href="/favicon.ico" />
30
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
31
+
32
+ <!-- Open Graph / Facebook -->
33
+ <meta property="og:type" content="website" />
34
+ <meta property="og:url" content="https://otherwise.app/" />
35
+ <meta
36
+ property="og:title"
37
+ content="Otherwise | Local AI Models, ChatGPT, Claude & Gemini"
38
+ />
39
+ <meta
40
+ property="og:description"
41
+ content="Chat with AI models privately in your browser. Runs local AI models via WebGPU and supports OpenAI, Claude, Gemini, Grok."
42
+ />
43
+ <meta property="og:image" content="https://otherwise.app/banner.png" />
44
+ <meta property="og:site_name" content="Otherwise" />
45
+
46
+ <!-- Twitter Card -->
47
+ <meta name="twitter:card" content="summary_large_image" />
48
+ <meta name="twitter:url" content="https://otherwise.app/" />
49
+ <meta
50
+ name="twitter:title"
51
+ content="Otherwise | Local AI Models, ChatGPT, Claude & Gemini"
52
+ />
53
+ <meta
54
+ name="twitter:description"
55
+ content="Chat with AI models privately in your browser. Runs local AI models via WebGPU and supports OpenAI, Claude, Gemini, Grok."
56
+ />
57
+ <meta name="twitter:image" content="https://otherwise.app/banner.png" />
58
+
59
+ <!-- Theme Colors -->
60
+ <meta
61
+ name="theme-color"
62
+ content="#111827"
63
+ media="(prefers-color-scheme: dark)"
64
+ />
65
+ <meta
66
+ name="theme-color"
67
+ content="#ffffff"
68
+ media="(prefers-color-scheme: light)"
69
+ />
70
+
71
+ <!-- PWA Manifest -->
72
+ <link rel="manifest" href="/manifest.json" />
73
+
74
+ <!-- Canonical URL -->
75
+ <link rel="canonical" href="https://otherwise.app/" />
76
+
77
+ <!-- Google Fonts -->
78
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
79
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
80
+ <link
81
+ href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
82
+ rel="stylesheet"
83
+ />
84
+
85
+ <!-- Structured Data -->
86
+ <script type="application/ld+json">
87
+ {
88
+ "@context": "https://schema.org",
89
+ "@type": "WebApplication",
90
+ "name": "Otherwise",
91
+ "url": "https://otherwise.app",
92
+ "description": "A private and powerful AI chatbot that runs locally in your browser",
93
+ "applicationCategory": "UtilitiesApplication",
94
+ "operatingSystem": "Any",
95
+ "offers": {
96
+ "@type": "Offer",
97
+ "price": "0",
98
+ "priceCurrency": "USD"
99
+ },
100
+ "featureList": [
101
+ "ChatGPT integration",
102
+ "Claude AI integration",
103
+ "Gemini AI integration",
104
+ "Local AI models via WebGPU",
105
+ "Voice conversations",
106
+ "AI music generation"
107
+ ]
108
+ }
109
+ </script>
110
+ <script type="module" crossorigin src="/assets/index-Blh8_TEM.js"></script>
111
+ <link rel="stylesheet" crossorigin href="/assets/index-Df737c8w.css">
112
+ </head>
113
+
114
+ <body class="bg-gray-50 dark:bg-gray-900">
115
+ <div id="root"></div>
116
+
117
+ <!-- Apply theme and font preferences before React loads to prevent flash -->
118
+ <script>
119
+ (function () {
120
+ // Apply theme mode
121
+ var themeMode = localStorage.getItem('themeMode');
122
+ // Migrate from old darkMode boolean if it exists
123
+ if (themeMode === null) {
124
+ var oldDarkMode = localStorage.getItem('darkMode');
125
+ if (oldDarkMode !== null) {
126
+ themeMode = JSON.parse(oldDarkMode) ? 'dark' : 'light';
127
+ localStorage.removeItem('darkMode');
128
+ localStorage.setItem('themeMode', themeMode);
129
+ } else {
130
+ themeMode = 'system'; // Default to system mode
131
+ }
132
+ }
133
+
134
+ var isDark;
135
+ if (themeMode === 'system') {
136
+ isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
137
+ } else {
138
+ isDark = themeMode === 'dark';
139
+ }
140
+
141
+ if (isDark) {
142
+ document.documentElement.classList.add('dark');
143
+ }
144
+
145
+ // Apply font family
146
+ var fontFamily = localStorage.getItem('fontFamily');
147
+ if (fontFamily === 'roboto') {
148
+ document.documentElement.classList.add('font-roboto');
149
+ } else if (fontFamily === 'playfair') {
150
+ document.documentElement.classList.add('font-playfair');
151
+ } else if (fontFamily === 'opensans') {
152
+ document.documentElement.classList.add('font-opensans');
153
+ }
154
+ })();
155
+ </script>
156
+
157
+ <!-- Suppress MathJax loader "No version information available" for [tex]/ams, newcommand, noundefined -->
158
+ <script>
159
+ (function () {
160
+ var orig = console.warn;
161
+ console.warn = function () {
162
+ if (arguments[0] && typeof arguments[0] === 'string' && arguments[0].indexOf('No version information available') !== -1) return;
163
+ orig.apply(console, arguments);
164
+ };
165
+ })();
166
+ </script>
167
+ <script>
168
+ window.MathJax = {
169
+ startup: {
170
+ typeset: false, // Prevent initial typeset
171
+ ready: () => {
172
+ MathJax.startup.defaultReady();
173
+ },
174
+ },
175
+ loader: {
176
+ // Suppress version warnings for dynamically loaded components
177
+ source: {},
178
+ require: (url) => {
179
+ return new Promise((resolve, reject) => {
180
+ const script = document.createElement('script');
181
+ script.src = url;
182
+ script.onload = resolve;
183
+ script.onerror = reject;
184
+ document.head.appendChild(script);
185
+ });
186
+ },
187
+ load: [
188
+ '[tex]/ams',
189
+ '[tex]/newcommand',
190
+ '[tex]/noundefined',
191
+ ],
192
+ },
193
+ tex: {
194
+ // NOTE: Single $ delimiters removed to prevent currency symbols from
195
+ // being interpreted as math (e.g., "$89,412" triggering math mode).
196
+ // Use \(...\) for inline math instead.
197
+ inlineMath: [
198
+ ['\\(', '\\)'],
199
+ ],
200
+ displayMath: [
201
+ ['$$', '$$'],
202
+ ['\\[', '\\]'],
203
+ ],
204
+ packages: {
205
+ '[+]': [
206
+ 'ams',
207
+ 'newcommand',
208
+ 'noundefined',
209
+ ],
210
+ },
211
+ },
212
+ svg: {
213
+ fontCache: 'global',
214
+ },
215
+ options: {
216
+ enableMenu: false, // Disable right-click menu
217
+ ignoreHtmlClass: 'mathjax_ignore', // Ignore elements with this class
218
+ renderActions: {
219
+ // Handle any errors gracefully
220
+ assistiveMml: [],
221
+ },
222
+ },
223
+ };
224
+ </script>
225
+ <script
226
+ id="MathJax-script"
227
+ async
228
+ src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
229
+ ></script>
230
+ <!-- Skulpt scripts -->
231
+ <script src="https://cdn.jsdelivr.net/npm/skulpt@1.2.0/dist/skulpt.min.js"></script>
232
+ <script src="https://cdn.jsdelivr.net/npm/skulpt@1.2.0/dist/skulpt-stdlib.js"></script>
233
+ </body>
234
+ </html>
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "Otherwise - AI Chatbot",
3
+ "short_name": "Otherwise",
4
+ "description": "Chat with AI models privately in your browser. Supports ChatGPT, Claude, Gemini, and local AI models.",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "background_color": "#111827",
8
+ "theme_color": "#111827",
9
+ "orientation": "portrait-primary",
10
+ "icons": [
11
+ {
12
+ "src": "/favicon.svg",
13
+ "sizes": "any",
14
+ "type": "image/svg+xml"
15
+ }
16
+ ]
17
+ }