@terminai/a2a-server 0.21.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 +5 -0
- package/dist/.last_build +0 -0
- package/dist/a2a-server.mjs +415698 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/src/agent/executor.d.ts +41 -0
- package/dist/src/agent/executor.js +408 -0
- package/dist/src/agent/executor.js.map +1 -0
- package/dist/src/agent/task.d.ts +67 -0
- package/dist/src/agent/task.js +799 -0
- package/dist/src/agent/task.js.map +1 -0
- package/dist/src/agent/task.test.d.ts +7 -0
- package/dist/src/agent/task.test.js +435 -0
- package/dist/src/agent/task.test.js.map +1 -0
- package/dist/src/agent/task.token.test.d.ts +7 -0
- package/dist/src/agent/task.token.test.js +53 -0
- package/dist/src/agent/task.token.test.js.map +1 -0
- package/dist/src/auth/llmAuthManager.d.ts +39 -0
- package/dist/src/auth/llmAuthManager.js +209 -0
- package/dist/src/auth/llmAuthManager.js.map +1 -0
- package/dist/src/auth/llmAuthManager.test.d.ts +7 -0
- package/dist/src/auth/llmAuthManager.test.js +92 -0
- package/dist/src/auth/llmAuthManager.test.js.map +1 -0
- package/dist/src/commands/command-registry.d.ts +16 -0
- package/dist/src/commands/command-registry.js +35 -0
- package/dist/src/commands/command-registry.js.map +1 -0
- package/dist/src/commands/command-registry.test.d.ts +7 -0
- package/dist/src/commands/command-registry.test.js +100 -0
- package/dist/src/commands/command-registry.test.js.map +1 -0
- package/dist/src/commands/extensions.d.ts +19 -0
- package/dist/src/commands/extensions.js +26 -0
- package/dist/src/commands/extensions.js.map +1 -0
- package/dist/src/commands/extensions.test.d.ts +7 -0
- package/dist/src/commands/extensions.test.js +70 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/commands/init.d.ts +16 -0
- package/dist/src/commands/init.js +111 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/init.test.d.ts +7 -0
- package/dist/src/commands/init.test.js +146 -0
- package/dist/src/commands/init.test.js.map +1 -0
- package/dist/src/commands/restore.d.ts +21 -0
- package/dist/src/commands/restore.js +126 -0
- package/dist/src/commands/restore.js.map +1 -0
- package/dist/src/commands/restore.test.d.ts +7 -0
- package/dist/src/commands/restore.test.js +111 -0
- package/dist/src/commands/restore.test.js.map +1 -0
- package/dist/src/commands/types.d.ts +33 -0
- package/dist/src/commands/types.js +8 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/config/config.d.ts +24 -0
- package/dist/src/config/config.js +140 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/extension.d.ts +12 -0
- package/dist/src/config/extension.js +105 -0
- package/dist/src/config/extension.js.map +1 -0
- package/dist/src/config/settings.d.ts +15 -0
- package/dist/src/config/settings.js +20 -0
- package/dist/src/config/settings.js.map +1 -0
- package/dist/src/config/settings.test.d.ts +7 -0
- package/dist/src/config/settings.test.js +170 -0
- package/dist/src/config/settings.test.js.map +1 -0
- package/dist/src/http/app.d.ts +17 -0
- package/dist/src/http/app.js +399 -0
- package/dist/src/http/app.js.map +1 -0
- package/dist/src/http/app.test.d.ts +7 -0
- package/dist/src/http/app.test.js +1048 -0
- package/dist/src/http/app.test.js.map +1 -0
- package/dist/src/http/auth.d.ts +21 -0
- package/dist/src/http/auth.js +55 -0
- package/dist/src/http/auth.js.map +1 -0
- package/dist/src/http/auth.test.d.ts +7 -0
- package/dist/src/http/auth.test.js +53 -0
- package/dist/src/http/auth.test.js.map +1 -0
- package/dist/src/http/authRoutes.test.d.ts +7 -0
- package/dist/src/http/authRoutes.test.js +169 -0
- package/dist/src/http/authRoutes.test.js.map +1 -0
- package/dist/src/http/cors.d.ts +8 -0
- package/dist/src/http/cors.js +96 -0
- package/dist/src/http/cors.js.map +1 -0
- package/dist/src/http/cors.test.d.ts +7 -0
- package/dist/src/http/cors.test.js +62 -0
- package/dist/src/http/cors.test.js.map +1 -0
- package/dist/src/http/deferredAuth.test.d.ts +7 -0
- package/dist/src/http/deferredAuth.test.js +45 -0
- package/dist/src/http/deferredAuth.test.js.map +1 -0
- package/dist/src/http/endpoints.test.d.ts +7 -0
- package/dist/src/http/endpoints.test.js +149 -0
- package/dist/src/http/endpoints.test.js.map +1 -0
- package/dist/src/http/llmAuthMiddleware.d.ts +9 -0
- package/dist/src/http/llmAuthMiddleware.js +37 -0
- package/dist/src/http/llmAuthMiddleware.js.map +1 -0
- package/dist/src/http/relay.d.ts +28 -0
- package/dist/src/http/relay.js +342 -0
- package/dist/src/http/relay.js.map +1 -0
- package/dist/src/http/relay.test.d.ts +7 -0
- package/dist/src/http/relay.test.js +149 -0
- package/dist/src/http/relay.test.js.map +1 -0
- package/dist/src/http/replay.d.ts +19 -0
- package/dist/src/http/replay.js +90 -0
- package/dist/src/http/replay.js.map +1 -0
- package/dist/src/http/replay.test.d.ts +7 -0
- package/dist/src/http/replay.test.js +78 -0
- package/dist/src/http/replay.test.js.map +1 -0
- package/dist/src/http/requestStorage.d.ts +11 -0
- package/dist/src/http/requestStorage.js +9 -0
- package/dist/src/http/requestStorage.js.map +1 -0
- package/dist/src/http/routes/auth.d.ts +9 -0
- package/dist/src/http/routes/auth.js +125 -0
- package/dist/src/http/routes/auth.js.map +1 -0
- package/dist/src/http/server.d.ts +8 -0
- package/dist/src/http/server.js +28 -0
- package/dist/src/http/server.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/persistence/gcs.d.ts +25 -0
- package/dist/src/persistence/gcs.js +248 -0
- package/dist/src/persistence/gcs.js.map +1 -0
- package/dist/src/persistence/gcs.test.d.ts +7 -0
- package/dist/src/persistence/gcs.test.js +335 -0
- package/dist/src/persistence/gcs.test.js.map +1 -0
- package/dist/src/persistence/remoteAuthStore.d.ts +21 -0
- package/dist/src/persistence/remoteAuthStore.js +74 -0
- package/dist/src/persistence/remoteAuthStore.js.map +1 -0
- package/dist/src/types.d.ts +100 -0
- package/dist/src/types.js +49 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/envAliases.d.ts +7 -0
- package/dist/src/utils/envAliases.js +9 -0
- package/dist/src/utils/envAliases.js.map +1 -0
- package/dist/src/utils/executor_utils.d.ts +8 -0
- package/dist/src/utils/executor_utils.js +42 -0
- package/dist/src/utils/executor_utils.js.map +1 -0
- package/dist/src/utils/logger.d.ts +9 -0
- package/dist/src/utils/logger.js +26 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/redactSecrets.d.ts +16 -0
- package/dist/src/utils/redactSecrets.js +72 -0
- package/dist/src/utils/redactSecrets.js.map +1 -0
- package/dist/src/utils/redactSecrets.test.d.ts +7 -0
- package/dist/src/utils/redactSecrets.test.js +62 -0
- package/dist/src/utils/redactSecrets.test.js.map +1 -0
- package/dist/src/utils/testing_utils.d.ts +48 -0
- package/dist/src/utils/testing_utils.js +173 -0
- package/dist/src/utils/testing_utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/web-client/app.js +526 -0
- package/dist/web-client/index.html +43 -0
- package/dist/web-client/package.json +10 -0
- package/dist/web-client/relay-client.js +330 -0
- package/dist/web-client/style.css +189 -0
- package/package.json +53 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import * as dotenv from 'dotenv';
|
|
9
|
+
import { AuthType, Config, FileDiscoveryService, ApprovalMode, loadServerHierarchicalMemory, DEFAULT_GEMINI_EMBEDDING_MODEL, DEFAULT_GEMINI_MODEL, startupProfiler, PREVIEW_GEMINI_MODEL, findEnvFile, } from '@terminai/core';
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
import { CoderAgentEvent } from '../types.js';
|
|
12
|
+
export async function loadConfig(loadedSettings, extensionLoader, taskId, targetDirOverride, options) {
|
|
13
|
+
const settings = loadedSettings.merged;
|
|
14
|
+
const workspaceDir = targetDirOverride || process.cwd();
|
|
15
|
+
const adcFilePath = process.env['GOOGLE_APPLICATION_CREDENTIALS'];
|
|
16
|
+
const configParams = {
|
|
17
|
+
sessionId: taskId,
|
|
18
|
+
model: settings.general?.previewFeatures
|
|
19
|
+
? PREVIEW_GEMINI_MODEL
|
|
20
|
+
: DEFAULT_GEMINI_MODEL,
|
|
21
|
+
embeddingModel: DEFAULT_GEMINI_EMBEDDING_MODEL,
|
|
22
|
+
sandbox: undefined,
|
|
23
|
+
targetDir: workspaceDir,
|
|
24
|
+
debugMode: process.env['DEBUG'] === 'true' || false,
|
|
25
|
+
question: '',
|
|
26
|
+
// CRITICAL FIX: V2 nested paths (not V1 flat paths)
|
|
27
|
+
coreTools: settings.tools?.core || undefined,
|
|
28
|
+
excludeTools: settings.tools?.exclude || undefined,
|
|
29
|
+
showMemoryUsage: settings.ui?.showMemoryUsage || false,
|
|
30
|
+
approvalMode: process.env['GEMINI_YOLO_MODE'] === 'true'
|
|
31
|
+
? ApprovalMode.YOLO
|
|
32
|
+
: ApprovalMode.DEFAULT,
|
|
33
|
+
mcpServers: settings.mcpServers,
|
|
34
|
+
cwd: workspaceDir,
|
|
35
|
+
telemetry: {
|
|
36
|
+
enabled: settings.telemetry?.enabled,
|
|
37
|
+
target: settings.telemetry?.target,
|
|
38
|
+
otlpEndpoint: process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] ??
|
|
39
|
+
settings.telemetry?.otlpEndpoint,
|
|
40
|
+
logPrompts: settings.telemetry?.logPrompts,
|
|
41
|
+
},
|
|
42
|
+
// CRITICAL FIX: V2 nested paths for fileFiltering
|
|
43
|
+
fileFiltering: {
|
|
44
|
+
respectGitIgnore: settings.context?.fileFiltering?.respectGitIgnore,
|
|
45
|
+
respectGeminiIgnore: settings.context?.fileFiltering?.respectGeminiIgnore,
|
|
46
|
+
enableRecursiveFileSearch: settings.context?.fileFiltering?.enableRecursiveFileSearch,
|
|
47
|
+
disableFuzzySearch: settings.context?.fileFiltering?.disableFuzzySearch,
|
|
48
|
+
},
|
|
49
|
+
ideMode: false,
|
|
50
|
+
// CRITICAL FIX: V2 nested path for folderTrust
|
|
51
|
+
folderTrust: settings.security?.folderTrust?.enabled === true,
|
|
52
|
+
extensionLoader,
|
|
53
|
+
// CRITICAL FIX: V2 nested path for checkpointing
|
|
54
|
+
checkpointing: process.env['CHECKPOINTING']
|
|
55
|
+
? process.env['CHECKPOINTING'] === 'true'
|
|
56
|
+
: settings.general?.checkpointing?.enabled,
|
|
57
|
+
previewFeatures: settings.general?.previewFeatures,
|
|
58
|
+
interactive: true,
|
|
59
|
+
webRemoteRelayUrl: process.env['WEB_REMOTE_RELAY_URL'],
|
|
60
|
+
};
|
|
61
|
+
const fileService = new FileDiscoveryService(workspaceDir);
|
|
62
|
+
const { memoryContent, fileCount } = await loadServerHierarchicalMemory(workspaceDir, [], configParams.debugMode ?? false, fileService, extensionLoader,
|
|
63
|
+
// CRITICAL FIX: V2 nested path for folderTrust
|
|
64
|
+
settings.security?.folderTrust?.enabled === true, 'tree', undefined, 200);
|
|
65
|
+
configParams.userMemory = memoryContent;
|
|
66
|
+
configParams.geminiMdFileCount = fileCount;
|
|
67
|
+
const config = new Config({
|
|
68
|
+
...configParams,
|
|
69
|
+
});
|
|
70
|
+
// Needed to initialize ToolRegistry, and git checkpointing if enabled
|
|
71
|
+
await config.initialize();
|
|
72
|
+
startupProfiler.flush(config);
|
|
73
|
+
// Task 9: Deferred auth mode (skip initial refreshAuth)
|
|
74
|
+
if (options?.deferLlmAuth === true) {
|
|
75
|
+
logger.info('[Config] Deferred auth enabled; skipping initial auth refresh.');
|
|
76
|
+
return config;
|
|
77
|
+
}
|
|
78
|
+
if (process.env['USE_CCPA']) {
|
|
79
|
+
logger.info('[Config] Using CCPA Auth:');
|
|
80
|
+
try {
|
|
81
|
+
if (adcFilePath) {
|
|
82
|
+
path.resolve(adcFilePath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
logger.error(`[Config] USE_CCPA env var is true but unable to resolve GOOGLE_APPLICATION_CREDENTIALS file path ${adcFilePath}. Error ${e}`);
|
|
87
|
+
}
|
|
88
|
+
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
|
89
|
+
logger.info(`[Config] GOOGLE_CLOUD_PROJECT: ${process.env['GOOGLE_CLOUD_PROJECT']}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Task 10: Respect settings.security.auth.selectedType
|
|
93
|
+
const selectedAuthType = settings.security?.auth?.selectedType;
|
|
94
|
+
if (selectedAuthType) {
|
|
95
|
+
logger.info(`[Config] Using configured auth type: ${selectedAuthType}`);
|
|
96
|
+
await config.refreshAuth(selectedAuthType);
|
|
97
|
+
}
|
|
98
|
+
else if (process.env['GEMINI_API_KEY']) {
|
|
99
|
+
logger.info('[Config] Using Gemini API Key (Implicit)');
|
|
100
|
+
await config.refreshAuth(AuthType.USE_GEMINI);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
logger.info('[Config] Using OAuth (LOGIN_WITH_GOOGLE) (Default)');
|
|
104
|
+
await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return config;
|
|
108
|
+
}
|
|
109
|
+
export function setTargetDir(agentSettings) {
|
|
110
|
+
const originalCWD = process.cwd();
|
|
111
|
+
const targetDir = process.env['CODER_AGENT_WORKSPACE_PATH'] ??
|
|
112
|
+
(agentSettings?.kind === CoderAgentEvent.StateAgentSettingsEvent
|
|
113
|
+
? agentSettings.workspacePath
|
|
114
|
+
: undefined);
|
|
115
|
+
if (!targetDir) {
|
|
116
|
+
return originalCWD;
|
|
117
|
+
}
|
|
118
|
+
logger.info(`[CoderAgentExecutor] Overriding workspace path to: ${targetDir}`);
|
|
119
|
+
try {
|
|
120
|
+
const resolvedPath = path.resolve(targetDir);
|
|
121
|
+
// process.chdir(resolvedPath); // DISABLED: Global state mutation causes issues in multi-task server
|
|
122
|
+
return resolvedPath;
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
logger.error(`[CoderAgentExecutor] Error resolving workspace path: ${e}, returning original os.cwd()`);
|
|
126
|
+
return originalCWD;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Loads environment variables from .env file.
|
|
131
|
+
* Uses Core's findEnvFile for parity with CLI.
|
|
132
|
+
*/
|
|
133
|
+
export function loadEnvironment(startDir) {
|
|
134
|
+
const envFilePath = findEnvFile(startDir || process.cwd());
|
|
135
|
+
if (envFilePath) {
|
|
136
|
+
// G-2 FIX: No override:true for CLI parity
|
|
137
|
+
dotenv.config({ path: envFilePath });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/config/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { type ExtensionInstallMetadata, type GeminiCLIExtension } from '@terminai/core';
|
|
8
|
+
export declare const EXTENSIONS_DIRECTORY_NAME: string;
|
|
9
|
+
export declare const EXTENSIONS_CONFIG_FILENAME = "gemini-extension.json";
|
|
10
|
+
export declare const INSTALL_METADATA_FILENAME = ".gemini-extension-install.json";
|
|
11
|
+
export declare function loadExtensions(workspaceDir: string): GeminiCLIExtension[];
|
|
12
|
+
export declare function loadInstallMetadata(extensionDir: string): ExtensionInstallMetadata | undefined;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
// Copied exactly from packages/cli/src/config/extension.ts, last PR #1026
|
|
8
|
+
import { GEMINI_DIR, } from '@terminai/core';
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import * as os from 'node:os';
|
|
12
|
+
import { logger } from '../utils/logger.js';
|
|
13
|
+
export const EXTENSIONS_DIRECTORY_NAME = path.join(GEMINI_DIR, 'extensions');
|
|
14
|
+
export const EXTENSIONS_CONFIG_FILENAME = 'gemini-extension.json';
|
|
15
|
+
export const INSTALL_METADATA_FILENAME = '.gemini-extension-install.json';
|
|
16
|
+
export function loadExtensions(workspaceDir) {
|
|
17
|
+
const allExtensions = [
|
|
18
|
+
...loadExtensionsFromDir(workspaceDir),
|
|
19
|
+
...loadExtensionsFromDir(os.homedir()),
|
|
20
|
+
];
|
|
21
|
+
const uniqueExtensions = [];
|
|
22
|
+
const seenNames = new Set();
|
|
23
|
+
for (const extension of allExtensions) {
|
|
24
|
+
if (!seenNames.has(extension.name)) {
|
|
25
|
+
logger.info(`Loading extension: ${extension.name} (version: ${extension.version})`);
|
|
26
|
+
uniqueExtensions.push(extension);
|
|
27
|
+
seenNames.add(extension.name);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return uniqueExtensions;
|
|
31
|
+
}
|
|
32
|
+
function loadExtensionsFromDir(dir) {
|
|
33
|
+
const extensionsDir = path.join(dir, EXTENSIONS_DIRECTORY_NAME);
|
|
34
|
+
if (!fs.existsSync(extensionsDir)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const extensions = [];
|
|
38
|
+
for (const subdir of fs.readdirSync(extensionsDir)) {
|
|
39
|
+
const extensionDir = path.join(extensionsDir, subdir);
|
|
40
|
+
const extension = loadExtension(extensionDir);
|
|
41
|
+
if (extension != null) {
|
|
42
|
+
extensions.push(extension);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return extensions;
|
|
46
|
+
}
|
|
47
|
+
function loadExtension(extensionDir) {
|
|
48
|
+
if (!fs.statSync(extensionDir).isDirectory()) {
|
|
49
|
+
logger.error(`Warning: unexpected file ${extensionDir} in extensions directory.`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const configFilePath = path.join(extensionDir, EXTENSIONS_CONFIG_FILENAME);
|
|
53
|
+
if (!fs.existsSync(configFilePath)) {
|
|
54
|
+
logger.error(`Warning: extension directory ${extensionDir} does not contain a config file ${configFilePath}.`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const configContent = fs.readFileSync(configFilePath, 'utf-8');
|
|
59
|
+
const config = JSON.parse(configContent);
|
|
60
|
+
if (!config.name || !config.version) {
|
|
61
|
+
logger.error(`Invalid extension config in ${configFilePath}: missing name or version.`);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const installMetadata = loadInstallMetadata(extensionDir);
|
|
65
|
+
const contextFiles = getContextFileNames(config)
|
|
66
|
+
.map((contextFileName) => path.join(extensionDir, contextFileName))
|
|
67
|
+
.filter((contextFilePath) => fs.existsSync(contextFilePath));
|
|
68
|
+
return {
|
|
69
|
+
name: config.name,
|
|
70
|
+
version: config.version,
|
|
71
|
+
path: extensionDir,
|
|
72
|
+
contextFiles,
|
|
73
|
+
installMetadata,
|
|
74
|
+
mcpServers: config.mcpServers,
|
|
75
|
+
excludeTools: config.excludeTools,
|
|
76
|
+
isActive: true, // Barring any other signals extensions should be considered Active.
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
logger.error(`Warning: error parsing extension config in ${configFilePath}: ${e}`);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function getContextFileNames(config) {
|
|
85
|
+
if (!config.contextFileName) {
|
|
86
|
+
return ['terminaI.md'];
|
|
87
|
+
}
|
|
88
|
+
else if (!Array.isArray(config.contextFileName)) {
|
|
89
|
+
return [config.contextFileName];
|
|
90
|
+
}
|
|
91
|
+
return config.contextFileName;
|
|
92
|
+
}
|
|
93
|
+
export function loadInstallMetadata(extensionDir) {
|
|
94
|
+
const metadataFilePath = path.join(extensionDir, INSTALL_METADATA_FILENAME);
|
|
95
|
+
try {
|
|
96
|
+
const configContent = fs.readFileSync(metadataFilePath, 'utf-8');
|
|
97
|
+
const metadata = JSON.parse(configContent);
|
|
98
|
+
return metadata;
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
logger.warn(`Failed to load or parse extension install metadata at ${metadataFilePath}: ${e}`);
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../src/config/extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { type Settings, type SettingsError, type LoadedSettings, type SettingScope, isLoadableSettingScope } from '@terminai/core';
|
|
8
|
+
export type { Settings, SettingsError, SettingScope, LoadedSettings };
|
|
9
|
+
export { isLoadableSettingScope };
|
|
10
|
+
export declare const USER_SETTINGS_PATH: string;
|
|
11
|
+
/**
|
|
12
|
+
* Loads settings from user and workspace directories using Core's SettingsLoader.
|
|
13
|
+
* Project settings override user settings.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadSettings(workspaceDir?: string): LoadedSettings;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { SettingsLoader, Storage, isLoadableSettingScope, } from '@terminai/core';
|
|
8
|
+
export { isLoadableSettingScope };
|
|
9
|
+
export const USER_SETTINGS_PATH = Storage.getGlobalSettingsPath();
|
|
10
|
+
/**
|
|
11
|
+
* Loads settings from user and workspace directories using Core's SettingsLoader.
|
|
12
|
+
* Project settings override user settings.
|
|
13
|
+
*/
|
|
14
|
+
export function loadSettings(workspaceDir = process.cwd()) {
|
|
15
|
+
const loader = new SettingsLoader({
|
|
16
|
+
workspaceDir,
|
|
17
|
+
});
|
|
18
|
+
return loader.load();
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/config/settings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EACd,OAAO,EAKP,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;AAElE;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,eAAuB,OAAO,CAAC,GAAG,EAAE;IAEpC,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QAChC,YAAY;KACb,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as os from 'node:os';
|
|
11
|
+
import { loadSettings, USER_SETTINGS_PATH } from './settings.js';
|
|
12
|
+
const mocks = vi.hoisted(() => {
|
|
13
|
+
const suffix = Math.random().toString(36).slice(2);
|
|
14
|
+
return {
|
|
15
|
+
suffix,
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
vi.mock('node:os', async (importOriginal) => {
|
|
19
|
+
const actual = await importOriginal();
|
|
20
|
+
const path = await import('node:path');
|
|
21
|
+
return {
|
|
22
|
+
...actual,
|
|
23
|
+
homedir: () => path.join(actual.tmpdir(), `gemini-home-${mocks.suffix}`),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
describe('loadSettings', () => {
|
|
27
|
+
const mockHomeDir = path.join(os.tmpdir(), `gemini-home-${mocks.suffix}`);
|
|
28
|
+
const mockWorkspaceDir = path.join(os.tmpdir(), `gemini-workspace-${mocks.suffix}`);
|
|
29
|
+
const mockGeminiHomeDir = path.join(mockHomeDir, '.terminai');
|
|
30
|
+
const mockGeminiWorkspaceDir = path.join(mockWorkspaceDir, '.terminai');
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.clearAllMocks();
|
|
33
|
+
// Create the directories using the real fs
|
|
34
|
+
if (!fs.existsSync(mockGeminiHomeDir)) {
|
|
35
|
+
fs.mkdirSync(mockGeminiHomeDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
if (!fs.existsSync(mockGeminiWorkspaceDir)) {
|
|
38
|
+
fs.mkdirSync(mockGeminiWorkspaceDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
// Clean up settings files before each test
|
|
41
|
+
if (fs.existsSync(USER_SETTINGS_PATH)) {
|
|
42
|
+
fs.rmSync(USER_SETTINGS_PATH);
|
|
43
|
+
}
|
|
44
|
+
const workspaceSettingsPath = path.join(mockGeminiWorkspaceDir, 'settings.json');
|
|
45
|
+
if (fs.existsSync(workspaceSettingsPath)) {
|
|
46
|
+
fs.rmSync(workspaceSettingsPath);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
try {
|
|
51
|
+
if (fs.existsSync(mockHomeDir)) {
|
|
52
|
+
fs.rmSync(mockHomeDir, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
if (fs.existsSync(mockWorkspaceDir)) {
|
|
55
|
+
fs.rmSync(mockWorkspaceDir, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.error('Failed to cleanup temp dirs', e);
|
|
60
|
+
}
|
|
61
|
+
vi.restoreAllMocks();
|
|
62
|
+
});
|
|
63
|
+
it('should load nested previewFeatures from user settings', () => {
|
|
64
|
+
const settings = {
|
|
65
|
+
general: {
|
|
66
|
+
previewFeatures: true,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
|
|
70
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
71
|
+
expect(result.merged.general?.previewFeatures).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
it('should load nested previewFeatures from workspace settings', () => {
|
|
74
|
+
const settings = {
|
|
75
|
+
general: {
|
|
76
|
+
previewFeatures: true,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
const workspaceSettingsPath = path.join(mockGeminiWorkspaceDir, 'settings.json');
|
|
80
|
+
fs.writeFileSync(workspaceSettingsPath, JSON.stringify(settings));
|
|
81
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
82
|
+
expect(result.merged.general?.previewFeatures).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
it('should prioritize workspace settings over user settings', () => {
|
|
85
|
+
const userSettings = {
|
|
86
|
+
general: {
|
|
87
|
+
previewFeatures: false,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings));
|
|
91
|
+
const workspaceSettings = {
|
|
92
|
+
general: {
|
|
93
|
+
previewFeatures: true,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const workspaceSettingsPath = path.join(mockGeminiWorkspaceDir, 'settings.json');
|
|
97
|
+
fs.writeFileSync(workspaceSettingsPath, JSON.stringify(workspaceSettings));
|
|
98
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
99
|
+
expect(result.merged.general?.previewFeatures).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
it('should handle missing previewFeatures', () => {
|
|
102
|
+
const settings = {
|
|
103
|
+
general: {},
|
|
104
|
+
};
|
|
105
|
+
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
|
|
106
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
107
|
+
expect(result.merged.general?.previewFeatures).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
it('should load other top-level settings correctly', () => {
|
|
110
|
+
const settings = {
|
|
111
|
+
ui: {
|
|
112
|
+
showMemoryUsage: true,
|
|
113
|
+
},
|
|
114
|
+
tools: {
|
|
115
|
+
core: ['tool1', 'tool2'],
|
|
116
|
+
},
|
|
117
|
+
mcpServers: {
|
|
118
|
+
server1: {
|
|
119
|
+
command: 'cmd',
|
|
120
|
+
args: ['arg'],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
context: {
|
|
124
|
+
fileFiltering: {
|
|
125
|
+
respectGitIgnore: true,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
|
|
130
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
131
|
+
expect(result.merged.ui?.showMemoryUsage).toBe(true);
|
|
132
|
+
expect(result.merged.tools?.core).toEqual(['tool1', 'tool2']);
|
|
133
|
+
expect(result.merged.mcpServers).toHaveProperty('server1');
|
|
134
|
+
expect(result.merged.context?.fileFiltering?.respectGitIgnore).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
it('should merge workspace settings properly', () => {
|
|
137
|
+
const userSettings = {
|
|
138
|
+
ui: {
|
|
139
|
+
showMemoryUsage: false,
|
|
140
|
+
},
|
|
141
|
+
context: {
|
|
142
|
+
fileFiltering: {
|
|
143
|
+
respectGitIgnore: true,
|
|
144
|
+
enableRecursiveFileSearch: true,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings));
|
|
149
|
+
const workspaceSettings = {
|
|
150
|
+
ui: {
|
|
151
|
+
showMemoryUsage: true,
|
|
152
|
+
},
|
|
153
|
+
context: {
|
|
154
|
+
fileFiltering: {
|
|
155
|
+
respectGitIgnore: false,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const workspaceSettingsPath = path.join(mockGeminiWorkspaceDir, 'settings.json');
|
|
160
|
+
fs.writeFileSync(workspaceSettingsPath, JSON.stringify(workspaceSettings));
|
|
161
|
+
const result = loadSettings(mockWorkspaceDir);
|
|
162
|
+
// Workspace overrides user
|
|
163
|
+
expect(result.merged.ui?.showMemoryUsage).toBe(true);
|
|
164
|
+
// Deep merge should preserve values not overridden
|
|
165
|
+
expect(result.merged.context?.fileFiltering?.respectGitIgnore).toBe(false);
|
|
166
|
+
// Core's loader uses deep merge, so this should be preserved
|
|
167
|
+
expect(result.merged.context?.fileFiltering?.enableRecursiveFileSearch).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=settings.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.test.js","sourceRoot":"","sources":["../../../src/config/settings.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* Portions Copyright 2025 TerminaI Authors
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateAppOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Force deferred LLM auth mode for this app instance.
|
|
10
|
+
* If unset, defaults to `TERMINAI_SIDECAR === '1'` unless explicitly overridden
|
|
11
|
+
* via `TERMINAI_A2A_DEFER_AUTH` / legacy `GEMINI_A2A_DEFER_AUTH`.
|
|
12
|
+
*/
|
|
13
|
+
readonly deferLlmAuth?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function updateCoderAgentCardUrl(port: number, host?: string): void;
|
|
16
|
+
export declare function createApp(options?: CreateAppOptions): Promise<import("express-serve-static-core").Express>;
|
|
17
|
+
export declare function main(): Promise<void>;
|