Skip to content

Commit b600d37

Browse files
committed
fix(web-pet): align i18n namespace and restore lifecycle test
1 parent 2f8ec7b commit b600d37

11 files changed

Lines changed: 131 additions & 179 deletions

File tree

tests/test_group_lifecycle_ops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_group_start_does_not_resume_paused_group(self) -> None:
5757
"actor_id": "peer1",
5858
"title": "Peer 1",
5959
"runtime": "codex",
60-
"runner": "pty",
60+
"runner": "headless",
6161
"by": "user",
6262
},
6363
)

web/src/features/webPet/PetPanel.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function countAgentsByState(panelData: PanelData) {
2424
}
2525

2626
export function PetPanel({ panelData, align = "left", onClose, onAction, catSize = 80 }: PetPanelProps) {
27-
const { t } = useTranslation("modals");
27+
const { t } = useTranslation("webPet");
2828
const counts = countAgentsByState(panelData);
2929
const actionItems = panelData.actionItems.slice(0, 3);
3030

@@ -49,7 +49,7 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
4949
maxHeight: "calc(100vh - 48px)",
5050
...horizontalStyle,
5151
}}
52-
aria-label={t("webPet.panelAria", { defaultValue: "Web Pet panel" })}
52+
aria-label={t("panelAria", { defaultValue: "Web Pet panel" })}
5353
>
5454
<div className="flex max-h-[inherit] flex-col overflow-hidden rounded-2xl">
5555
<div className="shrink-0 border-b border-[var(--glass-border-subtle)] px-4 py-3">
@@ -75,7 +75,7 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
7575
type="button"
7676
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-sm text-[var(--color-text-secondary)] transition hover:bg-white/10 hover:text-[var(--color-text-primary)]"
7777
onClick={onClose}
78-
aria-label={t("webPet.closePanelAria", { defaultValue: "Close panel" })}
78+
aria-label={t("closePanelAria", { defaultValue: "Close panel" })}
7979
>
8080
×
8181
</button>
@@ -85,15 +85,15 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
8585
<div className="mt-3">
8686
<div className="flex items-center justify-between text-[11px] text-[var(--color-text-secondary)]">
8787
<span>
88-
{t("webPet.taskProgress", {
88+
{t("taskProgress", {
8989
defaultValue: "{{done}}/{{total}} done",
9090
done: panelData.taskProgress.done,
9191
total: panelData.taskProgress.total,
9292
})}
9393
</span>
9494
{panelData.taskProgress.active > 0 ? (
9595
<span>
96-
{t("webPet.taskActive", {
96+
{t("taskActive", {
9797
defaultValue: "{{count}} active",
9898
count: panelData.taskProgress.active,
9999
})}
@@ -112,19 +112,19 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
112112
) : null}
113113
<div className="mt-3 flex flex-wrap gap-2">
114114
<span className={countPillClass}>
115-
{t("webPet.countWorking", {
115+
{t("countWorking", {
116116
defaultValue: "{{count}} working",
117117
count: counts.working,
118118
})}
119119
</span>
120120
<span className={countPillClass}>
121-
{t("webPet.countBusy", {
121+
{t("countBusy", {
122122
defaultValue: "{{count}} busy",
123123
count: counts.busy,
124124
})}
125125
</span>
126126
<span className={countPillClass}>
127-
{t("webPet.countNeedsYou", {
127+
{t("countNeedsYou", {
128128
defaultValue: "{{count}} needs you",
129129
count: counts.needsYou,
130130
})}
@@ -167,8 +167,8 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
167167
{clickable ? (
168168
<span className="text-[10px] text-[var(--color-text-secondary)] opacity-60">
169169
{item.action!.type === "open_task"
170-
? t("webPet.actionView", { defaultValue: "View" })
171-
: t("webPet.actionReply", { defaultValue: "Reply" })}
170+
? t("action.view", { defaultValue: "View" })
171+
: t("action.reply", { defaultValue: "Reply" })}
172172
{" →"}
173173
</span>
174174
) : null}
@@ -182,7 +182,7 @@ export function PetPanel({ panelData, align = "left", onClose, onAction, catSize
182182
</div>
183183
) : (
184184
<div className="rounded-xl border border-dashed border-[var(--glass-border-subtle)] px-3 py-4 text-sm text-[var(--color-text-secondary)]">
185-
{t("webPet.noActionItems", {
185+
{t("noActionItems", {
186186
defaultValue: "No action items right now.",
187187
})}
188188
</div>

web/src/features/webPet/PetReminderBubble.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,25 @@ function getActionButtons(
1818

1919
if (reminder.kind === "waiting_user" && reminder.source.taskId) {
2020
buttons.push({
21-
label: String(t("webPet.action.complete" as never, { defaultValue: "Done" } as never)),
21+
label: String(t("action.complete", { defaultValue: "Done" })),
2222
action: {
2323
type: "complete_task",
2424
groupId: reminder.action.groupId,
2525
taskId: reminder.source.taskId,
2626
},
2727
});
2828
buttons.push({
29-
label: String(t("webPet.action.view" as never, { defaultValue: "View" } as never)),
29+
label: String(t("action.view", { defaultValue: "View" })),
3030
action: reminder.action,
3131
});
3232
} else if (reminder.kind === "reply_required") {
3333
buttons.push({
34-
label: String(t("webPet.action.reply" as never, { defaultValue: "Reply" } as never)),
34+
label: String(t("action.reply", { defaultValue: "Reply" })),
3535
action: reminder.action,
3636
});
3737
} else {
3838
buttons.push({
39-
label: String(t("webPet.action.view" as never, { defaultValue: "View" } as never)),
39+
label: String(t("action.view", { defaultValue: "View" })),
4040
action: reminder.action,
4141
});
4242
}
@@ -49,7 +49,7 @@ export function PetReminderBubble({
4949
onDismiss,
5050
onAction,
5151
}: PetReminderBubbleProps) {
52-
const { t } = useTranslation("modals");
52+
const { t } = useTranslation("webPet");
5353
const autoHideTimeoutRef = useRef<number | null>(null);
5454

5555
const clearAutoHideTimer = useCallback(() => {
@@ -92,7 +92,7 @@ export function PetReminderBubble({
9292
);
9393

9494
const displayAgent = reminder?.agent === "system"
95-
? t("webPet.systemAgent", { defaultValue: "System" })
95+
? t("systemAgent", { defaultValue: "System" })
9696
: reminder?.agent || "";
9797

9898
const label = useMemo(() => {
@@ -112,9 +112,9 @@ export function PetReminderBubble({
112112
}
113113

114114
const kindLabel = String(
115-
t(`webPet.kind.${reminder.kind}` as never, {
115+
t(`kind.${reminder.kind}`, {
116116
defaultValue: reminder.kind.replace(/_/g, " "),
117-
} as never),
117+
}),
118118
);
119119

120120
return (
@@ -175,7 +175,7 @@ export function PetReminderBubble({
175175
event.stopPropagation();
176176
handleDismiss();
177177
}}
178-
aria-label={t("webPet.dismissReminderAria", {
178+
aria-label={t("dismissReminderAria", {
179179
defaultValue: "Dismiss reminder",
180180
})}
181181
>

web/src/features/webPet/WebPetBubble.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function WebPetBubble({
1919
panelOpen,
2020
onTogglePanel,
2121
}: WebPetBubbleProps) {
22-
const { t } = useTranslation("modals");
22+
const { t } = useTranslation("webPet");
2323
const { isDragging, handlers } = useWebPetDrag();
2424

2525
return (
@@ -39,11 +39,11 @@ export function WebPetBubble({
3939
aria-expanded={panelOpen}
4040
aria-label={
4141
hint
42-
? t("webPet.bubbleAriaHint", {
42+
? t("bubbleAriaHint", {
4343
defaultValue: "Web Pet. {{hint}}",
4444
hint,
4545
})
46-
: t("webPet.bubbleAria", { defaultValue: "Web Pet" })
46+
: t("bubbleAria", { defaultValue: "Web Pet" })
4747
}
4848
onKeyDown={(event) => {
4949
if (event.key !== "Enter" && event.key !== " ") return;

web/src/features/webPet/useWebPetData.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ function localizeConnectionMessage(
1010
tr: (key: string, fallback: string, vars?: Record<string, unknown>) => string,
1111
): string {
1212
if (sseStatus === "connected") {
13-
return tr("webPet.connection.connected", "Connected");
13+
return tr("connection.connected", "Connected");
1414
}
1515
if (sseStatus === "connecting") {
16-
return tr("webPet.connection.connecting", "Connecting…");
16+
return tr("connection.connecting", "Connecting…");
1717
}
18-
return tr("webPet.connection.disconnected", "Disconnected");
18+
return tr("connection.disconnected", "Disconnected");
1919
}
2020

2121
function localizeReminder(
@@ -24,29 +24,29 @@ function localizeReminder(
2424
): PetReminder {
2525
const agentLabel =
2626
reminder.agent === "system"
27-
? tr("webPet.systemAgent", "System")
27+
? tr("systemAgent", "System")
2828
: reminder.agent;
2929

3030
let summary = reminder.summary;
3131
if (reminder.kind === "stalled_peer") {
3232
summary = tr(
33-
"webPet.reminderSummary.stalledPeer",
33+
"reminderSummary.stalledPeer",
3434
"{{actor}} has been idle for a while on {{taskId}}.",
3535
{
3636
actor: reminder.source.actorId || agentLabel,
37-
taskId: reminder.source.taskId || tr("webPet.taskFallback", "this task"),
37+
taskId: reminder.source.taskId || tr("taskFallback", "this task"),
3838
},
3939
);
4040
} else if (!summary.trim()) {
4141
if (reminder.kind === "mention") {
4242
summary = tr(
43-
"webPet.reminderSummary.mention",
43+
"reminderSummary.mention",
4444
"{{actor}} mentioned you.",
4545
{ actor: agentLabel },
4646
);
4747
} else if (reminder.kind === "reply_required") {
4848
summary = tr(
49-
"webPet.reminderSummary.replyRequired",
49+
"reminderSummary.replyRequired",
5050
"{{actor}} is waiting for your reply.",
5151
{ actor: agentLabel },
5252
);
@@ -68,12 +68,12 @@ function localizePanelData(
6868
...panelData,
6969
teamName:
7070
panelData.teamName.trim() ||
71-
tr("webPet.teamFallback", "Team"),
71+
tr("teamFallback", "Team"),
7272
actionItems: panelData.actionItems.map((item) => ({
7373
...item,
7474
agent:
7575
item.agent === "system"
76-
? tr("webPet.systemAgent", "System")
76+
? tr("systemAgent", "System")
7777
: item.agent,
7878
})),
7979
connection: {
@@ -84,7 +84,7 @@ function localizePanelData(
8484
}
8585

8686
export function useWebPetData() {
87-
const { t } = useTranslation("modals");
87+
const { t } = useTranslation("webPet");
8888
const selectedGroupId = useGroupStore((state) => state.selectedGroupId);
8989
const groupContext = useGroupStore((state) => state.groupContext);
9090
const groupDocTitle = useGroupStore((state) => state.groupDoc?.title ?? "");
@@ -94,7 +94,7 @@ export function useWebPetData() {
9494
const { reminders, activeReminder, reaction, dismissReminder } =
9595
useWebPetNotifications();
9696
const tr = (key: string, fallback: string, vars?: Record<string, unknown>) =>
97-
String(t(key as never, { defaultValue: fallback, ...(vars || {}) } as never));
97+
String(t(key, { defaultValue: fallback, ...(vars || {}) }));
9898

9999
return useMemo(() => {
100100
const { catState, panelData: rawPanelData } = aggregateWebPetState({
@@ -127,12 +127,12 @@ export function useWebPetData() {
127127
const needsYouCount = localizedPanelData.actionItems.length;
128128
hint = needsYouCount > 0
129129
? tr(
130-
"webPet.hintTaskWithAction",
130+
"hintTaskWithAction",
131131
"{{done}}/{{total}} done, {{count}} need you",
132132
{ done, total, count: needsYouCount },
133133
)
134134
: tr(
135-
"webPet.hintTaskProgress",
135+
"hintTaskProgress",
136136
"{{done}}/{{total}} tasks done",
137137
{ done, total },
138138
);

web/src/i18n/locales/en/modals.json

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -352,35 +352,5 @@
352352
"agents": "Agents",
353353
"tasks": "Tasks",
354354
"direction": "Direction"
355-
},
356-
"webPet": {
357-
"panelAria": "Web Pet panel",
358-
"closePanelAria": "Close panel",
359-
"dismissReminderAria": "Dismiss reminder",
360-
"bubbleAria": "Web Pet",
361-
"bubbleAriaHint": "Web Pet. {{hint}}",
362-
"teamFallback": "Team",
363-
"systemAgent": "System",
364-
"taskFallback": "this task",
365-
"connection": {
366-
"connected": "Connected",
367-
"connecting": "Connecting…",
368-
"disconnected": "Disconnected"
369-
},
370-
"countWorking": "{{count}} working",
371-
"countBusy": "{{count}} busy",
372-
"countNeedsYou": "{{count}} needs you",
373-
"noActionItems": "No action items right now.",
374-
"kind": {
375-
"waiting_user": "waiting user",
376-
"reply_required": "reply required",
377-
"stalled_peer": "stalled peer",
378-
"mention": "mention"
379-
},
380-
"reminderSummary": {
381-
"mention": "{{actor}} mentioned you.",
382-
"replyRequired": "{{actor}} is waiting for your reply.",
383-
"stalledPeer": "{{actor}} has been idle for a while on {{taskId}}."
384-
}
385355
}
386356
}
Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
{
2-
"panelLabel": "Web Pet panel",
3-
"closePanel": "Close panel",
4-
"noActionItems": "No pending items",
2+
"panelAria": "Web Pet panel",
3+
"closePanelAria": "Close panel",
4+
"dismissReminderAria": "Dismiss reminder",
5+
"bubbleAria": "Web Pet",
6+
"bubbleAriaHint": "Web Pet. {{hint}}",
7+
"teamFallback": "Team",
8+
"systemAgent": "System",
9+
"taskFallback": "this task",
10+
"connection": {
11+
"connected": "Connected",
12+
"connecting": "Connecting…",
13+
"disconnected": "Disconnected"
14+
},
515
"countWorking": "{{count}} working",
616
"countBusy": "{{count}} busy",
717
"countNeedsYou": "{{count}} needs you",
8-
"dismissReminder": "Dismiss reminder",
9-
"reminderKind_waiting_user": "waiting user",
10-
"reminderKind_reply_required": "reply required",
11-
"reminderKind_stalled_peer": "stalled peer",
12-
"reminderKind_mention": "mention",
13-
"reminderAction_complete": "Done",
14-
"reminderAction_view": "View",
15-
"reminderAction_reply": "Reply",
16-
"connectionConnected": "Connected",
17-
"connectionConnecting": "Connecting...",
18-
"connectionDisconnected": "Disconnected",
18+
"noActionItems": "No action items right now.",
19+
"kind": {
20+
"waiting_user": "waiting user",
21+
"reply_required": "reply required",
22+
"stalled_peer": "stalled peer",
23+
"mention": "mention"
24+
},
25+
"action": {
26+
"complete": "Done",
27+
"view": "View",
28+
"reply": "Reply"
29+
},
1930
"taskProgress": "{{done}}/{{total}} done",
2031
"taskActive": "{{count}} active",
21-
"actionView": "View",
22-
"actionReply": "Reply",
2332
"hintTaskProgress": "{{done}}/{{total}} tasks done",
24-
"hintTaskWithAction": "{{done}}/{{total}} done, {{count}} need you"
33+
"hintTaskWithAction": "{{done}}/{{total}} done, {{count}} need you",
34+
"reminderSummary": {
35+
"mention": "{{actor}} mentioned you.",
36+
"replyRequired": "{{actor}} is waiting for your reply.",
37+
"stalledPeer": "{{actor}} has been idle for a while on {{taskId}}."
38+
}
2539
}

0 commit comments

Comments
 (0)