@benzsiangco/jarvis 1.0.0 → 1.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 (55) hide show
  1. package/README.md +5 -0
  2. package/bin/{jarvis.js → jarvis} +1 -1
  3. package/dist/cli.js +476 -350
  4. package/dist/electron/main.js +160 -0
  5. package/dist/electron/preload.js +19 -0
  6. package/package.json +21 -8
  7. package/skills.md +147 -0
  8. package/src/agents/index.ts +248 -0
  9. package/src/brain/loader.ts +136 -0
  10. package/src/cli.ts +411 -0
  11. package/src/config/index.ts +363 -0
  12. package/src/core/executor.ts +222 -0
  13. package/src/core/plugins.ts +148 -0
  14. package/src/core/types.ts +217 -0
  15. package/src/electron/main.ts +192 -0
  16. package/src/electron/preload.ts +25 -0
  17. package/src/electron/types.d.ts +20 -0
  18. package/src/index.ts +12 -0
  19. package/src/providers/antigravity-loader.ts +233 -0
  20. package/src/providers/antigravity.ts +585 -0
  21. package/src/providers/index.ts +523 -0
  22. package/src/sessions/index.ts +194 -0
  23. package/src/tools/index.ts +436 -0
  24. package/src/tui/index.tsx +784 -0
  25. package/src/utils/auth-prompt.ts +394 -0
  26. package/src/utils/index.ts +180 -0
  27. package/src/utils/native-picker.ts +71 -0
  28. package/src/utils/skills.ts +99 -0
  29. package/src/utils/table-integration-examples.ts +617 -0
  30. package/src/utils/table-utils.ts +401 -0
  31. package/src/web/build-ui.ts +27 -0
  32. package/src/web/server.ts +674 -0
  33. package/src/web/ui/dist/.gitkeep +0 -0
  34. package/src/web/ui/dist/main.css +1 -0
  35. package/src/web/ui/dist/main.js +320 -0
  36. package/src/web/ui/dist/main.js.map +20 -0
  37. package/src/web/ui/index.html +46 -0
  38. package/src/web/ui/src/App.tsx +143 -0
  39. package/src/web/ui/src/Modules/Safety/GuardianModal.tsx +83 -0
  40. package/src/web/ui/src/components/Layout/ContextPanel.tsx +243 -0
  41. package/src/web/ui/src/components/Layout/Header.tsx +91 -0
  42. package/src/web/ui/src/components/Layout/ModelSelector.tsx +235 -0
  43. package/src/web/ui/src/components/Layout/SessionStats.tsx +369 -0
  44. package/src/web/ui/src/components/Layout/Sidebar.tsx +895 -0
  45. package/src/web/ui/src/components/Modules/Chat/ChatStage.tsx +620 -0
  46. package/src/web/ui/src/components/Modules/Chat/MessageItem.tsx +446 -0
  47. package/src/web/ui/src/components/Modules/Editor/CommandInspector.tsx +71 -0
  48. package/src/web/ui/src/components/Modules/Editor/DiffViewer.tsx +83 -0
  49. package/src/web/ui/src/components/Modules/Terminal/TabbedTerminal.tsx +202 -0
  50. package/src/web/ui/src/components/Settings/SettingsModal.tsx +935 -0
  51. package/src/web/ui/src/config/models.ts +70 -0
  52. package/src/web/ui/src/main.tsx +13 -0
  53. package/src/web/ui/src/store/agentStore.ts +41 -0
  54. package/src/web/ui/src/store/uiStore.ts +64 -0
  55. package/src/web/ui/src/types/index.ts +54 -0
@@ -0,0 +1,233 @@
1
+ // Antigravity plugin loader adapter for Jarvis
2
+ // This uses Jarvis's own account storage instead of the plugin's storage
3
+ import { loadAccounts as loadJarvisAccounts, saveAccounts as saveJarvisAccounts, refreshAccountToken as jarvisRefreshToken } from './antigravity.js';
4
+ import type { AntigravityAccount, AccountsConfig } from './antigravity.js';
5
+ import { join } from 'path';
6
+ import { homedir } from 'os';
7
+ import crypto from 'crypto';
8
+
9
+ // Import only the request transformation functions, not the full plugin
10
+ import { prepareAntigravityRequest, transformAntigravityResponse } from 'opencode-antigravity-auth/dist/src/plugin/request.js';
11
+
12
+ // Ensure accounts have required fields
13
+ function ensureAccountFields(accounts: AccountsConfig): AccountsConfig {
14
+ const updated = { ...accounts };
15
+ updated.accounts = accounts.accounts.map((acc: any, index) => ({
16
+ id: acc.id || `acc_${Date.now()}_${index}`,
17
+ email: acc.email,
18
+ refreshToken: acc.refreshToken,
19
+ accessToken: acc.accessToken,
20
+ expiresAt: acc.expiresAt,
21
+ projectId: acc.projectId,
22
+ rateLimitedUntil: acc.rateLimitedUntil,
23
+ requestCount: acc.requestCount || 0,
24
+ lastUsed: acc.lastUsed || Date.now(),
25
+ }));
26
+ return updated;
27
+ }
28
+
29
+ // Get next available account with token refresh
30
+ async function getAccountWithToken(): Promise<AntigravityAccount | null> {
31
+ const accountsConfig = ensureAccountFields(loadJarvisAccounts());
32
+
33
+ if (accountsConfig.accounts.length === 0) {
34
+ return null;
35
+ }
36
+
37
+ const account = accountsConfig.accounts[accountsConfig.activeIndex || 0];
38
+
39
+ if (!account) {
40
+ return null;
41
+ }
42
+
43
+ // If no access token or expired, refresh it
44
+ if (!account.accessToken || (account.expiresAt && account.expiresAt < Date.now() + 5 * 60 * 1000)) {
45
+ const refreshed = await jarvisRefreshToken(account);
46
+ if (refreshed) {
47
+ return refreshed;
48
+ }
49
+ }
50
+
51
+ return account;
52
+ }
53
+
54
+ // Track usage
55
+ function trackUsage(accountId: string) {
56
+ const accounts = loadJarvisAccounts();
57
+ const account = accounts.accounts.find(a => (a as any).id === accountId);
58
+ if (account) {
59
+ (account as any).requestCount = ((account as any).requestCount || 0) + 1;
60
+ (account as any).lastUsed = Date.now();
61
+ saveJarvisAccounts(accounts);
62
+ }
63
+ }
64
+
65
+ // Mark rate limited
66
+ function markRateLimited(accountId: string, durationMs: number) {
67
+ const accounts = loadJarvisAccounts();
68
+ const account = accounts.accounts.find(a => (a as any).id === accountId);
69
+ if (account) {
70
+ (account as any).rateLimitedUntil = Date.now() + durationMs;
71
+ saveJarvisAccounts(accounts);
72
+ }
73
+ }
74
+
75
+ // Create a custom fetch function using Jarvis's accounts
76
+ export async function createJarvisAntigravityFetch() {
77
+ // Generate a session ID for signature caching
78
+ const sessionId = `jarvis-${crypto.randomUUID()}`;
79
+
80
+ return async (url: string | URL | Request, init?: RequestInit): Promise<Response> => {
81
+ // Get current account from Jarvis's storage
82
+ let account = await getAccountWithToken();
83
+
84
+ if (!account || !account.accessToken) {
85
+ throw new Error('No Antigravity account available. Run "jarvis auth login"');
86
+ }
87
+
88
+ const urlString = typeof url === 'string' ? url : url instanceof URL ? url.toString() : url.url;
89
+
90
+ // Only process Google Generative Language API requests
91
+ if (!urlString.includes('generativelanguage.googleapis.com')) {
92
+ return fetch(url, init);
93
+ }
94
+
95
+ // Force thinking recovery for all models that may have function calls
96
+ // The thought_signature error happens when function calls are made with thinking models
97
+ // We need to enable forceThinkingRecovery to properly handle the thought signatures
98
+ const bodyStr = typeof init?.body === 'string' ? init.body : '';
99
+ const hasToolsOrFunctions = bodyStr.includes('"tools"') ||
100
+ bodyStr.includes('"functions"') ||
101
+ bodyStr.includes('"function_declarations"') ||
102
+ bodyStr.includes('"functionDeclarations"');
103
+
104
+ // Gemini 3 models and any model with tools need thinking recovery
105
+ const isGemini3 = urlString.includes('gemini-3') || urlString.includes('gemini-2');
106
+ const needsThinkingRecovery = hasToolsOrFunctions && isGemini3;
107
+
108
+ // Extract model name from URL
109
+ const modelMatch = urlString.match(/models\/([^:\/]+)/);
110
+ const requestedModel = modelMatch ? modelMatch[1] : 'unknown';
111
+ const endpoint = 'https://daily-cloudcode-pa.sandbox.googleapis.com';
112
+ const projectId = account.projectId || 'jarvis-default-project';
113
+
114
+ // Use plugin's request preparation
115
+ const prepared = prepareAntigravityRequest(
116
+ urlString,
117
+ init,
118
+ account.accessToken!,
119
+ projectId,
120
+ endpoint,
121
+ 'antigravity',
122
+ needsThinkingRecovery, // Enable forceThinkingRecovery when tools are used
123
+ {} // Options
124
+ );
125
+
126
+ const response = await fetch(prepared.request, prepared.init);
127
+
128
+ if (!response.ok) {
129
+ const errorText = await response.text();
130
+ let errorMessage = `Antigravity error ${response.status}`;
131
+ try {
132
+ const errorJson = JSON.parse(errorText);
133
+ errorMessage = errorJson.error?.message || errorMessage;
134
+ } catch (e) {
135
+ errorMessage = errorText || errorMessage;
136
+ }
137
+ throw new Error(errorMessage);
138
+ }
139
+
140
+ // Handle rate limiting
141
+ if (response.status === 429) {
142
+ const retryAfter = response.headers.get('Retry-After');
143
+ const duration = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
144
+ markRateLimited(account.id, duration);
145
+
146
+ // Try to get another account
147
+ const nextAccount = await getAccountWithToken();
148
+ if (nextAccount && nextAccount.id !== account.id && nextAccount.accessToken) {
149
+ const nextPrepared = prepareAntigravityRequest(
150
+ urlString,
151
+ init,
152
+ nextAccount.accessToken,
153
+ nextAccount.projectId || 'jarvis-default-project',
154
+ endpoint,
155
+ 'antigravity',
156
+ needsThinkingRecovery,
157
+ {}
158
+ );
159
+ const retryResponse = await fetch(nextPrepared.request, nextPrepared.init);
160
+ return transformAntigravityResponse(
161
+ retryResponse,
162
+ prepared.streaming,
163
+ null, // debugContext
164
+ requestedModel,
165
+ projectId,
166
+ endpoint,
167
+ requestedModel, // effectiveModel
168
+ sessionId
169
+ );
170
+ }
171
+ }
172
+
173
+ // Handle auth errors
174
+ if (response.status === 401 || response.status === 403) {
175
+ const refreshed = await jarvisRefreshToken(account);
176
+ if (refreshed) {
177
+ const refreshedPrepared = prepareAntigravityRequest(
178
+ urlString,
179
+ init,
180
+ refreshed.accessToken!,
181
+ refreshed.projectId || 'jarvis-default-project',
182
+ endpoint,
183
+ 'antigravity',
184
+ needsThinkingRecovery,
185
+ {}
186
+ );
187
+ const retryResponse = await fetch(refreshedPrepared.request, refreshedPrepared.init);
188
+ return transformAntigravityResponse(
189
+ retryResponse,
190
+ prepared.streaming,
191
+ null,
192
+ requestedModel,
193
+ projectId,
194
+ endpoint,
195
+ requestedModel,
196
+ sessionId
197
+ );
198
+ }
199
+ }
200
+
201
+ // Track usage
202
+ if (response.ok) {
203
+ trackUsage(account.id);
204
+ }
205
+
206
+ // Transform the response using plugin's logic with full parameters
207
+ return transformAntigravityResponse(
208
+ response,
209
+ prepared.streaming,
210
+ null, // debugContext
211
+ requestedModel,
212
+ projectId,
213
+ endpoint,
214
+ requestedModel, // effectiveModel
215
+ sessionId
216
+ );
217
+ };
218
+ }
219
+
220
+ // Initialize with Jarvis's accounts only
221
+ export async function initializeAntigravityLoader() {
222
+ try {
223
+ // Ensure accounts have proper format
224
+ const accounts = ensureAccountFields(loadJarvisAccounts());
225
+ saveJarvisAccounts(accounts);
226
+
227
+ // Return the custom fetch function that uses Jarvis accounts
228
+ return await createJarvisAntigravityFetch();
229
+ } catch (error) {
230
+ console.error('Failed to initialize Antigravity loader:', error);
231
+ throw error;
232
+ }
233
+ }