Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
a0464b0
feat(orchestration): implement orchestration control plane
Fodesu Apr 25, 2026
0a08367
feat(orchestration): implement runtime replan and workerd loop
Fodesu Apr 25, 2026
b8dd54c
feat(orchestration): add verifier runtime and worker loop
Fodesu Apr 26, 2026
4135224
refactor(orchestration): refine attempt binding runtime
Fodesu Apr 26, 2026
89493db
fix(orchestration): harden run barrier sibling pause handling
Fodesu Apr 26, 2026
8c10c24
feat(orchestration): add run barrier resume and API coverage
Fodesu Apr 26, 2026
53ab196
feat(orchestration): add HTTP runtime blackbox coverage
Fodesu Apr 26, 2026
114d5c9
feat(orchestration): add llm runtime execution and action ledger
Fodesu Apr 30, 2026
51a5212
feat(agent): expose orchestration tool and control APIs
Fodesu Apr 30, 2026
f3822b7
feat(deploy): bundle orchestration workers in docker
Fodesu Apr 30, 2026
7285432
feat(web): add orchestration run inspector
Fodesu Apr 30, 2026
e091b77
feat(orchestration): add run watch, hint, and retry controls
Fodesu Apr 30, 2026
f4636ab
fix(orchestration): tighten retry and hint runtime guards
Fodesu Apr 30, 2026
e19db9f
feat(orchestration): add LLM start-run planner
Fodesu Apr 30, 2026
548caa8
docs(orchestration): add runtime plane plan
Fodesu Apr 30, 2026
2b38098
feat(orchestration): tighten executor runtime boundary
Fodesu Apr 30, 2026
ac9d0b7
feat(orchestration): tighten planner output contract
Fodesu May 1, 2026
f8e3317
feat(orchestration): add LLM replanning runtime
Fodesu May 3, 2026
aee4c78
feat(orchestration): enforce planner runtime limits
Fodesu May 3, 2026
b279ce6
fix(orchestration): harden executor replay recovery
Fodesu May 3, 2026
9f13303
feat(orchestration): add verifier retry policy
Fodesu May 3, 2026
5ab7b19
feat(orchestration): delay automatic retry dispatch
Fodesu May 4, 2026
5d6d308
fix(agent): honor canceled mock generation context
Fodesu May 4, 2026
b3c9c6a
fix(orchestration): recover expired planning intents
Fodesu May 4, 2026
bb65cfc
fix(orchestration): fix kernel migration rollback order
Fodesu May 4, 2026
1986d44
feat(orchestration): add NATS event bus contract
Fodesu May 8, 2026
35ef292
feat(orchestration): publish committed run events through outbox
Fodesu May 8, 2026
e67eb41
feat(orchestration): publish attempt and verification facts
Fodesu May 8, 2026
0539907
feat(orchestration): validate attempt facts in kernel
Fodesu May 8, 2026
107b822
feat(web): stream orchestration run events over SSE
Fodesu May 8, 2026
308ef7b
feat(orchestration): recover timed-out human checkpoints
Fodesu May 8, 2026
2b17d4c
feat(web): clean up orchestration page after SSE rewrite
Fodesu May 8, 2026
eb1e9b2
docs(orchestration): rewrite plan around the staged RFC rollout
Fodesu May 8, 2026
2d6c13f
feat(orchestration): add blackboard contract and in-memory backend
Fodesu May 8, 2026
10c1cfc
feat(orchestration): enforce blackboard writer ownership and CAS
Fodesu May 8, 2026
baad888
feat(orchestration): add jetstream kv blackboard backend
Fodesu May 8, 2026
f0c304f
feat(orchestration): publish task results and capture revisions in di…
Fodesu May 8, 2026
92c9baf
feat(orchestration): rebuild blackboard view from Postgres on demand
Fodesu May 8, 2026
4e731a0
docs(plan): mark Stage 2 blackboard as landed and refresh next-step p…
Fodesu May 8, 2026
b7ce040
feat(orchestration): add Stage 3 env runtime durable schema
Fodesu May 8, 2026
686373a
feat(orchestration): introduce orchestrationenv Manager and lease model
Fodesu May 8, 2026
64bceb6
feat(orchestration): add container env backend over container.Service
Fodesu May 8, 2026
3493172
feat(orchestration): add browser env backend over the browser gateway
Fodesu May 8, 2026
bafaac8
feat(orchestration): record env preconditions on tasks and dispatch m…
Fodesu May 8, 2026
f1470f9
feat(orchestration): require env_preconditions on every planned task
Fodesu May 8, 2026
655731e
feat(orchestration): lease env sessions on dispatch and release on co…
Fodesu May 8, 2026
898e11b
feat(orchestration): wire env manager into cmd/agent and run reclaim …
Fodesu May 8, 2026
00aea7e
feat(orchestration): add env resource admin API
Fodesu May 8, 2026
10d64dc
feat(orchestration): record env actions in ledger
Fodesu May 8, 2026
fef5170
feat(orchestration): resume held env sessions after HITL
Fodesu May 8, 2026
ae98597
feat(orchestration): harden env execution and tool flows
Fodesu May 10, 2026
cc63808
feat(orchestration): refresh run and env management UI
Fodesu May 10, 2026
b1912dd
feat(orchestration): show node actions like chat tools
Fodesu May 10, 2026
7a47909
refactor(orchestration): rename planning intents
Fodesu May 10, 2026
ee41d30
feat(orchestration): rebuild run graph views
Fodesu May 10, 2026
e77f26d
style(orchestration): soften run view accents
Fodesu May 10, 2026
15fbade
refactor(orchestration): split control plane daemon
Fodesu May 10, 2026
9417b8c
refactor(orchestration): squash migrations
Fodesu May 11, 2026
46e3305
feat(orchestration): support task retry and cancel
Fodesu May 11, 2026
7c6b3c5
feat(orchestration): move task controls into run views
Fodesu May 11, 2026
12f2903
fix(orchestration): remove browser gateway
chen-ran May 17, 2026
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
635 changes: 635 additions & 0 deletions PLAN.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@tailwindcss/vite": "^4.2.2",
"@tanstack/vue-table": "^8.21.3",
"@vee-validate/zod": "^4.15.1",
"@vue-flow/core": "^1.45.0",
"@vueuse/core": "^14.1.0",
"@vueuse/integrations": "^14.2.1",
"@xterm/addon-fit": "^0.11.0",
Expand All @@ -35,6 +36,7 @@
"animate.css": "^4.1.1",
"cron-parser": "^5.5.0",
"cronstrue": "^3.14.0",
"dagre": "^0.8.5",
"dotenv": "^17.2.3",
"echarts": "^6.0.0",
"katex": "^0.16.28",
Expand Down Expand Up @@ -63,6 +65,7 @@
},
"devDependencies": {
"@memohai/config": "workspace:*",
"@types/dagre": "^0.7.54",
"@types/moment": "^2.13.0",
"@types/node": "^24.10.1",
"@types/qrcode": "^1.5.6",
Expand Down
107 changes: 107 additions & 0 deletions apps/web/src/components/orchestration-sidebar/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<template>
<aside class="relative h-full">
<header
v-if="topInset"
class="fixed left-0 top-0 z-20 h-9 w-(--sidebar-width) bg-sidebar border-r border-sidebar-border [-webkit-app-region:drag]"
/>

<Sidebar
:collapsible="topInset ? 'none' : 'icon'"
:class="topInset ? 'pt-9 h-dvh border-r border-sidebar-border' : ''"
>
<SidebarHeader class="p-0 border-0">
<button
class="flex h-[53px] w-full items-center gap-2.5 border-b border-border px-3.5 text-foreground transition-colors hover:bg-accent/50 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-0"
@click="router.push(backToChatRoute)"
>
<ChevronLeft class="size-3 shrink-0" />
<span class="text-xs font-semibold group-data-[collapsible=icon]:hidden">
{{ t('sidebar.orchestration') }}
</span>
</button>
</SidebarHeader>

<SidebarContent>
<SidebarGroup class="px-2 py-2.5">
<SidebarGroupContent>
<SidebarMenu class="gap-0.5">
<SidebarMenuItem
v-for="item in navItems"
:key="item.name"
>
<SidebarMenuButton
:tooltip="item.title"
:is-active="isItemActive(item.name)"
:aria-current="isItemActive(item.name) ? 'page' : undefined"
class="relative h-9 gap-2 before:absolute before:bottom-1.5 before:left-0 before:top-1.5 before:w-0.5 before:rounded-full data-[active=true]:before:bg-foreground/70 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-0"
@click="router.push({ name: item.name })"
>
<component
:is="item.icon"
class="ml-1.5 size-3.5 group-data-[collapsible=icon]:ml-0"
/>
<span class="text-xs font-medium group-data-[collapsible=icon]:hidden">{{ item.title }}</span>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>

<SidebarRail v-if="!topInset" />
</Sidebar>
</aside>
</template>

<script setup lang="ts">
import { computed, inject, type Component } from 'vue'
import { storeToRefs } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { ChevronLeft, Container, Server, Workflow } from 'lucide-vue-next'
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from '@memohai/ui'
import { useChatSelectionStore } from '@/store/chat-selection'
import { DesktopShellKey } from '@/lib/desktop-shell'

const router = useRouter()
const route = useRoute()
const { t } = useI18n()
const topInset = inject(DesktopShellKey, false)
const selectionStore = useChatSelectionStore()
const { currentBotId } = storeToRefs(selectionStore)

const backToChatRoute = computed(() => {
const botId = (currentBotId.value ?? '').trim()
if (!botId) return { name: 'home' as const }
return {
name: 'chat' as const,
params: { botId },
}
})

const navItems: { title: string, name: string, icon: Component }[] = [
{ title: t('orchestration.runs'), name: 'orchestration', icon: Workflow },
{ title: t('orchestration.envResources'), name: 'orchestration-env-resources', icon: Server },
{ title: t('orchestration.images'), name: 'orchestration-images', icon: Container },
]

function isItemActive(name: string) {
if (name === 'orchestration-env-resources') {
return String(route.name ?? '').startsWith('orchestration-env-resources')
}
if (name === 'orchestration-images') {
return String(route.name ?? '').startsWith('orchestration-images')
}
return route.name === name
}
</script>
14 changes: 13 additions & 1 deletion apps/web/src/components/sidebar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@
<SidebarFooter class="relative border-0 px-2 pb-3.5 pt-2.5">
<div class="pointer-events-none absolute -top-30 left-0 h-38.25 w-full bg-linear-to-t from-(--sidebar-background) from-18% to-transparent z-10 group-data-[collapsible=icon]:hidden" />
<SidebarMenu class="gap-2.5">
<SidebarMenuItem>
<SidebarMenuButton
:tooltip="t('sidebar.orchestration')"
class="h-9 px-2.5 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-0"
:is-active="isOrchestrationActive"
@click="router.push('/orchestration')"
>
<Workflow class="size-3.5" />
<span class="text-xs font-medium group-data-[collapsible=icon]:hidden">{{ t('sidebar.orchestration') }}</span>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
:tooltip="t('sidebar.settings')"
Expand Down Expand Up @@ -126,7 +137,7 @@ import {
SidebarRail,
useSidebar,
} from '@memohai/ui'
import { Plus, LoaderCircle, Settings, PanelLeftClose, PanelLeftOpen } from 'lucide-vue-next'
import { Plus, LoaderCircle, Settings, PanelLeftClose, PanelLeftOpen, Workflow } from 'lucide-vue-next'
import BotItem from './bot-item.vue'
import { usePinnedBots } from '@/composables/usePinnedBots'
import { DesktopShellKey } from '@/lib/desktop-shell'
Expand All @@ -147,4 +158,5 @@ const { data: botData, isLoading } = useQuery(getBotsQuery())
const bots = computed<BotsBot[]>(() => sortBots(botData.value?.items ?? []))

const isSettingsActive = computed(() => route.path.startsWith('/settings'))
const isOrchestrationActive = computed(() => route.path.startsWith('/orchestration'))
</script>
Loading
Loading