perf: faster plugin updates, half-size first bundle, images from the chat attach on Windows
- Chat view: an attached image's path is pasted on its own after the text (promptForPane). claude turns a paste that is only an image path into [Image #n], but left a Windows path inside a paste of text as a plain path. Other files and @-mentions stay in the text as before. - Plugin bootstrap: depsHash covers only what npm installs (no release version), so a version bump no longer reinstalls runtime deps; the client's installed tree is kept while its manifests are unchanged (no npm ci per update); the user-side build runs vite only (tsc -b cost ~25 s / ~900 MB); clientBuild is recorded only after a build that did not fail, so a failed one is retried; npm output goes to runtime/npm-install.log. - Server: a port held by another program ends with a clear message and exit 1 instead of an uncaught 'error' stack trace. - Client: the onboarding wizard is lazy and rendered only before onboarding; usePrefersReducedMotion moved to hooks/ so PetSettings no longer pulls the Sagi chat/pane stack into the entry chunk (884 KB -> 431 KB, gzip 268 -> 133 KB).
This commit is contained in:
@@ -267,7 +267,7 @@ describe("PaneChat — model, effort and permission mode", () => {
|
||||
renderChat();
|
||||
fireEvent.click(screen.getByRole("button", { name: /Opus/ }));
|
||||
fireEvent.click(await screen.findByRole("menuitemradio", { name: /Sonnet/ }));
|
||||
expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "/model sonnet");
|
||||
expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "/model sonnet", []);
|
||||
});
|
||||
|
||||
it("shows the mode the pane shows, and asks the server to step it", async () => {
|
||||
@@ -430,7 +430,7 @@ describe("PaneChat — the unsent prompt", () => {
|
||||
expect(screen.getByPlaceholderText("Write a message…")).toHaveValue("half typed");
|
||||
expect(screen.getByText("a.ts")).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByTestId("pane-chat-send"));
|
||||
expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "half typed @src/a.ts");
|
||||
expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "half typed @src/a.ts", []);
|
||||
await waitFor(() => expect(localStorage.getItem("agenthub.chat.draft.s1")).toBeNull());
|
||||
});
|
||||
|
||||
@@ -462,7 +462,8 @@ describe("PaneChat — the unsent prompt", () => {
|
||||
fireEvent.click(screen.getByTestId("pane-chat-send"));
|
||||
expect(submitToRun).toHaveBeenCalledWith(
|
||||
"agenthub-lane-1",
|
||||
'read @"/home/u/My Docs/spec.md" @/home/u/b.ts'
|
||||
'read @"/home/u/My Docs/spec.md" @/home/u/b.ts',
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -490,7 +491,7 @@ describe("PaneChat — the unsent prompt", () => {
|
||||
expect(box).toHaveValue("hello");
|
||||
confirmDialog.mockResolvedValueOnce(true);
|
||||
fireEvent.click(screen.getByTestId("pane-chat-send"));
|
||||
await waitFor(() => expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "hello"));
|
||||
await waitFor(() => expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "hello", []));
|
||||
});
|
||||
|
||||
it("sends without asking once the session has started", async () => {
|
||||
@@ -499,7 +500,7 @@ describe("PaneChat — the unsent prompt", () => {
|
||||
renderChat();
|
||||
fireEvent.change(screen.getByPlaceholderText("Write a message…"), { target: { value: "hi" } });
|
||||
fireEvent.click(screen.getByTestId("pane-chat-send"));
|
||||
await waitFor(() => expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "hi"));
|
||||
await waitFor(() => expect(submitToRun).toHaveBeenCalledWith("agenthub-lane-1", "hi", []));
|
||||
expect(confirmDialog).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
ModelPicker,
|
||||
PASTE_AS_FILE_CHARS,
|
||||
PromptEditor,
|
||||
promptForPane,
|
||||
promptWithImages,
|
||||
type PromptImage,
|
||||
} from "../RunSetup";
|
||||
@@ -586,3 +587,23 @@ describe("ModelMenu", () => {
|
||||
expect(onChange).toHaveBeenCalledWith("claude-sonnet-5-5");
|
||||
});
|
||||
});
|
||||
|
||||
describe("promptForPane — images apart, every other file in the text", () => {
|
||||
it("keeps @-mentions and other files in the text, and takes images out", () => {
|
||||
// A Windows path inside a paste of text stayed a plain path in claude; a
|
||||
// paste that is only the path becomes [Image #n].
|
||||
const images: PromptImage[] = [
|
||||
{ path: "C:\\Users\\u\\.claude\\agenthub\\drops\\f326fc666d3bdd92-image.png", name: "image.png" },
|
||||
{ path: "/data/drops/0123456789abcdef-log.txt", name: "log.txt" },
|
||||
{ path: '@"/home/u/My Docs/a.PNG"', name: "a.PNG" },
|
||||
{ path: "/data/drops/0123456789abcdef.JPG", name: "b.jpg" },
|
||||
];
|
||||
expect(promptForPane(" look ", images)).toEqual({
|
||||
text: 'look /data/drops/0123456789abcdef-log.txt @"/home/u/My Docs/a.PNG"',
|
||||
files: [
|
||||
"C:\\Users\\u\\.claude\\agenthub\\drops\\f326fc666d3bdd92-image.png",
|
||||
"/data/drops/0123456789abcdef.JPG",
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user