-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin.ts
More file actions
116 lines (98 loc) · 3.64 KB
/
Copy pathplugin.ts
File metadata and controls
116 lines (98 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import type { Plugin, PluginInput } from "@opencode-ai/plugin";
import type { Config } from "@opencode-ai/sdk";
import { install, readLocalConfig, mergeConfigWithOverrides, type Scope, type InstallResult } from "./src/installer.ts";
import { RegistrationDetector } from "./src/registration.ts";
const PLUGIN_SERVICE_NAME = "opencode-intellisearch";
const ADVISORY_TOAST_DURATION_MS = 10000;
const INSTALL_ADVISORY_MESSAGE = `${PLUGIN_SERVICE_NAME} is not installed in any scope. Run "bunx opencode-intellisearch install --scope global" to enable the intelligent search skill and command.`;
const LOAD_INSTALL_OPTIONS = {
addPluginConfig: false,
migrateRootConfig: false,
force: false,
configurePermission: false,
configureMcp: false,
};
type PluginClient = PluginInput["client"] | undefined;
interface AdvisoryState {
emitted: boolean;
}
function setSkillPermission(input: Config): void {
input.permission ??= {};
const permission = input.permission as Record<string, unknown>;
permission.skill ??= {};
const skillPermissions = permission.skill as Record<string, string>;
skillPermissions["intellisearch"] = "allow";
}
async function mergeExistingLocalOverrides(input: Record<string, unknown>, directory: string): Promise<void> {
const localConfig = await readLocalConfig(directory);
if (localConfig === null) {
return;
}
mergeConfigWithOverrides(input, localConfig);
}
async function logWarn(client: PluginClient, message: string): Promise<void> {
const log = client?.app?.log;
if (!log) {
console.warn(`[${PLUGIN_SERVICE_NAME}] ${message}`);
return;
}
try {
await log({ body: { service: PLUGIN_SERVICE_NAME, level: "warn", message } });
} catch {
console.warn(`[${PLUGIN_SERVICE_NAME}] ${message}`);
}
}
async function showToastAdvisory(client: PluginClient, message: string): Promise<void> {
try {
await client?.tui?.showToast?.({
body: {
title: PLUGIN_SERVICE_NAME,
message,
variant: "warning",
duration: ADVISORY_TOAST_DURATION_MS,
},
});
} catch {
return;
}
}
async function maybeEmitInstallAdvisory(state: AdvisoryState, client: PluginClient, directory: string): Promise<void> {
if (state.emitted || (await RegistrationDetector.hasAnyInstallation(directory))) {
return;
}
state.emitted = true;
await logWarn(client, INSTALL_ADVISORY_MESSAGE);
await showToastAdvisory(client, INSTALL_ADVISORY_MESSAGE);
}
async function reportLoadSkippedFiles(client: PluginClient, result: InstallResult): Promise<void> {
for (const skippedPath of result.skipped) {
await logWarn(
client,
`Skipped consumer-modified file (re-run "bunx opencode-intellisearch install --force" to overwrite): ${skippedPath}`
);
}
}
async function ensureScopeAssets(client: PluginClient, scope: Scope, directory: string): Promise<InstallResult> {
const result = await install(scope, directory, LOAD_INSTALL_OPTIONS);
await reportLoadSkippedFiles(client, result);
return result;
}
const plugin: Plugin = async ({ directory, client }) => {
const advisoryState: AdvisoryState = { emitted: false };
return {
config: async (input: Config) => {
setSkillPermission(input);
await mergeExistingLocalOverrides(input as Record<string, unknown>, directory);
const context = await RegistrationDetector.detect(directory);
const scopes = RegistrationDetector.scopesToEnsure(context);
if (scopes.length === 0) {
await maybeEmitInstallAdvisory(advisoryState, client, directory);
return;
}
for (const scope of scopes) {
await ensureScopeAssets(client, scope, directory);
}
},
};
};
export default plugin;