+
{groupName ?? t`Group`}
- {headerSubtitle}
{awarenessLabel && awarenessEvent && speaker ? (
diff --git a/apps/web/src/components/voice/VoiceAwarenessStrip.tsx b/apps/web/src/components/voice/VoiceAwarenessStrip.tsx
index e299d11..f16b72a 100644
--- a/apps/web/src/components/voice/VoiceAwarenessStrip.tsx
+++ b/apps/web/src/components/voice/VoiceAwarenessStrip.tsx
@@ -20,7 +20,6 @@ export function VoiceAwarenessStrip({
handoff: t`Handoff`,
delegation: t`Delegated`,
"peer-reply": t`Peer reply`,
- working: t`In progress`,
}[event.kind];
const Icon =
event.kind === "subagent"
diff --git a/apps/web/src/lib/bot-persona.ts b/apps/web/src/lib/bot-persona.ts
index 2645819..04b5dfa 100644
--- a/apps/web/src/lib/bot-persona.ts
+++ b/apps/web/src/lib/bot-persona.ts
@@ -46,7 +46,7 @@ export interface BotPersonaProfile {
}
export interface VoiceAwarenessEvent {
- kind: "subagent" | "handoff" | "delegation" | "peer-reply" | "working";
+ kind: "subagent" | "handoff" | "delegation" | "peer-reply";
actorName: string;
detail: string;
targetName?: string;
@@ -347,13 +347,6 @@ export function extractVoiceAwareness(
}
}
}
- if (snapshot.run && ["running", "queued", "leased"].includes(snapshot.run.status)) {
- return {
- kind: "working",
- actorName: botName,
- detail: "",
- };
- }
return null;
}
@@ -372,8 +365,6 @@ export function narrateAwarenessForPersona(
return narrateDelegation(profile.archetype, specialist, task);
case "peer-reply":
return narratePeerReply(profile.archetype, event.actorName, task);
- case "working":
- return narrateWorking(profile.archetype, event.actorName);
default:
return task;
}
@@ -455,19 +446,6 @@ export function narrateGroupSpark(spark: GroupSpark, speakerArchetype?: PersonaA
}
}
-function narrateWorking(archetype: PersonaArchetype, name: string): string {
- switch (archetype) {
- case "cto-executive":
- return `${name} is in the work — give me a moment.`;
- case "quant":
- return `${name} is crunching — one beat.`;
- case "engineer":
- return `${name} is heads-down on this.`;
- default:
- return `${name} is working on your request.`;
- }
-}
-
function truncate(text: string, max: number): string {
const trimmed = text.trim();
if (trimmed.length <= max) return trimmed;
diff --git a/apps/web/src/locales/de/messages.po b/apps/web/src/locales/de/messages.po
index 901cd15..260de3a 100644
--- a/apps/web/src/locales/de/messages.po
+++ b/apps/web/src/locales/de/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr "1:1-Unterhaltung mit {title}"
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr "1:1 mit {0}"
@@ -2796,7 +2794,6 @@ msgstr "OpenAPI-JSON importieren"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr "In meinem Fachgebiet — ich gehe gern ins Detail oder setze einfach um, du entscheidest."
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr "In Arbeit"
diff --git a/apps/web/src/locales/en/messages.po b/apps/web/src/locales/en/messages.po
index 7bb7a10..a0b1b88 100644
--- a/apps/web/src/locales/en/messages.po
+++ b/apps/web/src/locales/en/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr "1:1 conversation with {title}"
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr "1:1 with {0}"
@@ -2796,7 +2794,6 @@ msgstr "Import OpenAPI JSON"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr "In my lane — happy to geek out or just execute, your call."
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr "In progress"
diff --git a/apps/web/src/locales/es/messages.po b/apps/web/src/locales/es/messages.po
index de2e52f..9f4e3b9 100644
--- a/apps/web/src/locales/es/messages.po
+++ b/apps/web/src/locales/es/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "Importar JSON de OpenAPI"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/hi/messages.po b/apps/web/src/locales/hi/messages.po
index d434e10..cf85a9c 100644
--- a/apps/web/src/locales/hi/messages.po
+++ b/apps/web/src/locales/hi/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "OpenAPI JSON इम्पोर्ट करें"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/ko/messages.po b/apps/web/src/locales/ko/messages.po
index cb7e027..0da0535 100644
--- a/apps/web/src/locales/ko/messages.po
+++ b/apps/web/src/locales/ko/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "OpenAPI JSON 가져오기"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/pt-BR/messages.po b/apps/web/src/locales/pt-BR/messages.po
index f0a5865..219e406 100644
--- a/apps/web/src/locales/pt-BR/messages.po
+++ b/apps/web/src/locales/pt-BR/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "Importar OpenAPI JSON"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/ru/messages.po b/apps/web/src/locales/ru/messages.po
index cfd504e..c47c8c4 100644
--- a/apps/web/src/locales/ru/messages.po
+++ b/apps/web/src/locales/ru/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "Импортировать OpenAPI JSON"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/tr/messages.po b/apps/web/src/locales/tr/messages.po
index c45dc4a..e4a4afb 100644
--- a/apps/web/src/locales/tr/messages.po
+++ b/apps/web/src/locales/tr/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "OpenAPI JSON içe aktar"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/locales/zh-CN/messages.po b/apps/web/src/locales/zh-CN/messages.po
index 3b41a24..1ede177 100644
--- a/apps/web/src/locales/zh-CN/messages.po
+++ b/apps/web/src/locales/zh-CN/messages.po
@@ -319,8 +319,6 @@ msgid "1:1 conversation with {title}"
msgstr ""
#. placeholder {0}: mainConversationEntry.bot.name
-#. placeholder {0}: speaker.name
-#: src/components/stage/OoStage.tsx
#: src/pages/Shell.tsx
msgid "1:1 with {0}"
msgstr ""
@@ -2796,7 +2794,6 @@ msgstr "导入 OpenAPI JSON"
msgid "In my lane — happy to geek out or just execute, your call."
msgstr ""
-#: src/components/voice/VoiceAwarenessStrip.tsx
#: src/pages/ProjectSessionTimeline.tsx
msgid "In progress"
msgstr ""
diff --git a/apps/web/src/pages/ActivityList.tsx b/apps/web/src/pages/ActivityList.tsx
index 41f0b06..0cb4e5b 100644
--- a/apps/web/src/pages/ActivityList.tsx
+++ b/apps/web/src/pages/ActivityList.tsx
@@ -2,6 +2,7 @@ import { i18n } from "@lingui/core";
import { t } from "@lingui/core/macro";
import { Trans, useLingui } from "@lingui/react/macro";
import type { RunActivityRow } from "@rakazo/contracts";
+import { runChatTitle } from "@rakazo/core";
import { useEffect, useState } from "react";
import { isNeedsYouStatus, runActivityLabel } from "../lib/agent-activity";
import { rpc } from "../lib/rpc";
@@ -93,7 +94,7 @@ export function ActivityList({ onOpenRun }: ActivityListProps) {
function ActivityRow({ run, onOpen }: { run: RunActivityRow; onOpen: () => void }) {
const { t } = useLingui();
- const title = run.groupName ? `${run.botName} · ${run.groupName}` : run.botName;
+ const title = runChatTitle(run);
const label = statusLabel(run.status);
const activityLabel = t`${title}, ${label}`;
const tone = statusTone(run.status);
diff --git a/apps/web/src/pages/HeuteBrief.tsx b/apps/web/src/pages/HeuteBrief.tsx
index 9379b9b..99660bc 100644
--- a/apps/web/src/pages/HeuteBrief.tsx
+++ b/apps/web/src/pages/HeuteBrief.tsx
@@ -8,6 +8,7 @@ import type {
HabitToday,
RunActivityRow,
} from "@rakazo/contracts";
+import { runChatTitle } from "@rakazo/core";
import { botColors } from "@rakazo/ui-tokens";
import { BotAvatar, Button, EvooMascot, GroupAvatar, Icon } from "@rakazo/ui-web";
import { CircleCheck, Pause, Play, Square } from "lucide-react";
@@ -347,7 +348,7 @@ function NeedsYouRow({
if (item.kind === "run") {
const run = item.run;
- const title = run.groupName ? `${run.botName} · ${run.groupName}` : run.botName;
+ const title = runChatTitle(run);
const subtitle = run.promptSnippet || runActivityLabel(run.status);
const label = t`${title}, ${runActivityLabel(run.status)}`;
return (
@@ -418,7 +419,7 @@ function DoingRow({
}) {
const { t } = useLingui();
const run = item.run;
- const title = run.groupName ? `${run.botName} · ${run.groupName}` : run.botName;
+ const title = runChatTitle(run);
const subtitle = run.promptSnippet || runActivityLabel(run.status);
const label = t`${title}, ${runActivityLabel(run.status)}`;
@@ -458,7 +459,7 @@ function DoneRow({
}) {
const { t } = useLingui();
const run = item.run;
- const title = run.groupName ? `${run.botName} · ${run.groupName}` : run.botName;
+ const title = runChatTitle(run);
const subtitle = run.promptSnippet || runActivityLabel(run.status);
const label = t`${title}, ${runActivityLabel(run.status)}`;
diff --git a/apps/web/src/pages/shell/transcript.tsx b/apps/web/src/pages/shell/transcript.tsx
index e3ba975..a19aa1d 100644
--- a/apps/web/src/pages/shell/transcript.tsx
+++ b/apps/web/src/pages/shell/transcript.tsx
@@ -313,15 +313,16 @@ export const Transcript = memo(function Transcript({
{
lastScrollTop.current = event.currentTarget.scrollTop;
autoScrolling.current = false;
- following.current = false;
+ following.current = transcriptIsNearEnd(event.currentTarget);
}}
onTouchStart={(event) => {
lastScrollTop.current = event.currentTarget.scrollTop;
autoScrolling.current = false;
- following.current = false;
+ following.current = transcriptIsNearEnd(event.currentTarget);
}}
onWheel={(event) => {
if (event.deltaY < 0) {
diff --git a/packages/adapters/src/executor.ts b/packages/adapters/src/executor.ts
index 43bc0da..6d1b5c5 100644
--- a/packages/adapters/src/executor.ts
+++ b/packages/adapters/src/executor.ts
@@ -4104,6 +4104,7 @@ export function createRunExecutor(deps: ExecutorDeps) {
? "Use list_secrets to discover saved names, secret_request to make authenticated requests without reading credentials, and forget_secret to revoke access."
: undefined,
"Never ask for a raw credential in chat or inject it into shell commands.",
+ "Tell the user what you do in plain words; never name your tools to them.",
exposedToolNames.has("remember") ? "Use remember for durable facts." : undefined,
exposedToolNames.has("scratchpad_add")
? "Use scratchpad_add / scratchpad_update / scratchpad_complete for open work that should outlive this turn (not reminders — those are schedule_*)."
diff --git a/packages/core/src/run-state.test.ts b/packages/core/src/run-state.test.ts
index e82cbe1..6b61fe2 100644
--- a/packages/core/src/run-state.test.ts
+++ b/packages/core/src/run-state.test.ts
@@ -1,6 +1,6 @@
import * as fc from "fast-check";
import { describe, expect, it } from "vitest";
-import { assertTransition, canTransition } from "./run-state.js";
+import { assertTransition, canTransition, runChatTitle } from "./run-state.js";
describe("run state machine", () => {
it("allows takeover resume onto a lease", () => {
@@ -30,3 +30,11 @@ describe("run state machine", () => {
);
});
});
+
+describe("runChatTitle", () => {
+ it("names the group unless it repeats the bot's name", () => {
+ expect(runChatTitle({ botName: "Writer", groupName: "Launch" })).toBe("Writer · Launch");
+ expect(runChatTitle({ botName: "Chief", groupName: "Chief" })).toBe("Chief");
+ expect(runChatTitle({ botName: "Chief", groupName: null })).toBe("Chief");
+ });
+});
diff --git a/packages/core/src/run-state.ts b/packages/core/src/run-state.ts
index ec2ce84..99fc6b7 100644
--- a/packages/core/src/run-state.ts
+++ b/packages/core/src/run-state.ts
@@ -41,3 +41,10 @@ export function isTerminal(status: RunStatus): boolean {
export function nextFence(current: number): number {
return current + 1;
}
+
+/** A run's chat as one label: the bot, and its group unless the group carries the bot's name. */
+export function runChatTitle(run: { botName: string; groupName: string | null }): string {
+ return run.groupName && run.groupName !== run.botName
+ ? `${run.botName} · ${run.groupName}`
+ : run.botName;
+}