mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 23:25:24 +00:00
feat: finish the ai plugin (B18)
This commit is contained in:
1 parent
6b4d1432ab
commit
21937a6b02
193 files changed
+23429
-4244
No files matched your search
@@ -1,38 +1,38 @@
|
||||
import type { Router } from "express";
|
||||
import type { PluginContext } from "@termix/plugin-sdk/backend";
|
||||
import { setPluginSsh } from "./ssh.js";
|
||||
import { setPluginServices } from "./services.js";
|
||||
import { startAiService, stopAiService } from "./routes.js";
|
||||
import { createCurrentAiRepository } from "../../../../src/backend/database/repositories/factory.js";
|
||||
import { hostImportNormalizer } from "./host-import.js";
|
||||
import { createAiRepository } from "./repository.js";
|
||||
import { registerAiRoutes } from "./routes.js";
|
||||
|
||||
export async function activate(ctx: PluginContext) {
|
||||
setPluginSsh(ctx.ssh);
|
||||
ctx.disposables.add(() => setPluginSsh(null));
|
||||
setPluginServices(ctx.services);
|
||||
ctx.disposables.add(() => setPluginServices(null));
|
||||
startAiService(ctx.http.router());
|
||||
const repository = await createAiRepository(ctx);
|
||||
|
||||
registerAiRoutes(ctx.http.router<Router>(), repository, ctx);
|
||||
|
||||
ctx.registry.provide("ai.hostImportNormalizer", hostImportNormalizer);
|
||||
ctx.disposables.add(
|
||||
() =>
|
||||
void ctx.registry.revoke("ai.hostImportNormalizer", hostImportNormalizer),
|
||||
);
|
||||
|
||||
// Offered by reference, not copied: this hands over a resolver, so the key
|
||||
// stays ours. Rotating or deleting the provider takes effect on the next
|
||||
// read by any borrower, and deactivate() below withdraws the offer entirely.
|
||||
// The resolve is per-user because the keys are stored per-user and encrypted
|
||||
// under that user's data key, so a borrowed read returns the acting user's
|
||||
// own default key, never someone else's.
|
||||
ctx.secrets.offer("api-key", async (userId: string) => {
|
||||
const repository = createCurrentAiRepository();
|
||||
const providers = await repository.listProviders(userId);
|
||||
const preferred = providers.find((provider) => provider.apiKeyPrefix);
|
||||
if (!preferred) return null;
|
||||
|
||||
const withSecret = await repository.findProviderWithSecret(
|
||||
preferred.id,
|
||||
userId,
|
||||
);
|
||||
return withSecret?.apiKey ?? null;
|
||||
});
|
||||
// read by any borrower, and deactivate withdraws the offer. Keys are per
|
||||
// user, so a borrowed read returns the acting user's own key.
|
||||
ctx.secrets.offer("api-key", (userId: string) =>
|
||||
ctx.asUser(userId, async () => {
|
||||
const providers = await repository.listProviders(userId);
|
||||
const preferred = providers.find((provider) => provider.apiKeyPrefix);
|
||||
if (!preferred) return null;
|
||||
const withSecret = await repository.findProviderWithSecret(
|
||||
preferred.id,
|
||||
userId,
|
||||
);
|
||||
return withSecret?.apiKey ?? null;
|
||||
}),
|
||||
);
|
||||
|
||||
ctx.log.info("AI assistant routes mounted at /plugin-api/ai");
|
||||
}
|
||||
|
||||
export async function deactivate() {
|
||||
stopAiService();
|
||||
}
|
||||
export async function deactivate() {}
|
||||
Reference in new issue
Block a user