Nicolas Cantu 69ab265560 feat: initial RAG sync with .4nkaiignore (extension 0.3, server 0.2)
**Motivations:**
- Seed AnythingLLM workspace from cloned repo using gitignore-style filters

**Root causes:**
- N/A

**Correctifs:**
- N/A

**Evolutions:**
- Template 4nkaiignore.default; server copies after clone; extension uploads via POST /api/v1/document/upload
- New commands /workspace-sync; settings initialSync*; dependency ignore

**Pages affectées:**
- extensions/anythingllm-workspaces/*
- services/repos-devtools-server/*
- docs/features/initial-rag-sync-4nkaiignore.md
2026-03-24 22:36:37 +01:00

113 lines
3.9 KiB
TypeScript

import * as vscode from "vscode";
import type { DevToolsConfigSnapshot } from "./config";
import { runDevToolsScript, makeOpenAnythingHandler, registerDevToolsOpenFolder } from "./devToolsExecutor";
const PANEL_ID = "anythingllmDevTools";
const panelTitle = "AnythingLLM dev tools";
const buildHtml = (
webview: vscode.Webview,
extensionUri: vscode.Uri,
): string => {
const scriptUri = webview.asWebviewUri(
vscode.Uri.joinPath(extensionUri, "media", "devTools.js"),
);
const csp = webview.cspSource;
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${csp} 'unsafe-inline'; script-src ${csp};" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${panelTitle}</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0.75rem; color: var(--vscode-foreground); background: var(--vscode-editor-background); }
label { display: block; margin-bottom: 0.35rem; font-weight: 600; }
textarea#cmd { width: 100%; min-height: 7rem; box-sizing: border-box; font-family: monospace; font-size: 12px; }
pre#out { white-space: pre-wrap; word-break: break-word; min-height: 4rem; padding: 0.5rem; border: 1px solid var(--vscode-panel-border); }
.row { margin-bottom: 0.5rem; }
button { margin-right: 0.5rem; }
</style>
</head>
<body>
<div class="row">
<label for="cmd">Commands (one per line)</label>
<textarea id="cmd" spellcheck="false" placeholder="/repos-clone-sync https://…&#10;/workspace-sync my-repo"></textarea>
</div>
<div class="row">
<button type="button" id="run">Run</button>
<button type="button" id="clear">Clear output</button>
</div>
<label for="out">Response</label>
<pre id="out"></pre>
<script src="${scriptUri}"></script>
</body>
</html>`;
};
export const showDevToolsPanel = (
context: vscode.ExtensionContext,
readConfig: () => DevToolsConfigSnapshot,
): void => {
const column = vscode.ViewColumn.Beside;
const panel = vscode.window.createWebviewPanel(
PANEL_ID,
panelTitle,
column,
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [
vscode.Uri.joinPath(context.extensionUri, "media"),
],
},
);
panel.webview.html = buildHtml(panel.webview, context.extensionUri);
const openFolder = registerDevToolsOpenFolder(vscode);
const templateFsPath = vscode.Uri.joinPath(
context.extensionUri,
"templates",
"4nkaiignore.default",
).fsPath;
panel.webview.onDidReceiveMessage(
(msg: unknown) => {
void (async () => {
if (typeof msg !== "object" || msg === null) {
return;
}
const rec = msg as Record<string, unknown>;
if (rec.type !== "run") {
return;
}
const text = typeof rec.text === "string" ? rec.text : "";
const use = readConfig();
const openBrowser = makeOpenAnythingHandler(vscode, use.anythingBaseUrl);
try {
const result = await runDevToolsScript(text, {
anythingBaseUrl: use.anythingBaseUrl,
anythingApiKey: use.anythingApiKey,
reposApiBaseUrl: use.reposApiBaseUrl,
reposApiToken: use.reposApiToken,
initialSyncAfterClone: use.initialSyncAfterClone,
initialSyncMaxFiles: use.initialSyncMaxFiles,
initialSyncMaxFileBytes: use.initialSyncMaxFileBytes,
default4nkaiignoreTemplateFsPath: templateFsPath,
openFolder,
openAnythingWorkspaceInBrowser: openBrowser,
});
panel.webview.postMessage({ type: "result", text: result });
} catch (e) {
const m = e instanceof Error ? e.message : String(e);
panel.webview.postMessage({ type: "result", text: `ERROR: ${m}` });
}
})();
},
undefined,
context.subscriptions,
);
};