mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-11 02:31:38 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7b9c694f7 |
No files matched your search
@@ -1546,12 +1546,6 @@
|
||||
.planCurrent {
|
||||
color: var(--fg);
|
||||
}
|
||||
.trayActivity {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* A one-button toolbar, not a round bubble: the popup's large arc would turn it into a circle. */
|
||||
.quotePopup {
|
||||
display: flex;
|
||||
|
||||
@@ -75,7 +75,7 @@ import { ConfigPickers } from "./ConfigPickers";
|
||||
import { findRanges, formatDuration, formatSentAt } from "./conversation";
|
||||
import { ImagePreview, imageSrc } from "./ImagePreview";
|
||||
import { useAgentSettings } from "./agentSettings";
|
||||
import { currentTool, foldedTurns, summarizeWork, workParts, type FoldedTurn, type WorkSummary } from "./timeline";
|
||||
import { foldedTurns, summarizeWork, workParts, type FoldedTurn, type WorkSummary } from "./timeline";
|
||||
import { useRevealedText } from "./reveal";
|
||||
import { AgentReply, MessageActions, ReplyActions } from "./AgentReply";
|
||||
import {
|
||||
@@ -2388,7 +2388,6 @@ function Tray({
|
||||
const added = changes?.reduce((n, c) => n + c.added, 0) ?? 0;
|
||||
const removed = changes?.reduce((n, c) => n + c.removed, 0) ?? 0;
|
||||
const busy = task.status === "running" || task.status === "starting";
|
||||
const tool = entries && busy ? currentTool(entries) : null;
|
||||
const lastUser = entries?.findLast((e): e is UserEntry => e.type === "user");
|
||||
return (
|
||||
<div className={styles.tray}>
|
||||
@@ -2445,10 +2444,6 @@ function Tray({
|
||||
<Spinner size={12} />
|
||||
{task.retry ? (
|
||||
<Retrying retry={task.retry} />
|
||||
) : tool ? (
|
||||
<span className={styles.trayActivity} title={tool.title}>
|
||||
{shortTitle(task, tool.title || tool.kind)}
|
||||
</span>
|
||||
) : (
|
||||
<T>{task.status === "starting" ? "Starting the agent…" : "Working…"}</T>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { AgentEntry } from "@/bindings";
|
||||
import { currentTool, foldedTurns, summarizeWork, workParts } from "./timeline";
|
||||
import { foldedTurns, summarizeWork, workParts } from "./timeline";
|
||||
|
||||
const user = (text: string, extra: Partial<Extract<AgentEntry, { type: "user" }>> = {}): AgentEntry => ({
|
||||
type: "user",
|
||||
@@ -45,11 +45,6 @@ describe("summarizeWork", () => {
|
||||
{ text: "1 other tool call", count: 1 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("finds the call in progress", () => {
|
||||
expect(currentTool([tool("read", { status: "running" }), tool("search")])?.kind).toBe("read");
|
||||
expect(currentTool([tool("read")])).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("foldedTurns", () => {
|
||||
|
||||
@@ -91,15 +91,6 @@ export function workParts(s: WorkSummary): Array<{ text: string; count: number }
|
||||
return parts.filter(([, , n]) => n > 0).map(([one, many, count]) => ({ text: count === 1 ? one : many, count }));
|
||||
}
|
||||
|
||||
/** The running tool call of a run, if any: what the agent is doing right now. */
|
||||
export function currentTool(entries: readonly AgentEntry[]): ToolEntry | null {
|
||||
for (let i = entries.length - 1; i >= 0; i--) {
|
||||
const e = entries[i]!;
|
||||
if (e.type === "tool" && (e.status === "running" || e.status === "pending")) return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** A finished turn: the message that asked it at `user`, its work in `[user + 1, reply)`. */
|
||||
export interface FoldedTurn {
|
||||
user: number;
|
||||
|
||||
@@ -129,15 +129,6 @@ export function catalogState(
|
||||
|
||||
const vendorOf = (authors: readonly string[]) => authors.join(", ");
|
||||
|
||||
/** The marketplace's newer version of an installed plugin, if there is one this IDE can load. */
|
||||
function useMarketUpdate(plugin: PluginInfo): MarketPlugin | undefined {
|
||||
return usePlugins((s) =>
|
||||
plugin.source === "installed"
|
||||
? s.market?.find((m) => m.id === plugin.id && m.compatible && compareVersions(m.version, plugin.version) > 0)
|
||||
: undefined,
|
||||
);
|
||||
}
|
||||
|
||||
function PluginIcon({ id, icon, large }: { id: string; icon: PluginIconData | null | undefined; large?: boolean }) {
|
||||
return (
|
||||
<span className={clsx(styles.icon, large && styles.iconLarge)} aria-hidden>
|
||||
@@ -157,7 +148,6 @@ function ListHeader({ title, count }: { title: string; count: number }) {
|
||||
|
||||
function InstalledRow({ plugin, selected, onSelect }: { plugin: PluginInfo; selected: boolean; onSelect: () => void }) {
|
||||
const busy = usePlugins((s) => !!s.busy[plugin.id]);
|
||||
const update = useMarketUpdate(plugin);
|
||||
return (
|
||||
<li className={clsx(styles.row, selected && styles.rowSelected, !plugin.enabled && styles.rowDisabled)}>
|
||||
<button
|
||||
@@ -176,7 +166,6 @@ function InstalledRow({ plugin, selected, onSelect }: { plugin: PluginInfo; sele
|
||||
{plugin.source !== "installed" && (
|
||||
<span className={styles.devTag}>{plugin.source === "linked" ? tx("linked") : tx("dev")}</span>
|
||||
)}
|
||||
{update && <Badge tone="accent">{tx("Update")}</Badge>}
|
||||
{plugin.status === "failed" && (
|
||||
<Badge dot tone="danger">
|
||||
<T>Failed</T>
|
||||
@@ -555,8 +544,6 @@ function Homepage({ value }: { value: string }) {
|
||||
|
||||
function InstalledDetails({ plugin }: { plugin: PluginInfo }) {
|
||||
const busy = usePlugins((s) => !!s.busy[plugin.id]);
|
||||
const installing = usePlugins((s) => s.installing);
|
||||
const update = useMarketUpdate(plugin);
|
||||
const status = STATUS[plugin.status];
|
||||
const [confirmUninstall, setConfirmUninstall] = useState(false);
|
||||
|
||||
@@ -659,16 +646,6 @@ function InstalledDetails({ plugin }: { plugin: PluginInfo }) {
|
||||
</div>
|
||||
<div className={styles.headerActions}>
|
||||
{busy && <Spinner size={14} label="Working" />}
|
||||
{update && (
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
disabled={busy || installing}
|
||||
onClick={() => void installFromMarket(update.id)}
|
||||
>
|
||||
{tx`Update to ${update.version}`}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
size="small"
|
||||
variant={plugin.enabled ? "secondary" : "primary"}
|
||||
|
||||
@@ -1354,19 +1354,6 @@ describe("marketplace", () => {
|
||||
await waitFor(() => expect(consents.map(([id]) => id)).toEqual(["a", "b"]));
|
||||
});
|
||||
|
||||
it("marks installed plugins with updates and updates one from its details", async () => {
|
||||
setConsentPrompt(async () => ({ optional: [] }));
|
||||
const consents = updatesBackend({ a: preview("a", "1.1.0"), b: preview("b", "2.0.0") });
|
||||
const user = userEvent.setup();
|
||||
render(<PluginsPage />);
|
||||
await waitFor(() => expect(usePlugins.getState().market).toHaveLength(3));
|
||||
const list = screen.getByRole("list", { name: "Installed plugins" });
|
||||
expect(within(list).getAllByText("Update")).toHaveLength(2);
|
||||
await user.click(within(list).getAllByRole("button", { name: /^b/i })[0]!);
|
||||
await user.click(await screen.findByRole("button", { name: "Update to 2.0.0" }));
|
||||
await waitFor(() => expect(consents.map(([id]) => id)).toEqual(["b"]));
|
||||
});
|
||||
|
||||
it("announces updates with actions to install them or show the plugins", async () => {
|
||||
updatesBackend({ a: preview("a", "1.1.0"), b: preview("b", "2.0.0") });
|
||||
handlePluginEvent({
|
||||
|
||||
Reference in new issue
Block a user