Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/activity-without-nested-scroll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Show every reasoning step and tool in the Brunch Activity fold instead of clipping them in a nested scroll area, so the visible list always matches the tool count.
5 changes: 5 additions & 0 deletions .changeset/brunch-activity-labels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Show activity wording instead of naming Brunch during a turn. The waiting row and the default working status read "Working…", and the Voice brief reads "Preparing request", "Sending request", then "Request sent".
5 changes: 5 additions & 0 deletions .changeset/brunch-activity-stays-put.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Keep the Brunch Activity row in place through a turn. A spoken Live reply no longer takes over the Working… row, and the row's label no longer shifts when the spinner gives way to the Activity icon.
5 changes: 5 additions & 0 deletions .changeset/brunch-tab-fade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Stop Brunch assistant tabs inheriting the stock tab fade, so the Brunch selected and hover treatment applies on its own.
5 changes: 5 additions & 0 deletions .changeset/brunch-waiting-in-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Show Brunch's waiting state in the transcript, where the turn's Activity will appear, and keep the spinner in the Activity header while Brunch works. The status row above the composer now appears only while the host tab is shown.
5 changes: 5 additions & 0 deletions .changeset/voice-settings-copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hashintel/petrinaut": patch
---

Shorten Voice audio settings help: the voice note reads "Applies next session. To preview, mute your mic while the agent is idle." and disabled controls read "Connect Voice to use audio controls."
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ test.each([
props: { brunchConfigured: false },
control: "Use Brunch",
checked: false,
description:
"Brunch is unavailable because this site has no Brunch endpoint configured.",
description: "Brunch isn’t set up on this site.",
Comment thread
kostandinang marked this conversation as resolved.
},
{
name: "Voice preference loading",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ export const AssistantLabsSettings = ({
const brunchDescription = !assistantReady
? "Loading your assistant preference…"
: !brunchConfigured
? "Brunch is unavailable because this site has no Brunch endpoint configured."
: "Use Brunch instead of the stock Petrinaut assistant.";
? "Brunch isn’t set up on this site."
: "Use Brunch instead of the default assistant.";
const voiceDescription = !voicePreferenceReady
? "Loading your Voice preference…"
: !brunchSelected
Expand All @@ -129,7 +129,7 @@ export const AssistantLabsSettings = ({
? "Checking whether Voice is available…"
: openAIVoiceConfig === null
? "Voice is unavailable in this deployment."
: "Make Voice mode available for Brunch conversations.";
: "Talk to Brunch by voice.";

return (
<section className={sectionStyle} aria-label="AI assistant">
Expand All @@ -155,7 +155,7 @@ export const AssistantLabsSettings = ({
/>
{brunchSelected && voicePreferenceReady && voiceEnabled && (
<AssistantSetting
description="Switch to an alternative voice engine if you’re having trouble with Live."
description="Use the alternative voice engine if Voice isn’t working well."
disabled={!realtimePreferenceReady || !openAIVoiceConfig}
label="Realtime mode"
onChange={setRealtimeEnabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,5 @@ test("a changed net after the read requires another canonical read before a draf
{ ...snapshot, messages } as FlueConversationState,
"draft-1",
),
).rejects.toThrow(/latest settled canonical net read/u);
).rejects.toThrow(/read the latest model before drafting/u);
});
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ describe("BrunchDraftExperimentWidget", () => {
await waitFor(() => expect(submit).toHaveBeenCalledTimes(1));
expect(heading()).toEqual(["Preparing draft"]);
expect(screen.getByText(/being prepared/u)).toBeTruthy();
expect(screen.queryByText(/before this editor was loaded/u)).toBeNull();
expect(screen.queryByText(/is from an earlier session/u)).toBeNull();
expect(screen.queryByRole("button", { name: "Run" })).toBeNull();

await act(async () => submission.resolve());
Expand Down Expand Up @@ -423,7 +423,7 @@ describe("BrunchDraftExperimentWidget", () => {
name: "Run",
});
expect(run.disabled).toBe(true);
expect(screen.getByRole("alert").textContent).toContain("Run is blocked");
expect(screen.getByRole("alert").textContent).toContain("Can’t run");
fireEvent.click(run);
expect(runExperiment).not.toHaveBeenCalled();
},
Expand Down Expand Up @@ -534,7 +534,7 @@ describe("BrunchDraftExperimentWidget", () => {
await waitFor(() => expect(submit).toHaveBeenCalledTimes(1));
expect(submit.mock.calls[0]?.[0]).toMatchObject({ status: "invalid" });
expect(submit.mock.calls[0]?.[0].diagnostics[0]).toMatch(
/changed since the canonical read/u,
/changed since the AI assistant read it/u,
);
expect(heading()).toEqual(["Could not be prepared"]);
expect(screen.queryByRole("button", { name: "Run" })).toBeNull();
Expand Down Expand Up @@ -1441,9 +1441,7 @@ describe("BrunchDraftExperimentWidget", () => {

expect(submit).not.toHaveBeenCalled();
expect(heading()).toEqual(["Not retained in this editor"]);
expect(
screen.getByText(/prepared before this editor was loaded/u),
).toBeTruthy();
expect(screen.getByText(/draft is from an earlier session/u)).toBeTruthy();
expect(screen.queryByRole("button", { name: "Run" })).toBeNull();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export const resolveDraftAuthorityFromHistory = async (
latest.state !== "output-available"
)
throw new Error(
"Draft requires the latest settled canonical net read after changes.",
"The AI assistant needs to read the latest model before drafting.",
);
const envelope = latest.output;
const metadata =
Expand All @@ -192,7 +192,9 @@ export const resolveDraftAuthorityFromHistory = async (
: undefined;
const revision = metadata?.documentRevision.before;
if (revision === undefined)
throw new Error("The latest canonical read has no document revision.");
throw new Error(
"The AI assistant’s latest model read has no document revision.",
);
return revision;
};

Expand Down Expand Up @@ -320,7 +322,7 @@ export const BrunchDraftExperimentWidget = ({
: {
prepared: null,
error:
"The model changed since the canonical read. Ask Brunch to read the current model and draft again.",
"The model changed since the AI assistant read it. Ask it to draft again.",
};
} catch (caught) {
outcome = {
Expand Down Expand Up @@ -606,7 +608,7 @@ export const BrunchDraftExperimentWidget = ({
? preparationFailure.kind === "prepare"
? `The experiment proposal could not be prepared: ${preparationFailure.message}`
: `The prepared proposal could not be submitted: ${preparationFailure.message}`
: "This draft was prepared before this editor was loaded. Ask Brunch to draft it again to run it.")}
: "This draft is from an earlier session. Ask the AI assistant to draft it again to run it.")}
</p>
)}
<p className={sectionLabelStyle}>Declared</p>
Expand All @@ -620,8 +622,7 @@ export const BrunchDraftExperimentWidget = ({
<p className={sectionLabelStyle}>Not carried into execution</p>
{input.unsupported.length === 0 ? (
<p className={bodyStyle}>
No restrictions were stated. The request carries no constraints, so
none are enforced.
No restrictions were stated, so none are enforced.
</p>
) : (
<ul className={listStyle}>
Expand All @@ -639,8 +640,9 @@ export const BrunchDraftExperimentWidget = ({
)}
{blocksRun ? (
<p className={noticeStyle} role="alert">
Run is blocked by an unsupported restriction. Ask Brunch to revise the
proposal; a reporting-only exploration needs your explicit acceptance.
Can’t run: a restriction isn’t supported. Ask the AI assistant to
revise the proposal, or tell it you accept a run that only reports on
it.
</p>
) : null}
{optimizationUnavailable !== null ? (
Expand All @@ -657,7 +659,7 @@ export const BrunchDraftExperimentWidget = ({
<div className={noticeStyle}>
<p role="status">
The model changed since this was drafted. Review the changes below
before running, or ask Brunch to draft it again.
before running, or ask the AI assistant to draft it again.
</p>
<details>
<summary>Review model changes</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const BrunchExperimentFollowUp = ({
context.status === "submitted" ||
context.status === "streaming"
}
tooltip="The experiment finished, but its results could not be sent to Brunch."
tooltip="The experiment finished, but its results could not be sent to the AI assistant."
onClick={() => sendResults(drafts, context.submitText, failed)}
>
Retry result summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ const summarizeSweepOutput = (
switch (sweep.status) {
case "no-settled-range":
return {
title: "No settled range to sweep",
detail: "The conversation has no settled user entries.",
title: "Nothing confirmed to sweep yet",
detail: "None of your messages in this conversation are confirmed yet.",
};
case "refused":
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ describe("Brunch tool presentation", () => {
test.each([
[
{ includeContent: false, sourceIds: ["m1"], locateTexts: ["claim"] },
"Read settled passages and conversation sources",
"Read confirmed passages and conversation sources",
],
[
{ includeContent: false, locateTexts: ["claim"] },
"Read settled passages",
"Read confirmed passages",
],
[{ includeContent: false, sourceIds: ["m1"] }, "Read conversation sources"],
[{ includeContent: false, sourceIds: [] }, "Checked Ledger revision"],
[{ includeContent: false }, "Checked Ledger revision"],
[{ includeContent: false, sourceIds: [] }, "Checked for Ledger updates"],
[{ includeContent: false }, "Checked for Ledger updates"],
[{ includeContent: true, sourceIds: ["m1"] }, "Read conversation sources"],
[{}, "Read ledger"],
[undefined, "Read ledger"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ const lifecycleTitles = {
error: "Could not check recorded basis",
},
[brunchTools.ping]: {
pending: "Checking Brunch connection",
success: "Checked Brunch connection",
error: "Could not reach Brunch",
pending: "Checking connection to the AI assistant",
success: "Checked connection to the AI assistant",
error: "Could not reach the AI assistant",
},
} satisfies Record<VisibleOrdinaryBrunchToolName, LifecycleTitles>;

Expand Down Expand Up @@ -117,16 +117,16 @@ const readWorkpiecePurpose = (input: unknown): LifecycleTitles => {

if (hasPassages && hasSources) {
return {
pending: "Reading settled passages and conversation sources",
success: "Read settled passages and conversation sources",
error: "Could not read settled passages and conversation sources",
pending: "Reading confirmed passages and conversation sources",
success: "Read confirmed passages and conversation sources",
error: "Could not read confirmed passages and conversation sources",
};
}
if (hasPassages) {
return {
pending: "Reading settled passages",
success: "Read settled passages",
error: "Could not read settled passages",
pending: "Reading confirmed passages",
success: "Read confirmed passages",
error: "Could not read confirmed passages",
};
}
if (hasSources) {
Expand All @@ -138,9 +138,9 @@ const readWorkpiecePurpose = (input: unknown): LifecycleTitles => {
}
if (record.includeContent === false) {
return {
pending: "Checking Ledger revision",
success: "Checked Ledger revision",
error: "Could not check Ledger revision",
pending: "Checking for Ledger updates",
success: "Checked for Ledger updates",
error: "Could not check for Ledger updates",
};
}
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ test("does not display the input of a typed refused settlement or mark it newer"
);
expect(html).toContain("<h1>Settled account</h1>");
expect(html).not.toContain("Refused silent-shrink account");
expect(html).not.toContain("A newer Ledger revision exists");
expect(html).not.toContain("This view is out of date");
});

test("does not display the input of a failed settlement", () => {
Expand Down Expand Up @@ -150,7 +150,7 @@ test("does not display the input of a failed settlement", () => {
);
expect(html).toContain("<h1>Settled account</h1>");
expect(html).not.toContain("Refused stale-base account");
expect(html).not.toContain("A newer Ledger revision exists");
expect(html).not.toContain("This view is out of date");
});

test("a later settlement replaces the displayed query while retaining the recorded why", () => {
Expand All @@ -164,9 +164,7 @@ test("a later settlement replaces the displayed query while retaining the record
/>,
);
expect(html).toContain("<h1>Later account</h1>");
expect(html).toContain(
"recorded explanation predates a newer Ledger revision",
);
expect(html).toContain("This explanation is out of date");
});

test("an explicit later query replaces a recorded settlement", () => {
Expand Down Expand Up @@ -195,7 +193,7 @@ test("a later settlement whose output is not bound to its call marks the display
/>,
);
expect(html).toContain("<h1>Earlier account</h1>");
expect(html).toContain("A newer Ledger revision exists");
expect(html).toContain("This view is out of date");
expect(html).not.toContain("Unbound account");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const BrunchWorkpiecePane = ({
const workpiece = report?.workpiece;
return (
<section
aria-label="Brunch Ledger"
aria-label="Ledger"
className={css({
minWidth: "0",
userSelect: "text",
Expand All @@ -70,14 +70,12 @@ export const BrunchWorkpiecePane = ({
>
{stateChangedSinceReport && (
<p role="status" className={noticeStyle}>
A newer Ledger revision exists. Ask Brunch to refresh this view before
relying on it.
This view is out of date. Ask the AI assistant to refresh it.
</p>
)}
{whyPredatesSettlement && (
<p role="status" className={noticeStyle}>
The recorded explanation predates a newer Ledger revision. Ask why
again to assess the latest account.
This explanation is out of date. Ask why again for the latest.
</p>
)}
{workpiece && typeof workpiece.markdown === "string" && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ describe("local storage demo Brunch voice integration", () => {
]),
);
expect(aiAssistant.resolveToolPresentation).toBeTypeOf("function");
expect(aiAssistant.workingLabel).toBe("Brunch is working");
expect(aiAssistant.workingLabel).toBe("Working…");
expect(
aiAssistant.resolveToolPresentation?.({
toolName: "layout_petrinaut_net",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ export const LocalStorageDemoApp = ({
presentation: "brunch" as const,
mapMessagesForDisplay: mapVoiceMessages,
resolveToolPresentation: resolveBrunchToolPresentation,
workingLabel: "Brunch is working",
workingLabel: "Working…",
renderComposerControl: (
context: PetrinautAiComposerControlContext,
) => <BrunchExperimentFollowUp context={context} />,
Expand Down
Loading
Loading