mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 21:03:05 -07:00
feat(cli): support extension installation for teleportation
This commit is contained in:
@@ -51,6 +51,7 @@ import {
|
|||||||
type HookDefinition,
|
type HookDefinition,
|
||||||
type HookEventName,
|
type HookEventName,
|
||||||
type ResolvedExtensionSetting,
|
type ResolvedExtensionSetting,
|
||||||
|
type TrajectoryProvider,
|
||||||
coreEvents,
|
coreEvents,
|
||||||
applyAdminAllowlist,
|
applyAdminAllowlist,
|
||||||
getAdminBlockedMcpServersMessage,
|
getAdminBlockedMcpServersMessage,
|
||||||
@@ -957,6 +958,23 @@ Would you like to attempt to install via "git clone" instead?`,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let trajectoryProviderModule: TrajectoryProvider | undefined;
|
||||||
|
if (config.trajectoryProvider) {
|
||||||
|
try {
|
||||||
|
const expectedPath = path.resolve(
|
||||||
|
effectiveExtensionPath,
|
||||||
|
config.trajectoryProvider,
|
||||||
|
);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
trajectoryProviderModule = (await import(expectedPath))
|
||||||
|
.default as TrajectoryProvider;
|
||||||
|
} catch (e) {
|
||||||
|
debugLogger.warn(
|
||||||
|
`Failed to import trajectoryProvider at ${config.trajectoryProvider} for extension ${config.name}: ${getErrorMessage(e)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: config.name,
|
name: config.name,
|
||||||
version: config.version,
|
version: config.version,
|
||||||
@@ -980,6 +998,7 @@ Would you like to attempt to install via "git clone" instead?`,
|
|||||||
rules,
|
rules,
|
||||||
checkers,
|
checkers,
|
||||||
plan: config.plan,
|
plan: config.plan,
|
||||||
|
trajectoryProviderModule,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const extName = path.basename(extensionDir);
|
const extName = path.basename(extensionDir);
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ export interface ExtensionConfig {
|
|||||||
* Used to migrate an extension to a new repository source.
|
* Used to migrate an extension to a new repository source.
|
||||||
*/
|
*/
|
||||||
migratedTo?: string;
|
migratedTo?: string;
|
||||||
|
/**
|
||||||
|
* Path to a module that implements the TrajectoryProvider interface.
|
||||||
|
* Used for importing binary chat histories like Jetski Teleportation.
|
||||||
|
*/
|
||||||
|
trajectoryProvider?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtensionUpdateInfo {
|
export interface ExtensionUpdateInfo {
|
||||||
|
|||||||
@@ -242,6 +242,50 @@ export abstract class ExtensionLoader {
|
|||||||
await this.stopExtension(extension);
|
await this.stopExtension(extension);
|
||||||
await this.startExtension(extension);
|
await this.startExtension(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recent session from all extensions if it's within the threshold.
|
||||||
|
*/
|
||||||
|
async getRecentExternalSession(
|
||||||
|
workspaceUri?: string,
|
||||||
|
thresholdMs: number = 10 * 60 * 1000,
|
||||||
|
): Promise<{ prefix: string; id: string; displayName?: string } | null> {
|
||||||
|
const activeExtensions = this.getExtensions().filter((e) => e.isActive);
|
||||||
|
let mostRecent: {
|
||||||
|
prefix: string;
|
||||||
|
id: string;
|
||||||
|
displayName?: string;
|
||||||
|
mtime: number;
|
||||||
|
} | null = null;
|
||||||
|
|
||||||
|
for (const extension of activeExtensions) {
|
||||||
|
if (extension.trajectoryProviderModule) {
|
||||||
|
try {
|
||||||
|
const sessions =
|
||||||
|
await extension.trajectoryProviderModule.listSessions(workspaceUri);
|
||||||
|
for (const s of sessions) {
|
||||||
|
const mtime = new Date(s.mtime).getTime();
|
||||||
|
if (!mostRecent || mtime > mostRecent.mtime) {
|
||||||
|
mostRecent = {
|
||||||
|
prefix: extension.trajectoryProviderModule.prefix || '',
|
||||||
|
id: s.id,
|
||||||
|
displayName: s.displayName,
|
||||||
|
mtime,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_e) {
|
||||||
|
// Ignore extension errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mostRecent && Date.now() - mostRecent.mtime < thresholdMs) {
|
||||||
|
return mostRecent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtensionEvents {
|
export interface ExtensionEvents {
|
||||||
|
|||||||
Reference in New Issue
Block a user