diff --git a/apps/desktop/src/app/chat/sidebar/index.tsx b/apps/desktop/src/app/chat/sidebar/index.tsx
index f1587dcc3dc80..2e83cd75f199f 100644
--- a/apps/desktop/src/app/chat/sidebar/index.tsx
+++ b/apps/desktop/src/app/chat/sidebar/index.tsx
@@ -127,6 +127,7 @@ import { $sidebarSessionRankIds } from '@/store/sidebar-sort'
import {
type AppView,
ARTIFACTS_ROUTE,
+ CRON_ROUTE,
MESSAGING_ROUTE,
SIDEBAR_NAV_AREA,
type SidebarNavContribution,
@@ -203,6 +204,13 @@ const SIDEBAR_NAV: SidebarNavItem[] = [
icon: props => ,
route: ARTIFACTS_ROUTE,
keybindActionId: 'nav.artifacts'
+ },
+ {
+ id: 'cron',
+ label: '',
+ icon: props => ,
+ route: CRON_ROUTE,
+ keybindActionId: 'nav.cron'
}
]
@@ -1405,6 +1413,7 @@ export function ChatSidebar({
(item.id === 'skills' && currentView === 'skills') ||
(item.id === 'messaging' && currentView === 'messaging') ||
(item.id === 'artifacts' && currentView === 'artifacts') ||
+ (item.id === 'cron' && currentView === 'cron') ||
// Contributed rows light up at their own route.
(Boolean(item.route) && pathname === item.route)
diff --git a/apps/desktop/src/app/cron/index.tsx b/apps/desktop/src/app/cron/index.tsx
index 9f89b0d923fb0..ca18aaa2db444 100644
--- a/apps/desktop/src/app/cron/index.tsx
+++ b/apps/desktop/src/app/cron/index.tsx
@@ -356,6 +356,23 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt
[jobs, query]
)
+ // Blueprint recipes render in the same list rail, below the jobs — clicking
+ // one opens the create dialog pre-seeded to that recipe. Same query key as
+ // the dialog's "Start from" dropdown, so the catalog is fetched once.
+ const blueprintsQuery = useQuery({
+ queryKey: ['cron-blueprints'],
+ queryFn: async () => (await getAutomationBlueprints()).blueprints
+ })
+
+ const visibleBlueprints = useMemo(() => {
+ const list = blueprintsQuery.data ?? []
+ const needle = query.trim().toLowerCase()
+
+ return needle
+ ? list.filter(item => `${item.title} ${item.description}`.toLowerCase().includes(needle))
+ : list
+ }, [blueprintsQuery.data, query])
+
// Detail always reflects a concrete job: the explicitly selected one, else the
// first visible row, so the right pane is never empty while jobs exist.
const selectedJob = useMemo(
@@ -480,7 +497,7 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt
{loading && jobs.length === 0 ? (
- ) : totalCount === 0 ? (
+ ) : totalCount === 0 && visibleBlueprints.length === 0 ? (
setEditor({ mode: 'create' })} size="sm">
@@ -521,6 +538,21 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt
{c.emptyTitleSearch}
)}
setEditor({ mode: 'create' })} />
+ {visibleBlueprints.length > 0 && (
+ <>
+ {c.blueprints.tab}
+ {visibleBlueprints.map(item => (
+ setEditor({ blueprintKey: item.key, mode: 'create' })}
+ rowKey={`blueprint-${item.key}`}
+ title={item.title}
+ />
+ ))}
+ >
+ )}
{selectedJob ? (
@@ -919,10 +951,10 @@ function CronEditorDialog({
setDeliver(initial ? jobDeliver(initial) : DEFAULT_DELIVER)
setModelChoice(initial && jobModel(initial) ? `${jobProvider(initial)}:${jobModel(initial)}` : MODEL_DEFAULT_VALUE)
setSlotValues({})
- setTemplateChoice(CUSTOM_TEMPLATE)
+ setTemplateChoice(editor.mode === 'create' ? (editor.blueprintKey ?? CUSTOM_TEMPLATE) : CUSTOM_TEMPLATE)
setError(null)
setSaving(false)
- }, [initial, open])
+ }, [editor, initial, open])
// Seed the typed slots with the blueprint's defaults whenever a blueprint is
// picked from "Start from" (and reset them when switching back to Custom).
@@ -1232,7 +1264,12 @@ function CronEditorDialog({
)
}
-type EditorState = { job: CronJob; mode: 'edit' } | { mode: 'closed' } | { mode: 'create' }
+type EditorState =
+ | { job: CronJob; mode: 'edit' }
+ | { mode: 'closed' }
+ // `blueprintKey` pre-selects a blueprint in the create dialog's "Start from"
+ // dropdown (set when a recipe row in the list rail is clicked).
+ | { blueprintKey?: string; mode: 'create' }
interface EditorValues {
deliver: string
diff --git a/apps/desktop/src/app/types.ts b/apps/desktop/src/app/types.ts
index 743c2b95be019..fe9398d7bbf02 100644
--- a/apps/desktop/src/app/types.ts
+++ b/apps/desktop/src/app/types.ts
@@ -158,7 +158,7 @@ export type CommandDispatchResponse =
| SendCommandDispatchResponse
| PrefillCommandDispatchResponse
-export type SidebarNavId = 'artifacts' | 'command-center' | 'messaging' | 'new-session' | 'settings' | 'skills'
+export type SidebarNavId = 'artifacts' | 'command-center' | 'cron' | 'messaging' | 'new-session' | 'settings' | 'skills'
export interface SidebarNavItem {
/** Built-in view id, or a contributed row's namespaced contribution id. */
diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts
index 3160533d69d1a..35916ae65cc6c 100644
--- a/apps/desktop/src/i18n/en.ts
+++ b/apps/desktop/src/i18n/en.ts
@@ -1865,7 +1865,8 @@ export const en: Translations = {
'new-session': 'New session',
skills: 'Capabilities',
messaging: 'Messaging',
- artifacts: 'Artifacts'
+ artifacts: 'Artifacts',
+ cron: 'Scheduled jobs'
},
searchAria: 'Search sessions',
searchPlaceholder: 'Search sessions…',
diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts
index 6ff8e056ac5e5..a4e49cc8f6948 100644
--- a/apps/desktop/src/i18n/ja.ts
+++ b/apps/desktop/src/i18n/ja.ts
@@ -1689,7 +1689,8 @@ export const ja = defineLocale({
'new-session': '新しいセッション',
skills: 'スキルとツール',
messaging: 'メッセージング',
- artifacts: 'アーティファクト'
+ artifacts: 'アーティファクト',
+ cron: 'スケジュール済みジョブ'
},
searchAria: 'セッションを検索',
searchPlaceholder: 'セッションを検索…',
diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts
index 9e1bfad1cc0c5..1020be810d1dd 100644
--- a/apps/desktop/src/i18n/zh-hant.ts
+++ b/apps/desktop/src/i18n/zh-hant.ts
@@ -1634,7 +1634,8 @@ export const zhHant = defineLocale({
'new-session': '新工作階段',
skills: '技能與工具',
messaging: '訊息平台',
- artifacts: '成品'
+ artifacts: '成品',
+ cron: '排程工作'
},
searchAria: '搜尋工作階段',
searchPlaceholder: '搜尋工作階段…',
diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts
index b6063d1cb45fb..471fa8767a324 100644
--- a/apps/desktop/src/i18n/zh.ts
+++ b/apps/desktop/src/i18n/zh.ts
@@ -2056,7 +2056,8 @@ export const zh: Translations = {
'new-session': '新建会话',
skills: '技能与工具',
messaging: '消息平台',
- artifacts: '产物'
+ artifacts: '产物',
+ cron: '定时任务'
},
searchAria: '搜索会话',
searchPlaceholder: '搜索会话…',