antigravity-auth 1.6.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.
- package/README.md +61 -0
- package/dist/antigravity/oauth.d.ts +30 -0
- package/dist/antigravity/oauth.js +170 -0
- package/dist/claude/login.d.ts +7 -0
- package/dist/claude/login.js +480 -0
- package/dist/claude/menu-helpers.d.ts +22 -0
- package/dist/claude/menu-helpers.js +281 -0
- package/dist/claude/proxy-manager.d.ts +11 -0
- package/dist/claude/proxy-manager.js +129 -0
- package/dist/claude/proxy.d.ts +1 -0
- package/dist/claude/proxy.js +733 -0
- package/dist/constants.d.ts +138 -0
- package/dist/constants.js +216 -0
- package/dist/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/hooks/auto-update-checker/cache.js +70 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/hooks/auto-update-checker/checker.js +233 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/hooks/auto-update-checker/constants.js +22 -0
- package/dist/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/hooks/auto-update-checker/index.js +121 -0
- package/dist/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/hooks/auto-update-checker/logging.js +8 -0
- package/dist/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/hooks/auto-update-checker/types.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/opencode/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/opencode/hooks/auto-update-checker/cache.js +70 -0
- package/dist/opencode/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/opencode/hooks/auto-update-checker/checker.js +233 -0
- package/dist/opencode/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/opencode/hooks/auto-update-checker/constants.js +22 -0
- package/dist/opencode/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/opencode/hooks/auto-update-checker/index.js +121 -0
- package/dist/opencode/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/opencode/hooks/auto-update-checker/logging.js +8 -0
- package/dist/opencode/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/opencode/hooks/auto-update-checker/types.js +1 -0
- package/dist/opencode/plugin.d.ts +29 -0
- package/dist/opencode/plugin.js +2954 -0
- package/dist/plugin/accounts.d.ts +173 -0
- package/dist/plugin/accounts.js +966 -0
- package/dist/plugin/auth.d.ts +20 -0
- package/dist/plugin/auth.js +44 -0
- package/dist/plugin/cache/index.d.ts +4 -0
- package/dist/plugin/cache/index.js +4 -0
- package/dist/plugin/cache/signature-cache.d.ts +110 -0
- package/dist/plugin/cache/signature-cache.js +347 -0
- package/dist/plugin/cache.d.ts +43 -0
- package/dist/plugin/cache.js +180 -0
- package/dist/plugin/cli.d.ts +26 -0
- package/dist/plugin/cli.js +126 -0
- package/dist/plugin/config/index.d.ts +15 -0
- package/dist/plugin/config/index.js +15 -0
- package/dist/plugin/config/loader.d.ts +38 -0
- package/dist/plugin/config/loader.js +150 -0
- package/dist/plugin/config/models.d.ts +26 -0
- package/dist/plugin/config/models.js +95 -0
- package/dist/plugin/config/schema.d.ts +144 -0
- package/dist/plugin/config/schema.js +458 -0
- package/dist/plugin/config/updater.d.ts +76 -0
- package/dist/plugin/config/updater.js +205 -0
- package/dist/plugin/core/streaming/index.d.ts +2 -0
- package/dist/plugin/core/streaming/index.js +2 -0
- package/dist/plugin/core/streaming/transformer.d.ts +9 -0
- package/dist/plugin/core/streaming/transformer.js +301 -0
- package/dist/plugin/core/streaming/types.d.ts +28 -0
- package/dist/plugin/core/streaming/types.js +1 -0
- package/dist/plugin/debug.d.ts +93 -0
- package/dist/plugin/debug.js +375 -0
- package/dist/plugin/errors.d.ts +27 -0
- package/dist/plugin/errors.js +41 -0
- package/dist/plugin/fingerprint.d.ts +69 -0
- package/dist/plugin/fingerprint.js +137 -0
- package/dist/plugin/image-saver.d.ts +24 -0
- package/dist/plugin/image-saver.js +78 -0
- package/dist/plugin/logger.d.ts +35 -0
- package/dist/plugin/logger.js +67 -0
- package/dist/plugin/logging-utils.d.ts +22 -0
- package/dist/plugin/logging-utils.js +91 -0
- package/dist/plugin/project.d.ts +32 -0
- package/dist/plugin/project.js +229 -0
- package/dist/plugin/quota.d.ts +34 -0
- package/dist/plugin/quota.js +261 -0
- package/dist/plugin/recovery/constants.d.ts +21 -0
- package/dist/plugin/recovery/constants.js +42 -0
- package/dist/plugin/recovery/index.d.ts +11 -0
- package/dist/plugin/recovery/index.js +11 -0
- package/dist/plugin/recovery/storage.d.ts +23 -0
- package/dist/plugin/recovery/storage.js +340 -0
- package/dist/plugin/recovery/types.d.ts +115 -0
- package/dist/plugin/recovery/types.js +6 -0
- package/dist/plugin/recovery.d.ts +60 -0
- package/dist/plugin/recovery.js +360 -0
- package/dist/plugin/refresh-queue.d.ts +99 -0
- package/dist/plugin/refresh-queue.js +235 -0
- package/dist/plugin/request-helpers.d.ts +281 -0
- package/dist/plugin/request-helpers.js +2200 -0
- package/dist/plugin/request.d.ts +110 -0
- package/dist/plugin/request.js +1489 -0
- package/dist/plugin/rotation.d.ts +182 -0
- package/dist/plugin/rotation.js +364 -0
- package/dist/plugin/search.d.ts +31 -0
- package/dist/plugin/search.js +185 -0
- package/dist/plugin/server.d.ts +22 -0
- package/dist/plugin/server.js +306 -0
- package/dist/plugin/storage.d.ts +136 -0
- package/dist/plugin/storage.js +599 -0
- package/dist/plugin/stores/signature-store.d.ts +4 -0
- package/dist/plugin/stores/signature-store.js +24 -0
- package/dist/plugin/thinking-recovery.d.ts +89 -0
- package/dist/plugin/thinking-recovery.js +289 -0
- package/dist/plugin/token.d.ts +18 -0
- package/dist/plugin/token.js +127 -0
- package/dist/plugin/transform/claude.d.ts +79 -0
- package/dist/plugin/transform/claude.js +256 -0
- package/dist/plugin/transform/cross-model-sanitizer.d.ts +34 -0
- package/dist/plugin/transform/cross-model-sanitizer.js +224 -0
- package/dist/plugin/transform/gemini.d.ts +132 -0
- package/dist/plugin/transform/gemini.js +659 -0
- package/dist/plugin/transform/index.d.ts +14 -0
- package/dist/plugin/transform/index.js +9 -0
- package/dist/plugin/transform/model-resolver.d.ts +98 -0
- package/dist/plugin/transform/model-resolver.js +320 -0
- package/dist/plugin/transform/types.d.ts +110 -0
- package/dist/plugin/transform/types.js +1 -0
- package/dist/plugin/types.d.ts +95 -0
- package/dist/plugin/types.js +1 -0
- package/dist/plugin/ui/ansi.d.ts +31 -0
- package/dist/plugin/ui/ansi.js +45 -0
- package/dist/plugin/ui/auth-menu.d.ts +47 -0
- package/dist/plugin/ui/auth-menu.js +199 -0
- package/dist/plugin/ui/confirm.d.ts +1 -0
- package/dist/plugin/ui/confirm.js +14 -0
- package/dist/plugin/ui/select.d.ts +22 -0
- package/dist/plugin/ui/select.js +243 -0
- package/dist/plugin/version.d.ts +18 -0
- package/dist/plugin/version.js +79 -0
- package/dist/src/antigravity/oauth.d.ts +30 -0
- package/dist/src/antigravity/oauth.js +170 -0
- package/dist/src/constants.d.ts +138 -0
- package/dist/src/constants.js +216 -0
- package/dist/src/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/src/hooks/auto-update-checker/cache.js +70 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/src/hooks/auto-update-checker/checker.js +233 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/src/hooks/auto-update-checker/constants.js +22 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/src/hooks/auto-update-checker/index.js +121 -0
- package/dist/src/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/src/hooks/auto-update-checker/logging.js +8 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/src/hooks/auto-update-checker/types.js +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +5 -0
- package/dist/src/plugin/accounts.d.ts +173 -0
- package/dist/src/plugin/accounts.js +966 -0
- package/dist/src/plugin/auth.d.ts +20 -0
- package/dist/src/plugin/auth.js +44 -0
- package/dist/src/plugin/cache/index.d.ts +4 -0
- package/dist/src/plugin/cache/index.js +4 -0
- package/dist/src/plugin/cache/signature-cache.d.ts +110 -0
- package/dist/src/plugin/cache/signature-cache.js +347 -0
- package/dist/src/plugin/cache.d.ts +43 -0
- package/dist/src/plugin/cache.js +180 -0
- package/dist/src/plugin/cli.d.ts +26 -0
- package/dist/src/plugin/cli.js +126 -0
- package/dist/src/plugin/config/index.d.ts +15 -0
- package/dist/src/plugin/config/index.js +15 -0
- package/dist/src/plugin/config/loader.d.ts +38 -0
- package/dist/src/plugin/config/loader.js +150 -0
- package/dist/src/plugin/config/models.d.ts +26 -0
- package/dist/src/plugin/config/models.js +95 -0
- package/dist/src/plugin/config/schema.d.ts +144 -0
- package/dist/src/plugin/config/schema.js +458 -0
- package/dist/src/plugin/config/updater.d.ts +76 -0
- package/dist/src/plugin/config/updater.js +205 -0
- package/dist/src/plugin/core/streaming/index.d.ts +2 -0
- package/dist/src/plugin/core/streaming/index.js +2 -0
- package/dist/src/plugin/core/streaming/transformer.d.ts +9 -0
- package/dist/src/plugin/core/streaming/transformer.js +301 -0
- package/dist/src/plugin/core/streaming/types.d.ts +28 -0
- package/dist/src/plugin/core/streaming/types.js +1 -0
- package/dist/src/plugin/debug.d.ts +93 -0
- package/dist/src/plugin/debug.js +375 -0
- package/dist/src/plugin/errors.d.ts +27 -0
- package/dist/src/plugin/errors.js +41 -0
- package/dist/src/plugin/fingerprint.d.ts +69 -0
- package/dist/src/plugin/fingerprint.js +137 -0
- package/dist/src/plugin/image-saver.d.ts +24 -0
- package/dist/src/plugin/image-saver.js +78 -0
- package/dist/src/plugin/logger.d.ts +35 -0
- package/dist/src/plugin/logger.js +67 -0
- package/dist/src/plugin/logging-utils.d.ts +22 -0
- package/dist/src/plugin/logging-utils.js +91 -0
- package/dist/src/plugin/project.d.ts +32 -0
- package/dist/src/plugin/project.js +229 -0
- package/dist/src/plugin/quota.d.ts +34 -0
- package/dist/src/plugin/quota.js +261 -0
- package/dist/src/plugin/recovery/constants.d.ts +21 -0
- package/dist/src/plugin/recovery/constants.js +42 -0
- package/dist/src/plugin/recovery/index.d.ts +11 -0
- package/dist/src/plugin/recovery/index.js +11 -0
- package/dist/src/plugin/recovery/storage.d.ts +23 -0
- package/dist/src/plugin/recovery/storage.js +340 -0
- package/dist/src/plugin/recovery/types.d.ts +115 -0
- package/dist/src/plugin/recovery/types.js +6 -0
- package/dist/src/plugin/recovery.d.ts +60 -0
- package/dist/src/plugin/recovery.js +360 -0
- package/dist/src/plugin/refresh-queue.d.ts +99 -0
- package/dist/src/plugin/refresh-queue.js +235 -0
- package/dist/src/plugin/request-helpers.d.ts +281 -0
- package/dist/src/plugin/request-helpers.js +2200 -0
- package/dist/src/plugin/request.d.ts +110 -0
- package/dist/src/plugin/request.js +1489 -0
- package/dist/src/plugin/rotation.d.ts +182 -0
- package/dist/src/plugin/rotation.js +364 -0
- package/dist/src/plugin/search.d.ts +31 -0
- package/dist/src/plugin/search.js +185 -0
- package/dist/src/plugin/server.d.ts +22 -0
- package/dist/src/plugin/server.js +306 -0
- package/dist/src/plugin/storage.d.ts +136 -0
- package/dist/src/plugin/storage.js +599 -0
- package/dist/src/plugin/stores/signature-store.d.ts +4 -0
- package/dist/src/plugin/stores/signature-store.js +24 -0
- package/dist/src/plugin/thinking-recovery.d.ts +89 -0
- package/dist/src/plugin/thinking-recovery.js +289 -0
- package/dist/src/plugin/token.d.ts +18 -0
- package/dist/src/plugin/token.js +127 -0
- package/dist/src/plugin/transform/claude.d.ts +79 -0
- package/dist/src/plugin/transform/claude.js +256 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +34 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.js +224 -0
- package/dist/src/plugin/transform/gemini.d.ts +132 -0
- package/dist/src/plugin/transform/gemini.js +659 -0
- package/dist/src/plugin/transform/index.d.ts +14 -0
- package/dist/src/plugin/transform/index.js +9 -0
- package/dist/src/plugin/transform/model-resolver.d.ts +98 -0
- package/dist/src/plugin/transform/model-resolver.js +320 -0
- package/dist/src/plugin/transform/types.d.ts +110 -0
- package/dist/src/plugin/transform/types.js +1 -0
- package/dist/src/plugin/types.d.ts +95 -0
- package/dist/src/plugin/types.js +1 -0
- package/dist/src/plugin/ui/ansi.d.ts +31 -0
- package/dist/src/plugin/ui/ansi.js +45 -0
- package/dist/src/plugin/ui/auth-menu.d.ts +47 -0
- package/dist/src/plugin/ui/auth-menu.js +199 -0
- package/dist/src/plugin/ui/confirm.d.ts +1 -0
- package/dist/src/plugin/ui/confirm.js +14 -0
- package/dist/src/plugin/ui/select.d.ts +22 -0
- package/dist/src/plugin/ui/select.js +243 -0
- package/dist/src/plugin/version.d.ts +18 -0
- package/dist/src/plugin/version.js +79 -0
- package/package.json +54 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Saving Utility
|
|
3
|
+
*
|
|
4
|
+
* Handles saving generated images to disk and returning file paths.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
/**
|
|
10
|
+
* Default directory for saving generated images.
|
|
11
|
+
* Uses ~/.opencode/generated-images/
|
|
12
|
+
*/
|
|
13
|
+
function getImageOutputDir() {
|
|
14
|
+
const homeDir = os.homedir();
|
|
15
|
+
const outputDir = path.join(homeDir, '.opencode', 'generated-images');
|
|
16
|
+
if (!fs.existsSync(outputDir)) {
|
|
17
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
return outputDir;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate a unique filename for the image.
|
|
23
|
+
*/
|
|
24
|
+
function generateImageFilename(mimeType) {
|
|
25
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
26
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
27
|
+
let ext = 'png';
|
|
28
|
+
if (mimeType.includes('jpeg') || mimeType.includes('jpg')) {
|
|
29
|
+
ext = 'jpg';
|
|
30
|
+
}
|
|
31
|
+
else if (mimeType.includes('gif')) {
|
|
32
|
+
ext = 'gif';
|
|
33
|
+
}
|
|
34
|
+
else if (mimeType.includes('webp')) {
|
|
35
|
+
ext = 'webp';
|
|
36
|
+
}
|
|
37
|
+
return `image-${timestamp}-${random}.${ext}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Save base64 image data to disk and return the file path.
|
|
41
|
+
*
|
|
42
|
+
* @param base64Data - The base64-encoded image data
|
|
43
|
+
* @param mimeType - The MIME type of the image (e.g., "image/jpeg")
|
|
44
|
+
* @returns The absolute path to the saved image file
|
|
45
|
+
*/
|
|
46
|
+
export function saveImageToDisk(base64Data, mimeType) {
|
|
47
|
+
try {
|
|
48
|
+
const outputDir = getImageOutputDir();
|
|
49
|
+
const filename = generateImageFilename(mimeType);
|
|
50
|
+
const filePath = path.join(outputDir, filename);
|
|
51
|
+
const buffer = Buffer.from(base64Data, 'base64');
|
|
52
|
+
fs.writeFileSync(filePath, buffer);
|
|
53
|
+
return filePath;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('[image-saver] Failed to save image:', error);
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Process inlineData and return either a file path or base64 data URL.
|
|
62
|
+
* Attempts to save to disk first, falls back to base64 if saving fails.
|
|
63
|
+
*
|
|
64
|
+
* @param inlineData - Object containing mimeType and base64 data
|
|
65
|
+
* @returns Markdown image string with either file path or data URL
|
|
66
|
+
*/
|
|
67
|
+
export function processImageData(inlineData) {
|
|
68
|
+
const mimeType = inlineData.mimeType || 'image/png';
|
|
69
|
+
const data = inlineData.data;
|
|
70
|
+
if (!data) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const filePath = saveImageToDisk(data, mimeType);
|
|
74
|
+
if (filePath) {
|
|
75
|
+
return `\n\nImage saved to: \`${filePath}\`\n\nTo view: \`open "${filePath}"\``;
|
|
76
|
+
}
|
|
77
|
+
return ``;
|
|
78
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logger for Antigravity Plugin
|
|
3
|
+
*
|
|
4
|
+
* Logging behavior:
|
|
5
|
+
* - debug controls file logs only (via debug.ts)
|
|
6
|
+
* - debug_tui controls TUI log panel only
|
|
7
|
+
* - either sink can be enabled independently
|
|
8
|
+
* - OPENCODE_ANTIGRAVITY_CONSOLE_LOG=1 → console output (independent of debug flags)
|
|
9
|
+
*/
|
|
10
|
+
import type { PluginClient } from "./types";
|
|
11
|
+
export interface Logger {
|
|
12
|
+
debug(message: string, extra?: Record<string, unknown>): void;
|
|
13
|
+
info(message: string, extra?: Record<string, unknown>): void;
|
|
14
|
+
warn(message: string, extra?: Record<string, unknown>): void;
|
|
15
|
+
error(message: string, extra?: Record<string, unknown>): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Initialize the logger with the plugin client.
|
|
19
|
+
* Must be called during plugin initialization to enable TUI logging.
|
|
20
|
+
*/
|
|
21
|
+
export declare function initLogger(client: PluginClient): void;
|
|
22
|
+
/**
|
|
23
|
+
* Create a logger instance for a specific module.
|
|
24
|
+
*
|
|
25
|
+
* @param module - The module name (e.g., "refresh-queue", "transform.claude")
|
|
26
|
+
* @returns Logger instance with debug, info, warn, error methods
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const log = createLogger("refresh-queue");
|
|
31
|
+
* log.debug("Checking tokens", { count: 5 });
|
|
32
|
+
* log.warn("Token expired", { accountIndex: 0 });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function createLogger(module: string): Logger;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logger for Antigravity Plugin
|
|
3
|
+
*
|
|
4
|
+
* Logging behavior:
|
|
5
|
+
* - debug controls file logs only (via debug.ts)
|
|
6
|
+
* - debug_tui controls TUI log panel only
|
|
7
|
+
* - either sink can be enabled independently
|
|
8
|
+
* - OPENCODE_ANTIGRAVITY_CONSOLE_LOG=1 → console output (independent of debug flags)
|
|
9
|
+
*/
|
|
10
|
+
import { isDebugTuiEnabled } from "./debug";
|
|
11
|
+
import { isTruthyFlag, writeConsoleLog, } from "./logging-utils";
|
|
12
|
+
const ENV_CONSOLE_LOG = "OPENCODE_ANTIGRAVITY_CONSOLE_LOG";
|
|
13
|
+
let _client = null;
|
|
14
|
+
/**
|
|
15
|
+
* Check if console logging is enabled via environment variable.
|
|
16
|
+
*/
|
|
17
|
+
function isConsoleLogEnabled() {
|
|
18
|
+
return isTruthyFlag(process.env[ENV_CONSOLE_LOG]);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the logger with the plugin client.
|
|
22
|
+
* Must be called during plugin initialization to enable TUI logging.
|
|
23
|
+
*/
|
|
24
|
+
export function initLogger(client) {
|
|
25
|
+
_client = client;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a logger instance for a specific module.
|
|
29
|
+
*
|
|
30
|
+
* @param module - The module name (e.g., "refresh-queue", "transform.claude")
|
|
31
|
+
* @returns Logger instance with debug, info, warn, error methods
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const log = createLogger("refresh-queue");
|
|
36
|
+
* log.debug("Checking tokens", { count: 5 });
|
|
37
|
+
* log.warn("Token expired", { accountIndex: 0 });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function createLogger(module) {
|
|
41
|
+
const service = `antigravity.${module}`;
|
|
42
|
+
const log = (level, message, extra) => {
|
|
43
|
+
// TUI logging: controlled only by debug_tui policy
|
|
44
|
+
if (isDebugTuiEnabled()) {
|
|
45
|
+
const app = _client?.app;
|
|
46
|
+
if (app && typeof app.log === "function") {
|
|
47
|
+
app
|
|
48
|
+
.log({
|
|
49
|
+
body: { service, level, message, extra },
|
|
50
|
+
})
|
|
51
|
+
.catch(() => {
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (isConsoleLogEnabled()) {
|
|
56
|
+
const prefix = `[${service}]`;
|
|
57
|
+
const args = extra ? [prefix, message, extra] : [prefix, message];
|
|
58
|
+
writeConsoleLog(level, ...args);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
debug: (message, extra) => log("debug", message, extra),
|
|
63
|
+
info: (message, extra) => log("info", message, extra),
|
|
64
|
+
warn: (message, extra) => log("warn", message, extra),
|
|
65
|
+
error: (message, extra) => log("error", message, extra),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
2
|
+
export interface DebugPolicyInput {
|
|
3
|
+
configDebug: boolean;
|
|
4
|
+
configDebugTui: boolean;
|
|
5
|
+
envDebugFlag?: string;
|
|
6
|
+
envDebugTuiFlag?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DebugPolicy {
|
|
9
|
+
debugLevel: number;
|
|
10
|
+
debugEnabled: boolean;
|
|
11
|
+
debugTuiEnabled: boolean;
|
|
12
|
+
verboseEnabled: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function isTruthyFlag(flag?: string): boolean;
|
|
15
|
+
export declare function parseDebugLevel(flag: string): number;
|
|
16
|
+
export declare function deriveDebugPolicy(input: DebugPolicyInput): DebugPolicy;
|
|
17
|
+
export declare function formatAccountLabel(email: string | undefined, accountIndex: number): string;
|
|
18
|
+
export declare function formatAccountContextLabel(email: string | undefined, accountIndex: number): string;
|
|
19
|
+
export declare function formatErrorForLog(error: unknown): string;
|
|
20
|
+
export declare function truncateTextForLog(text: string, maxChars: number): string;
|
|
21
|
+
export declare function formatBodyPreviewForLog(body: BodyInit | null | undefined, maxChars: number): string | undefined;
|
|
22
|
+
export declare function writeConsoleLog(level: LogLevel, ...args: unknown[]): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export function isTruthyFlag(flag) {
|
|
2
|
+
return flag === "1" || flag?.toLowerCase() === "true";
|
|
3
|
+
}
|
|
4
|
+
export function parseDebugLevel(flag) {
|
|
5
|
+
const trimmed = flag.trim();
|
|
6
|
+
if (trimmed === "2" || trimmed === "verbose")
|
|
7
|
+
return 2;
|
|
8
|
+
if (trimmed === "1" || trimmed === "true")
|
|
9
|
+
return 1;
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
export function deriveDebugPolicy(input) {
|
|
13
|
+
const envDebugFlag = input.envDebugFlag ?? "";
|
|
14
|
+
const debugLevel = input.configDebug
|
|
15
|
+
? envDebugFlag === "2" || envDebugFlag === "verbose"
|
|
16
|
+
? 2
|
|
17
|
+
: 1
|
|
18
|
+
: parseDebugLevel(envDebugFlag);
|
|
19
|
+
const debugEnabled = debugLevel >= 1;
|
|
20
|
+
const verboseEnabled = debugLevel >= 2;
|
|
21
|
+
const debugTuiEnabled = debugEnabled && (input.configDebugTui || isTruthyFlag(input.envDebugTuiFlag));
|
|
22
|
+
return {
|
|
23
|
+
debugLevel,
|
|
24
|
+
debugEnabled,
|
|
25
|
+
debugTuiEnabled,
|
|
26
|
+
verboseEnabled,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function formatAccountLabel(email, accountIndex) {
|
|
30
|
+
return email || `Account ${accountIndex + 1}`;
|
|
31
|
+
}
|
|
32
|
+
export function formatAccountContextLabel(email, accountIndex) {
|
|
33
|
+
if (email) {
|
|
34
|
+
return email;
|
|
35
|
+
}
|
|
36
|
+
if (accountIndex >= 0) {
|
|
37
|
+
return `Account ${accountIndex + 1}`;
|
|
38
|
+
}
|
|
39
|
+
return "All accounts";
|
|
40
|
+
}
|
|
41
|
+
export function formatErrorForLog(error) {
|
|
42
|
+
if (error instanceof Error) {
|
|
43
|
+
return error.stack ?? error.message;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
return JSON.stringify(error);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return String(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function truncateTextForLog(text, maxChars) {
|
|
53
|
+
if (text.length <= maxChars) {
|
|
54
|
+
return text;
|
|
55
|
+
}
|
|
56
|
+
return `${text.slice(0, maxChars)}... (truncated ${text.length - maxChars} chars)`;
|
|
57
|
+
}
|
|
58
|
+
export function formatBodyPreviewForLog(body, maxChars) {
|
|
59
|
+
if (body == null) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (typeof body === "string") {
|
|
63
|
+
return truncateTextForLog(body, maxChars);
|
|
64
|
+
}
|
|
65
|
+
if (body instanceof URLSearchParams) {
|
|
66
|
+
return truncateTextForLog(body.toString(), maxChars);
|
|
67
|
+
}
|
|
68
|
+
if (typeof Blob !== "undefined" && body instanceof Blob) {
|
|
69
|
+
return `[Blob size=${body.size}]`;
|
|
70
|
+
}
|
|
71
|
+
if (typeof FormData !== "undefined" && body instanceof FormData) {
|
|
72
|
+
return "[FormData payload omitted]";
|
|
73
|
+
}
|
|
74
|
+
return `[${body.constructor?.name ?? typeof body} payload omitted]`;
|
|
75
|
+
}
|
|
76
|
+
export function writeConsoleLog(level, ...args) {
|
|
77
|
+
switch (level) {
|
|
78
|
+
case "debug":
|
|
79
|
+
console.debug(...args);
|
|
80
|
+
break;
|
|
81
|
+
case "info":
|
|
82
|
+
console.info(...args);
|
|
83
|
+
break;
|
|
84
|
+
case "warn":
|
|
85
|
+
console.warn(...args);
|
|
86
|
+
break;
|
|
87
|
+
case "error":
|
|
88
|
+
console.error(...args);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { OAuthAuthDetails, ProjectContextResult } from "./types";
|
|
2
|
+
interface AntigravityUserTier {
|
|
3
|
+
id?: string;
|
|
4
|
+
isDefault?: boolean;
|
|
5
|
+
userDefinedCloudaicompanionProject?: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface LoadCodeAssistPayload {
|
|
8
|
+
cloudaicompanionProject?: string | {
|
|
9
|
+
id?: string;
|
|
10
|
+
};
|
|
11
|
+
currentTier?: {
|
|
12
|
+
id?: string;
|
|
13
|
+
};
|
|
14
|
+
allowedTiers?: AntigravityUserTier[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Clears cached project context results and pending promises, globally or for a refresh key.
|
|
18
|
+
*/
|
|
19
|
+
export declare function invalidateProjectContextCache(refresh?: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Loads managed project information for the given access token and optional project.
|
|
22
|
+
*/
|
|
23
|
+
export declare function loadManagedProject(accessToken: string, projectId?: string): Promise<LoadCodeAssistPayload | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Onboards a managed project for the user, optionally retrying until completion.
|
|
26
|
+
*/
|
|
27
|
+
export declare function onboardManagedProject(accessToken: string, tierId: string, projectId?: string, attempts?: number, delayMs?: number): Promise<string | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves an effective project ID for the current auth state, caching results per refresh token.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ensureProjectContext(auth: OAuthAuthDetails): Promise<ProjectContextResult>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { getAntigravityHeaders, ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_LOAD_ENDPOINTS, ANTIGRAVITY_DEFAULT_PROJECT_ID, } from "../constants";
|
|
2
|
+
import { formatRefreshParts, parseRefreshParts } from "./auth";
|
|
3
|
+
import { createLogger } from "./logger";
|
|
4
|
+
const log = createLogger("project");
|
|
5
|
+
const projectContextResultCache = new Map();
|
|
6
|
+
const projectContextPendingCache = new Map();
|
|
7
|
+
const CODE_ASSIST_METADATA = {
|
|
8
|
+
ideType: "ANTIGRAVITY",
|
|
9
|
+
platform: process.platform === "win32" ? "WINDOWS" : "MACOS",
|
|
10
|
+
pluginType: "GEMINI",
|
|
11
|
+
};
|
|
12
|
+
function buildMetadata(projectId) {
|
|
13
|
+
const metadata = {
|
|
14
|
+
ideType: CODE_ASSIST_METADATA.ideType,
|
|
15
|
+
platform: CODE_ASSIST_METADATA.platform,
|
|
16
|
+
pluginType: CODE_ASSIST_METADATA.pluginType,
|
|
17
|
+
};
|
|
18
|
+
if (projectId) {
|
|
19
|
+
metadata.duetProject = projectId;
|
|
20
|
+
}
|
|
21
|
+
return metadata;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Selects the default tier ID from the allowed tiers list.
|
|
25
|
+
*/
|
|
26
|
+
function getDefaultTierId(allowedTiers) {
|
|
27
|
+
if (!allowedTiers || allowedTiers.length === 0) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
for (const tier of allowedTiers) {
|
|
31
|
+
if (tier?.isDefault) {
|
|
32
|
+
return tier.id;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return allowedTiers[0]?.id;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Promise-based delay utility.
|
|
39
|
+
*/
|
|
40
|
+
function wait(ms) {
|
|
41
|
+
return new Promise(function (resolve) {
|
|
42
|
+
setTimeout(resolve, ms);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extracts the cloudaicompanion project id from loadCodeAssist responses.
|
|
47
|
+
*/
|
|
48
|
+
function extractManagedProjectId(payload) {
|
|
49
|
+
if (!payload) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
if (typeof payload.cloudaicompanionProject === "string") {
|
|
53
|
+
return payload.cloudaicompanionProject;
|
|
54
|
+
}
|
|
55
|
+
if (payload.cloudaicompanionProject && typeof payload.cloudaicompanionProject.id === "string") {
|
|
56
|
+
return payload.cloudaicompanionProject.id;
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generates a cache key for project context based on refresh token.
|
|
62
|
+
*/
|
|
63
|
+
function getCacheKey(auth) {
|
|
64
|
+
const refresh = auth.refresh?.trim();
|
|
65
|
+
return refresh ? refresh : undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Clears cached project context results and pending promises, globally or for a refresh key.
|
|
69
|
+
*/
|
|
70
|
+
export function invalidateProjectContextCache(refresh) {
|
|
71
|
+
if (!refresh) {
|
|
72
|
+
projectContextPendingCache.clear();
|
|
73
|
+
projectContextResultCache.clear();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
projectContextPendingCache.delete(refresh);
|
|
77
|
+
projectContextResultCache.delete(refresh);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Loads managed project information for the given access token and optional project.
|
|
81
|
+
*/
|
|
82
|
+
export async function loadManagedProject(accessToken, projectId) {
|
|
83
|
+
const metadata = buildMetadata(projectId);
|
|
84
|
+
const requestBody = { metadata };
|
|
85
|
+
const loadHeaders = {
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
Authorization: `Bearer ${accessToken}`,
|
|
88
|
+
"User-Agent": "google-api-nodejs-client/9.15.1",
|
|
89
|
+
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
90
|
+
"Client-Metadata": getAntigravityHeaders()["Client-Metadata"],
|
|
91
|
+
};
|
|
92
|
+
const loadEndpoints = Array.from(new Set([...ANTIGRAVITY_LOAD_ENDPOINTS, ...ANTIGRAVITY_ENDPOINT_FALLBACKS]));
|
|
93
|
+
for (const baseEndpoint of loadEndpoints) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch(`${baseEndpoint}/v1internal:loadCodeAssist`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: loadHeaders,
|
|
98
|
+
body: JSON.stringify(requestBody),
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
return (await response.json());
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
log.debug("Failed to load managed project", { endpoint: baseEndpoint, error: String(error) });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Onboards a managed project for the user, optionally retrying until completion.
|
|
114
|
+
*/
|
|
115
|
+
export async function onboardManagedProject(accessToken, tierId, projectId, attempts = 10, delayMs = 5000) {
|
|
116
|
+
const metadata = buildMetadata(projectId);
|
|
117
|
+
const requestBody = {
|
|
118
|
+
tierId,
|
|
119
|
+
metadata,
|
|
120
|
+
};
|
|
121
|
+
for (const baseEndpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
|
|
122
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
123
|
+
try {
|
|
124
|
+
const response = await fetch(`${baseEndpoint}/v1internal:onboardUser`, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json",
|
|
128
|
+
Authorization: `Bearer ${accessToken}`,
|
|
129
|
+
...getAntigravityHeaders(),
|
|
130
|
+
},
|
|
131
|
+
body: JSON.stringify(requestBody),
|
|
132
|
+
});
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
const payload = (await response.json());
|
|
137
|
+
const managedProjectId = payload.response?.cloudaicompanionProject?.id;
|
|
138
|
+
if (payload.done && managedProjectId) {
|
|
139
|
+
return managedProjectId;
|
|
140
|
+
}
|
|
141
|
+
if (payload.done && projectId) {
|
|
142
|
+
return projectId;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
log.debug("Failed to onboard managed project", { endpoint: baseEndpoint, error: String(error) });
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
await wait(delayMs);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Resolves an effective project ID for the current auth state, caching results per refresh token.
|
|
156
|
+
*/
|
|
157
|
+
export async function ensureProjectContext(auth) {
|
|
158
|
+
const accessToken = auth.access;
|
|
159
|
+
if (!accessToken) {
|
|
160
|
+
return { auth, effectiveProjectId: "" };
|
|
161
|
+
}
|
|
162
|
+
const cacheKey = getCacheKey(auth);
|
|
163
|
+
if (cacheKey) {
|
|
164
|
+
const cached = projectContextResultCache.get(cacheKey);
|
|
165
|
+
if (cached) {
|
|
166
|
+
return cached;
|
|
167
|
+
}
|
|
168
|
+
const pending = projectContextPendingCache.get(cacheKey);
|
|
169
|
+
if (pending) {
|
|
170
|
+
return pending;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const resolveContext = async () => {
|
|
174
|
+
const parts = parseRefreshParts(auth.refresh);
|
|
175
|
+
if (parts.managedProjectId) {
|
|
176
|
+
return { auth, effectiveProjectId: parts.managedProjectId };
|
|
177
|
+
}
|
|
178
|
+
const fallbackProjectId = ANTIGRAVITY_DEFAULT_PROJECT_ID;
|
|
179
|
+
const persistManagedProject = async (managedProjectId) => {
|
|
180
|
+
const updatedAuth = {
|
|
181
|
+
...auth,
|
|
182
|
+
refresh: formatRefreshParts({
|
|
183
|
+
refreshToken: parts.refreshToken,
|
|
184
|
+
projectId: parts.projectId,
|
|
185
|
+
managedProjectId,
|
|
186
|
+
}),
|
|
187
|
+
};
|
|
188
|
+
return { auth: updatedAuth, effectiveProjectId: managedProjectId };
|
|
189
|
+
};
|
|
190
|
+
const loadPayload = await loadManagedProject(accessToken, parts.projectId ?? fallbackProjectId);
|
|
191
|
+
const resolvedManagedProjectId = extractManagedProjectId(loadPayload);
|
|
192
|
+
if (resolvedManagedProjectId) {
|
|
193
|
+
return persistManagedProject(resolvedManagedProjectId);
|
|
194
|
+
}
|
|
195
|
+
const tierId = getDefaultTierId(loadPayload?.allowedTiers) ?? "FREE";
|
|
196
|
+
log.debug("Auto-provisioning managed project", { tierId, projectId: parts.projectId });
|
|
197
|
+
const provisionedProjectId = await onboardManagedProject(accessToken, tierId, parts.projectId);
|
|
198
|
+
if (provisionedProjectId) {
|
|
199
|
+
log.debug("Successfully provisioned managed project", { provisionedProjectId });
|
|
200
|
+
return persistManagedProject(provisionedProjectId);
|
|
201
|
+
}
|
|
202
|
+
log.warn("Failed to provision managed project - account may not work correctly", {
|
|
203
|
+
hasProjectId: !!parts.projectId,
|
|
204
|
+
});
|
|
205
|
+
if (parts.projectId) {
|
|
206
|
+
return { auth, effectiveProjectId: parts.projectId };
|
|
207
|
+
}
|
|
208
|
+
return { auth, effectiveProjectId: fallbackProjectId };
|
|
209
|
+
};
|
|
210
|
+
if (!cacheKey) {
|
|
211
|
+
return resolveContext();
|
|
212
|
+
}
|
|
213
|
+
const promise = resolveContext()
|
|
214
|
+
.then((result) => {
|
|
215
|
+
const nextKey = getCacheKey(result.auth) ?? cacheKey;
|
|
216
|
+
projectContextPendingCache.delete(cacheKey);
|
|
217
|
+
projectContextResultCache.set(nextKey, result);
|
|
218
|
+
if (nextKey !== cacheKey) {
|
|
219
|
+
projectContextResultCache.delete(cacheKey);
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
})
|
|
223
|
+
.catch((error) => {
|
|
224
|
+
projectContextPendingCache.delete(cacheKey);
|
|
225
|
+
throw error;
|
|
226
|
+
});
|
|
227
|
+
projectContextPendingCache.set(cacheKey, promise);
|
|
228
|
+
return promise;
|
|
229
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PluginClient } from "./types";
|
|
2
|
+
import type { AccountMetadataV3 } from "./storage";
|
|
3
|
+
export type QuotaGroup = "claude" | "gemini-pro" | "gemini-flash";
|
|
4
|
+
export interface QuotaGroupSummary {
|
|
5
|
+
remainingFraction?: number;
|
|
6
|
+
resetTime?: string;
|
|
7
|
+
modelCount: number;
|
|
8
|
+
}
|
|
9
|
+
export interface QuotaSummary {
|
|
10
|
+
groups: Partial<Record<QuotaGroup, QuotaGroupSummary>>;
|
|
11
|
+
modelCount: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface GeminiCliQuotaModel {
|
|
15
|
+
modelId: string;
|
|
16
|
+
remainingFraction: number;
|
|
17
|
+
resetTime?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface GeminiCliQuotaSummary {
|
|
20
|
+
models: GeminiCliQuotaModel[];
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
export type AccountQuotaStatus = "ok" | "disabled" | "error";
|
|
24
|
+
export interface AccountQuotaResult {
|
|
25
|
+
index: number;
|
|
26
|
+
email?: string;
|
|
27
|
+
status: AccountQuotaStatus;
|
|
28
|
+
error?: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
quota?: QuotaSummary;
|
|
31
|
+
geminiCliQuota?: GeminiCliQuotaSummary;
|
|
32
|
+
updatedAccount?: AccountMetadataV3;
|
|
33
|
+
}
|
|
34
|
+
export declare function checkAccountsQuota(accounts: AccountMetadataV3[], client: PluginClient, providerId?: string): Promise<AccountQuotaResult[]>;
|