feat: add URL-driven workspace state and streamed Codex research

This commit is contained in:
2026-09-28 20:08:28 +09:00
parent 85d23a328b
commit 8085ad2f90
207 changed files with 15287 additions and 16026 deletions
+18 -39
View File
@@ -1,64 +1,43 @@
import { conversations } from '#/features/support/mock-conversations'
import { useWorkspaceState } from '#/features/workspace/workspace-state'
import { conversations } from "#/features/support/mock-conversations";
import { useWorkspaceState } from "#/features/workspace/workspace-state";
export function DailyBrief({
onOpenContact,
}: {
onOpenContact: (id: string) => void
}) {
const { tasks, statuses, entries } = useWorkspaceState()
const focus = tasks.find(
(task) => task.section === 'focus' && task.status === 'todo',
)
const optional = tasks.find(
(task) => task.section === 'optional' && task.status === 'todo',
)
const contacts = conversations.filter(
(person) => (statuses[person.id] ?? 'now') === 'now',
)
const firstContact = contacts[0]
export function DailyBrief({ onOpenContact }: { onOpenContact: (id: string) => void }) {
const { tasks, statuses, entries } = useWorkspaceState();
const focus = tasks.find((task) => task.section === "focus" && task.status === "todo");
const optional = tasks.find((task) => task.section === "optional" && task.status === "todo");
const contacts = conversations.filter((person) => (statuses[person.id] ?? "now") === "now");
const firstContact = contacts[0];
const resume = entries.find(
(entry) =>
entry.kind === '再開地点' &&
!entries.some((other) => other.correctionOf === entry.id),
)
entry.kind === "再開地点" && !entries.some((other) => other.correctionOf === entry.id),
);
return (
<section className="home-brief" aria-label="Daily brief">
<p>
{focus
? `Start with “${focus.title}” today.`
: 'There are no priority tasks right now.'}
{focus ? `Start with “${focus.title}” today.` : "There are no priority tasks right now."}
{firstContact ? (
<>
{' '}
<button
type="button"
onClick={() => onOpenContact(firstContact.id)}
>
{" "}
<button type="button" onClick={() => onOpenContact(firstContact.id)}>
Reply to {firstContact.name}
</button>
{contacts.length > 1
? ` — one of ${contacts.length} conversations to review.`
: ' when you’re ready.'}
: " when you’re ready."}
</>
) : (
' There are no conversations awaiting your attention.'
" There are no conversations awaiting your attention."
)}
</p>
{resume ? (
<p className="home-brief-secondary">
Your resume note: “
{resume.text.length > 100
? `${resume.text.slice(0, 100)}…`
: resume.text}
”
{resume.text.length > 100 ? `${resume.text.slice(0, 100)}…` : resume.text}”
</p>
) : optional ? (
<p className="home-brief-secondary">
“{optional.title}” can wait until you have room.
</p>
<p className="home-brief-secondary">“{optional.title}” can wait until you have room.</p>
) : null}
</section>
)
);
}