Files
Pawan Osman 7bb5801a8c Rewrite project as OpenCursor, a VS Code AI coding agent extension
Replace the ChatGPT reverse proxy (Docker/proxy server) entirely with
OpenCursor: a Cursor-like agentic coding extension for VS Code.

- Remove proxy server, Dockerfiles, docker-compose setups, and CI workflows
- Add agent loop with tools (files, shell, search, web, MCP), multi-provider
  LLM support (OpenAI-compatible, Ollama, llama.cpp) with OAuth
- Add semantic indexing, workspace context, and @-mentions
- Add sidebar chat + settings webview UI (React), inline review, personas,
  hooks, and approval policies
- Switch to pnpm, esbuild bundling, and VS Code extension packaging
2026-07-05 22:07:25 +03:00

104 lines
3.9 KiB
TypeScript

/*
* Copyright (c) 2026 Pawan Osman <https://github.com/PawanOsman>
*
* This file is part of OpenCursor — AI coding agent chat inside VS Code.
* https://github.com/PawanOsman/OpenCursor
*
* Licensed under the MIT License. See LICENSE file in the project root.
*/
import * as React from "react";
import { Icon } from "../../shared/icons";
import { FeatureConfig, Persona, uid } from "../features";
export function PersonasPanel({
features,
setFeatures,
builtinPersonas,
}: {
features: FeatureConfig;
setFeatures: (f: Partial<FeatureConfig>) => void;
builtinPersonas: Persona[];
}) {
const all = [...builtinPersonas, ...features.customPersonas];
const updateCustom = (id: string, patch: Partial<Persona>) => {
setFeatures({ customPersonas: features.customPersonas.map((p) => (p.id === id ? { ...p, ...patch } : p)) });
};
const removeCustom = (id: string) => {
const next = features.customPersonas.filter((p) => p.id !== id);
const patch: Partial<FeatureConfig> = { customPersonas: next };
if (features.activePersonaId === id) {
patch.activePersonaId = "default";
}
setFeatures(patch);
};
const addCustom = () =>
setFeatures({
customPersonas: [
...features.customPersonas,
{ id: uid("persona"), name: "My Persona", description: "Custom persona", prompt: "" },
],
});
return (
<>
<h1 className="page-title">Personas</h1>
<div className="section-label">Default Persona</div>
<p className="panel-hint">New chats use this persona's system prompt. You can override it per chat from the composer.</p>
<div className="row">
<div className="row-text">
<div className="row-title">Active Persona</div>
<div className="row-desc">Applied automatically to new conversations.</div>
</div>
<select value={features.activePersonaId} onChange={(e) => setFeatures({ activePersonaId: e.target.value })}>
{all.map((p) => (
<option key={p.id} value={p.id}>
{p.name}
</option>
))}
</select>
</div>
<div className="section-label" style={{ marginTop: 24 }}>Built-in Personas</div>
{builtinPersonas.map((p) => (
<div className="list-row" key={p.id}>
<Icon name="agent" />
<div className="lr-text">
<div className="lr-title">{p.name}</div>
<div className="lr-desc">{p.description}</div>
</div>
{features.activePersonaId === p.id && <span className="badge-default">default</span>}
</div>
))}
<div className="section-label" style={{ marginTop: 24 }}>Custom Personas</div>
<p className="panel-hint">Define your own personas. The prompt layers onto the base coding-agent prompt.</p>
{features.customPersonas.map((p) => (
<div className="feature-card" key={p.id}>
<div className="fc-head">
<input className="fc-title-input" value={p.name} onChange={(e) => updateCustom(p.id, { name: e.target.value })} placeholder="name" />
<button className="icon-btn" onClick={() => removeCustom(p.id)} title="Remove">
<Icon name="trash" size={14} />
</button>
</div>
<div className="fc-body">
<label className="fc-field">
<span>Description</span>
<input value={p.description} onChange={(e) => updateCustom(p.id, { description: e.target.value })} placeholder="Short description" />
</label>
<label className="fc-field">
<span>System Prompt</span>
<textarea rows={4} value={p.prompt} onChange={(e) => updateCustom(p.id, { prompt: e.target.value })} placeholder="You are a..." />
</label>
</div>
</div>
))}
<div className="panel-actions">
<button className="btn-ghost" onClick={addCustom}>
<Icon name="plus" size={14} /> Add Persona
</button>
</div>
</>
);
}