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
1 change: 1 addition & 0 deletions packages/app/src/components/session/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { SessionHeader } from "./session-header"
export { SessionContextTab } from "./session-context-tab"
export { SessionWorkersTab } from "./session-workers-tab"
export { SortableTab, FileVisual } from "./session-sortable-tab"
export { SortableTerminalTab } from "./session-sortable-terminal-tab"
export { NewSessionView } from "./session-new-view"
45 changes: 45 additions & 0 deletions packages/app/src/components/session/session-workers-tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { For, Show, createMemo, type JSX } from "solid-js"
import type { CoordTeamSummary } from "@opencode-ai/sdk/v2/client"
import { useLanguage } from "@/context/language"

export function SessionWorkersTab(props: { summary: CoordTeamSummary | null | undefined }): JSX.Element {
const language = useLanguage()
const members = createMemo(() => props.summary?.team.members ?? [])
const inbox = createMemo(() => props.summary?.inbox ?? [])
const unreadFor = (name: string) => inbox().find((item) => item.name === name)?.unread ?? 0

return (
<div class="flex flex-col h-full overflow-hidden">
<Show
when={props.summary}
fallback={<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center text-text-weak">{language.t("session.workers.empty")}</div>}
>
<div class="px-6 pt-3 pb-2 border-b border-border-weak-base">
<div class="text-14-medium text-text-strong">{props.summary?.team.name}</div>
<Show when={props.summary?.team.description}>
<div class="text-12-regular text-text-weak">{props.summary?.team.description}</div>
</Show>
</div>
<div class="flex-1 overflow-auto">
<For each={members()}>
{(member) => (
<div class="px-6 py-2 border-b border-border-weak-base flex items-center justify-between">
<div class="flex flex-col">
<div class="text-14-regular text-text-strong">{member.name}</div>
<div class="text-12-regular text-text-weak">{member.agentType}</div>
</div>
<Show when={unreadFor(member.name) > 0}>
{(count) => (
<div class="text-12-medium text-text-strong h-5 px-2 flex items-center justify-center rounded-full bg-surface-base">
{count()}
</div>
)}
</Show>
</div>
)}
</For>
</div>
</Show>
</div>
)
}
25 changes: 25 additions & 0 deletions packages/app/src/components/settings-permissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,31 @@ const ITEMS = [
title: "settings.permissions.tool.doom_loop.title",
description: "settings.permissions.tool.doom_loop.description",
},
{
id: "coord_team",
title: "settings.permissions.tool.coord_team.title",
description: "settings.permissions.tool.coord_team.description",
},
{
id: "coord_member",
title: "settings.permissions.tool.coord_member.title",
description: "settings.permissions.tool.coord_member.description",
},
{
id: "coord_message",
title: "settings.permissions.tool.coord_message.title",
description: "settings.permissions.tool.coord_message.description",
},
{
id: "coord_task",
title: "settings.permissions.tool.coord_task.title",
description: "settings.permissions.tool.coord_task.description",
},
{
id: "coord_session",
title: "settings.permissions.tool.coord_session.title",
description: "settings.permissions.tool.coord_session.description",
},
] as const

const VALID_ACTIONS = new Set<PermissionAction>(["allow", "ask", "deny"])
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/context/global-sync/child-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export function createChildStoreManager(input: {
session_status: {},
session_diff: {},
todo: {},
coord: {},
permission: {},
question: {},
mcp: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const baseState = (input: Partial<State> = {}) =>
limit: 10,
message: {},
part: {},
coord: {},
...input,
}) as State

Expand Down
17 changes: 13 additions & 4 deletions packages/app/src/context/global-sync/event-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
Session,
SessionStatus,
Todo,
CoordTeamSummary,
} from "@opencode-ai/sdk/v2/client"
import type { State, VcsCache } from "./types"
import { trimSessions } from "./session-trim"
Expand Down Expand Up @@ -44,10 +45,12 @@ function cleanupSessionCaches(store: Store<State>, setStore: SetStoreFunction<St
const hasAny =
store.message[sessionID] !== undefined ||
store.session_diff[sessionID] !== undefined ||
store.todo[sessionID] !== undefined ||
store.permission[sessionID] !== undefined ||
store.question[sessionID] !== undefined ||
store.session_status[sessionID] !== undefined
store.todo[sessionID] !== undefined ||
store.coord[sessionID] !== undefined ||
store.permission[sessionID] !== undefined ||
store.question[sessionID] !== undefined ||
store.session_status[sessionID] !== undefined

if (!hasAny) return
setStore(
produce((draft) => {
Expand All @@ -62,6 +65,7 @@ function cleanupSessionCaches(store: Store<State>, setStore: SetStoreFunction<St
delete draft.message[sessionID]
delete draft.session_diff[sessionID]
delete draft.todo[sessionID]
delete draft.coord[sessionID]
delete draft.permission[sessionID]
delete draft.question[sessionID]
delete draft.session_status[sessionID]
Expand Down Expand Up @@ -151,6 +155,11 @@ export function applyDirectoryEvent(input: {
input.setStore("todo", props.sessionID, reconcile(props.todos, { key: "id" }))
break
}
case "coord.summary.updated": {
const props = event.properties as { sessionID: string; summary: CoordTeamSummary }
input.setStore("coord", props.sessionID, reconcile(props.summary))
break
}
case "session.status": {
const props = event.properties as { sessionID: string; status: SessionStatus }
input.setStore("session_status", props.sessionID, reconcile(props.status))
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/context/global-sync/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
SessionStatus,
Todo,
VcsInfo,
CoordTeamSummary,
} from "@opencode-ai/sdk/v2/client"
import type { Accessor } from "solid-js"
import type { SetStoreFunction, Store } from "solid-js/store"
Expand Down Expand Up @@ -52,6 +53,9 @@ export type State = {
todo: {
[sessionID: string]: Todo[]
}
coord: {
[sessionID: string]: CoordTeamSummary | null
}
permission: {
[sessionID: string]: PermissionRequest[]
}
Expand Down
2 changes: 2 additions & 0 deletions packages/app/src/context/sync-optimistic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe("sync optimistic reducers", () => {
const draft = {
message: { [sessionID]: [userMessage("msg_2", sessionID)] },
part: {} as Record<string, Part[] | undefined>,
coord: {},
}

applyOptimisticAdd(draft, {
Expand All @@ -45,6 +46,7 @@ describe("sync optimistic reducers", () => {
msg_1: [textPart("prt_1", sessionID, "msg_1")],
msg_2: [textPart("prt_2", sessionID, "msg_2")],
} as Record<string, Part[] | undefined>,
coord: {},
}

applyOptimisticRemove(draft, { sessionID, messageID: "msg_1" })
Expand Down
26 changes: 25 additions & 1 deletion packages/app/src/context/sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { retry } from "@opencode-ai/util/retry"
import { createSimpleContext } from "@opencode-ai/ui/context"
import { useGlobalSync } from "./global-sync"
import { useSDK } from "./sdk"
import type { Message, Part } from "@opencode-ai/sdk/v2/client"
import type { Message, Part, CoordTeamSummary } from "@opencode-ai/sdk/v2/client"

const keyFor = (directory: string, id: string) => `${directory}\n${id}`

Expand All @@ -14,8 +14,10 @@ const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)
type OptimisticStore = {
message: Record<string, Message[] | undefined>
part: Record<string, Part[] | undefined>
coord: Record<string, CoordTeamSummary | null | undefined>
}


type OptimisticAddInput = {
sessionID: string
message: Message
Expand Down Expand Up @@ -67,6 +69,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
const inflight = new Map<string, Promise<void>>()
const inflightDiff = new Map<string, Promise<void>>()
const inflightTodo = new Map<string, Promise<void>>()
const inflightCoord = new Map<string, Promise<void>>()
const [meta, setMeta] = createStore({
limit: {} as Record<string, number>,
complete: {} as Record<string, boolean>,
Expand Down Expand Up @@ -291,6 +294,27 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
inflightTodo.set(key, promise)
return promise
},
async coord(sessionID: string) {
const directory = sdk.directory
const client = sdk.client
const [store, setStore] = globalSync.child(directory)
if (store.coord[sessionID] !== undefined) return

const key = keyFor(directory, sessionID)
const pending = inflightCoord.get(key)
if (pending) return pending

const promise = retry(() => client.session.coord({ sessionID }))
.then((coord) => {
setStore("coord", sessionID, reconcile(coord.data ?? null))
})
.finally(() => {
inflightCoord.delete(key)
})

inflightCoord.set(key, promise)
return promise
},
history: {
more(sessionID: string) {
const store = current()[0]
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ export const dict = {
"session.tab.session": "جلسة",
"session.tab.review": "مراجعة",
"session.tab.context": "سياق",
"session.tab.workers": "العمال",
"session.workers.empty": "لا يوجد عمّال بعد",
"session.panel.reviewAndFiles": "المراجعة والملفات",
"session.review.filesChanged": "تم تغيير {{count}} ملفات",
"session.review.change.one": "تغيير",
Expand Down Expand Up @@ -680,6 +682,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "الوصول إلى الملفات خارج دليل المشروع",
"settings.permissions.tool.doom_loop.title": "حلقة الموت",
"settings.permissions.tool.doom_loop.description": "اكتشاف استدعاءات الأدوات المتكررة بمدخلات متطابقة",
"settings.permissions.tool.coord_team.title": "فريق التنسيق",
"settings.permissions.tool.coord_team.description": "إنشاء فرق التنسيق وعرضها وحذفها",
"settings.permissions.tool.coord_member.title": "عضو التنسيق",
"settings.permissions.tool.coord_member.description": "إضافة أعضاء فريق التنسيق أو إزالتهم",
"settings.permissions.tool.coord_message.title": "رسالة التنسيق",
"settings.permissions.tool.coord_message.description": "إرسال وإدارة رسائل صندوق وارد الفريق",
"settings.permissions.tool.coord_task.title": "مهمة التنسيق",
"settings.permissions.tool.coord_task.description": "إنشاء مهام التنسيق وإدارتها",
"settings.permissions.tool.coord_session.title": "جلسة التنسيق",
"settings.permissions.tool.coord_session.description": "ربط الجلسات بفرق التنسيق",

"session.delete.failed.title": "فشل حذف الجلسة",
"session.delete.title": "حذف الجلسة",
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ export const dict = {
"session.tab.session": "Sessão",
"session.tab.review": "Revisão",
"session.tab.context": "Contexto",
"session.tab.workers": "Trabalhadores",
"session.workers.empty": "Nenhum trabalhador ainda",
"session.panel.reviewAndFiles": "Revisão e arquivos",
"session.review.filesChanged": "{{count}} Arquivos Alterados",
"session.review.change.one": "Alteração",
Expand Down Expand Up @@ -686,6 +688,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "Acessar arquivos fora do diretório do projeto",
"settings.permissions.tool.doom_loop.title": "Loop Infinito",
"settings.permissions.tool.doom_loop.description": "Detectar chamadas de ferramentas repetidas com entrada idêntica",
"settings.permissions.tool.coord_team.title": "Equipe de coordenação",
"settings.permissions.tool.coord_team.description": "Criar, listar e excluir equipes de coordenação",
"settings.permissions.tool.coord_member.title": "Membro de coordenação",
"settings.permissions.tool.coord_member.description": "Adicionar ou remover membros da equipe de coordenação",
"settings.permissions.tool.coord_message.title": "Mensagem de coordenação",
"settings.permissions.tool.coord_message.description": "Enviar e gerenciar mensagens da caixa de entrada da equipe",
"settings.permissions.tool.coord_task.title": "Tarefa de coordenação",
"settings.permissions.tool.coord_task.description": "Criar e gerenciar tarefas de coordenação",
"settings.permissions.tool.coord_session.title": "Sessão de coordenação",
"settings.permissions.tool.coord_session.description": "Vincular sessões a equipes de coordenação",

"session.delete.failed.title": "Falha ao excluir sessão",
"session.delete.title": "Excluir sessão",
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/bs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ export const dict = {
"session.tab.session": "Sesija",
"session.tab.review": "Pregled",
"session.tab.context": "Kontekst",
"session.tab.workers": "Radnici",
"session.workers.empty": "Još nema radnika",
"session.panel.reviewAndFiles": "Pregled i datoteke",
"session.review.filesChanged": "Izmijenjeno {{count}} datoteka",
"session.review.change.one": "Izmjena",
Expand Down Expand Up @@ -713,6 +715,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "Pristup datotekama izvan direktorija projekta",
"settings.permissions.tool.doom_loop.title": "Beskonačna petlja",
"settings.permissions.tool.doom_loop.description": "Otkriva ponovljene pozive alata sa identičnim unosom",
"settings.permissions.tool.coord_team.title": "Koordinacijski tim",
"settings.permissions.tool.coord_team.description": "Kreiraj, prikaži i izbriši koordinacijske timove",
"settings.permissions.tool.coord_member.title": "Koordinacijski član",
"settings.permissions.tool.coord_member.description": "Dodaj ili ukloni članove koordinacijskog tima",
"settings.permissions.tool.coord_message.title": "Koordinacijska poruka",
"settings.permissions.tool.coord_message.description": "Pošalji i upravljaj porukama timskog sandučića",
"settings.permissions.tool.coord_task.title": "Koordinacijski zadatak",
"settings.permissions.tool.coord_task.description": "Kreiraj i upravljaj koordinacijskim zadacima",
"settings.permissions.tool.coord_session.title": "Koordinacijska sesija",
"settings.permissions.tool.coord_session.description": "Poveži sesije s koordinacijskim timovima",

"session.delete.failed.title": "Neuspjelo brisanje sesije",
"session.delete.title": "Izbriši sesiju",
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ export const dict = {
"session.tab.session": "Session",
"session.tab.review": "Gennemgang",
"session.tab.context": "Kontekst",
"session.tab.workers": "Arbejdere",
"session.workers.empty": "Ingen arbejdere endnu",
"session.panel.reviewAndFiles": "Gennemgang og filer",
"session.review.filesChanged": "{{count}} Filer ændret",
"session.review.change.one": "Ændring",
Expand Down Expand Up @@ -685,6 +687,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "Få adgang til filer uden for projektmappen",
"settings.permissions.tool.doom_loop.title": "Doom Loop",
"settings.permissions.tool.doom_loop.description": "Opdag gentagne værktøjskald med identisk input",
"settings.permissions.tool.coord_team.title": "Koordineringsteam",
"settings.permissions.tool.coord_team.description": "Opret, vis og slet koordinationsteams",
"settings.permissions.tool.coord_member.title": "Koordineringsmedlem",
"settings.permissions.tool.coord_member.description": "Tilføj eller fjern koordinationsteammedlemmer",
"settings.permissions.tool.coord_message.title": "Koordineringsbesked",
"settings.permissions.tool.coord_message.description": "Send og administrer teamets indbakke-beskeder",
"settings.permissions.tool.coord_task.title": "Koordineringsopgave",
"settings.permissions.tool.coord_task.description": "Opret og administrer koordineringsopgaver",
"settings.permissions.tool.coord_session.title": "Koordineringssession",
"settings.permissions.tool.coord_session.description": "Knyt sessioner til koordinationsteams",

"session.delete.failed.title": "Kunne ikke slette session",
"session.delete.title": "Slet session",
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ export const dict = {
"session.tab.session": "Sitzung",
"session.tab.review": "Überprüfung",
"session.tab.context": "Kontext",
"session.tab.workers": "Mitarbeiter",
"session.workers.empty": "Noch keine Mitarbeiter",
"session.panel.reviewAndFiles": "Überprüfung und Dateien",
"session.review.filesChanged": "{{count}} Dateien geändert",
"session.review.change.one": "Änderung",
Expand Down Expand Up @@ -730,6 +732,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "Zugriff auf Dateien außerhalb des Projektverzeichnisses",
"settings.permissions.tool.doom_loop.title": "Doom Loop",
"settings.permissions.tool.doom_loop.description": "Wiederholte Tool-Aufrufe mit identischer Eingabe erkennen",
"settings.permissions.tool.coord_team.title": "Koordinationsteam",
"settings.permissions.tool.coord_team.description": "Koordinationsteams erstellen, auflisten und löschen",
"settings.permissions.tool.coord_member.title": "Koordinationsmitglied",
"settings.permissions.tool.coord_member.description": "Mitglieder von Koordinationsteams hinzufügen oder entfernen",
"settings.permissions.tool.coord_message.title": "Koordinationsnachricht",
"settings.permissions.tool.coord_message.description": "Team-Posteingangsnachrichten senden und verwalten",
"settings.permissions.tool.coord_task.title": "Koordinationsaufgabe",
"settings.permissions.tool.coord_task.description": "Koordinationsaufgaben erstellen und verwalten",
"settings.permissions.tool.coord_session.title": "Koordinationssitzung",
"settings.permissions.tool.coord_session.description": "Sitzungen mit Koordinationsteams verknüpfen",

"session.delete.failed.title": "Sitzung konnte nicht gelöscht werden",
"session.delete.title": "Sitzung löschen",
Expand Down
12 changes: 12 additions & 0 deletions packages/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ export const dict = {
"session.tab.session": "Session",
"session.tab.review": "Review",
"session.tab.context": "Context",
"session.tab.workers": "Workers",
"session.workers.empty": "No workers yet",
"session.panel.reviewAndFiles": "Review and files",
"session.review.filesChanged": "{{count}} Files Changed",
"session.review.change.one": "Change",
Expand Down Expand Up @@ -756,6 +758,16 @@ export const dict = {
"settings.permissions.tool.external_directory.description": "Access files outside the project directory",
"settings.permissions.tool.doom_loop.title": "Doom Loop",
"settings.permissions.tool.doom_loop.description": "Detect repeated tool calls with identical input",
"settings.permissions.tool.coord_team.title": "Coord Team",
"settings.permissions.tool.coord_team.description": "Create, list, and delete coordination teams",
"settings.permissions.tool.coord_member.title": "Coord Member",
"settings.permissions.tool.coord_member.description": "Add or remove coordination team members",
"settings.permissions.tool.coord_message.title": "Coord Message",
"settings.permissions.tool.coord_message.description": "Send and manage team inbox messages",
"settings.permissions.tool.coord_task.title": "Coord Task",
"settings.permissions.tool.coord_task.description": "Create and manage coordination tasks",
"settings.permissions.tool.coord_session.title": "Coord Session",
"settings.permissions.tool.coord_session.description": "Link sessions with coordination teams",

"session.delete.failed.title": "Failed to delete session",
"session.delete.title": "Delete session",
Expand Down
Loading
Loading