Skip to content

Commit d10d7f6

Browse files
committed
Merge remote-tracking branch 'origin/main' into codex/manpage-agent-directory-20260917
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
2 parents f02b3fa + 090be98 commit d10d7f6

40 files changed

Lines changed: 859 additions & 190 deletions

‎apps/presentation/dashboard/src/features/personal-workspace/i18n.tsx‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ const en = {
6666
"common.waiting": "Waiting",
6767
"composer.addImage": "Add image",
6868
"composer.agentProgress": "Ask Agent for a progress report",
69+
"composer.blockers": "Ask what blocks",
6970
"composer.agentProgressPrompt": "Give me a progress report for this Goal: completed, running, blocked, and next steps.",
7071
"composer.attachImageHint": "Choose, paste, or drag an image",
7172
"composer.clarifyDefer": "Deferring a Todo requires a deterministic resume condition. Add todo_done:<todo_id>, pr_merged:[owner/repo]#<number>, capacity_available:<capability>, or resume_at:<timezone-aware RFC3339 timestamp>.",
@@ -76,7 +77,7 @@ const en = {
7677
"composer.createGoalDraftLead": "Create a long-term Goal:",
7778
"composer.createGoalTemplate": "Create a long-term Goal:\nObjective:\nCompletion criteria:\nExecution boundary (optional):\nRelated repository (optional):\nNotification method (optional):",
7879
"composer.createGoalHint": "Insert a Goal template to review before creation",
79-
"composer.draft": "Draft",
80+
"composer.evidence": "Check what is proven",
8081
"composer.globalProgress": "Summarize all Goal progress",
8182
"composer.globalProgressPrompt": "Summarize the latest progress and blockers for all active Goals.",
8283
"composer.globalTasks": "Ask about global priorities",
@@ -92,20 +93,18 @@ const en = {
9293
"composer.imageSizeError": "Each image must be {size} MB or smaller.",
9394
"composer.imageTypeError": "PNG, JPEG, WebP, and GIF images are supported.",
9495
"composer.imagesPending": "Images to send",
95-
"composer.immediate": "Send now",
9696
"composer.managerMessageHint": "Your message goes to the LoopX Manager across Goals for global questions or Goal creation.",
9797
"composer.managerPlaceholder": "Ask the LoopX Manager, or describe a new Goal…",
9898
"composer.monitor": "Configure scheduled check",
9999
"composer.monitorGoalQuestion": "Which Goal should receive the scheduled check?",
100100
"composer.monitorTemplate": "Add a scheduled check for the current Goal:\nCheck target:\nFrequency (supports 30 minutes / 2 hours / daily): Every 2 hours\nStop condition: Goal completes",
101+
"composer.monitorShortcutTemplate": "Add a scheduled check for the current Goal:\nCheck target: {target}\nFrequency: Every 2 hours\nStop condition: Goal completes",
101102
"composer.monitorTemplateWithoutGoal": "Configure a scheduled check:\nGoal:\nCheck target:\nFrequency: Every 2 hours\nStop condition: Goal completes",
102-
"composer.monitorHint": "Fill in what to check, frequency, and stop condition before creation",
103103
"composer.heartbeatGoalQuestion": "Which Goal should receive the Heartbeat?",
104104
"composer.heartbeatTemplate": "Set a Heartbeat for the current Goal:\nFrequency: Daily\nStop condition: Goal completes\nNotification: Only notify me when needed",
105105
"composer.heartbeatTemplateWithoutGoal": "Set up a Heartbeat:\nGoal:\nFrequency: Daily\nStop condition: Goal completes\nNotification: Only notify me when needed",
106106
"composer.nextAction": "Ask what’s next",
107107
"composer.nextActionPrompt": "What should I do next?",
108-
"composer.prepareDraft": "Insert a draft and review before sending",
109108
"composer.send": "Send",
110109
"composer.sendMessage": "Send a message to LoopX",
111110
"composer.sendMessageHint": "Send message",
@@ -1105,16 +1104,17 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
11051104
"composer.addImage": "添加图片",
11061105
"composer.agentProgress": "向 Agent 获取进度报告",
11071106
"composer.agentProgressPrompt": "请给我一份当前 Goal 的进度报告:已完成、执行中、阻塞和下一步。",
1107+
"composer.blockers": "看阻塞",
11081108
"composer.attachImageHint": "选择、粘贴或拖入图片",
11091109
"composer.clarifyDefer": "暂缓 Todo 需要可自动判断的恢复条件。请补充 todo_done:<todo_id>、pr_merged:[owner/repo]#<number>、capacity_available:<capability> 或 resume_at:<带时区 RFC3339 时间>。",
11101110
"composer.clarifySingleAction": "这句话包含多个可能修改状态的操作。请一次描述一项操作,我会逐项展示确认预览。",
1111+
"composer.evidence": "查证据",
11111112
"composer.createGoal": "创建新 Goal",
11121113
"composer.createGoalDraft": "Goal 草稿",
11131114
"composer.createGoalDraftDescription": "补充内容后发送,LoopX 会先展示待确认操作。",
11141115
"composer.createGoalDraftLead": "我想创建一个长期 Goal:",
11151116
"composer.createGoalTemplate": "我想创建一个长期 Goal:\n目标:\n完成标准:\n执行边界(可选):\n关联仓库(可选):\n通知方式(可选):",
11161117
"composer.createGoalHint": "填入 Goal 模板草稿,检查后再创建",
1117-
"composer.draft": "草稿",
11181118
"composer.globalProgress": "汇总所有 Goal 进展",
11191119
"composer.globalProgressPrompt": "请帮我汇总所有活跃 Goal 的最新进展与阻塞。",
11201120
"composer.globalTasks": "询问全局待办",
@@ -1130,20 +1130,18 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
11301130
"composer.imageSizeError": "单张图片不能超过 {size}MB。",
11311131
"composer.imageTypeError": "支持 PNG、JPEG、WebP 和 GIF 图片。",
11321132
"composer.imagesPending": "待发送图片",
1133-
"composer.immediate": "立即发送",
11341133
"composer.managerMessageHint": "你的消息由 LoopX 管家跨 Goal 接收,支持全局询问与创建 Goal",
11351134
"composer.managerPlaceholder": "问问 LoopX 管家,或描述一个新 Goal…",
11361135
"composer.monitor": "配置定时检查",
11371136
"composer.monitorGoalQuestion": "为哪个 Goal 添加定时检查?",
11381137
"composer.monitorTemplate": "为当前 Goal 添加定时检查:\n检查内容:\n频率(支持 30 分钟 / 2 小时 / 每天):每 2 小时\n停止条件:Goal 完成",
1138+
"composer.monitorShortcutTemplate": "为当前 Goal 添加定时检查:\n检查内容:{target}\n频率:每 2 小时\n停止条件:Goal 完成",
11391139
"composer.monitorTemplateWithoutGoal": "配置定时检查:\nGoal:\n检查内容:\n频率:每 2 小时\n停止条件:Goal 完成",
1140-
"composer.monitorHint": "先填写检查内容、频率和停止条件,不会立即创建",
11411140
"composer.heartbeatGoalQuestion": "为哪个 Goal 设置 Heartbeat?",
11421141
"composer.heartbeatTemplate": "为当前 Goal 设置 Heartbeat:\n频率:每天\n停止条件:Goal 完成\n通知:仅在需要我时",
11431142
"composer.heartbeatTemplateWithoutGoal": "设置 Heartbeat:\nGoal:\n频率:每天\n停止条件:Goal 完成\n通知:仅在需要我时",
11441143
"composer.nextAction": "询问下一步",
11451144
"composer.nextActionPrompt": "我现在该做什么?",
1146-
"composer.prepareDraft": "填入编辑框,确认后再发送",
11471145
"composer.send": "发送",
11481146
"composer.sendMessage": "向 LoopX 发送消息",
11491147
"composer.sendMessageHint": "发送消息",

‎apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-contract.test.mjs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ assert.match(timeline, /personal-message-images/, "Sent images remain visible in
165165
assert.match(dashboard, /attachments: route\?\.attachments/, "Image attachments enter the selected Agent Session");
166166
assert.match(page, /sendMessage\(t\("composer\.agentProgressPrompt"\)\)/, "Progress report shortcut sends a scoped read-only request immediately");
167167
assert.match(page, /t\("composer\.agentProgress"\)/, "Progress report shortcut makes its immediate-send behavior explicit");
168-
assert.match(page, /t\("composer\.nextAction"\)[\s\S]*t\("composer\.prepareDraft"\)/, "Advice shortcut explains that it only prepares a draft");
169-
assert.match(page, /t\("composer\.monitor"\)[\s\S]*t\("composer\.monitorHint"\)/, "Monitor shortcut explains its editable-draft boundary");
168+
assert.match(page, /t\("composer\.nextAction"\)[\s\S]*sendMessage\(t\("composer\.nextActionPrompt"\)\)/, "Advice shortcut sends its scoped question immediately");
169+
assert.match(page, /t\("composer\.monitor"\)[\s\S]*sendMessage\(t\("composer\.monitorShortcutTemplate", \{ target: t\("schedule\.defaultTarget"\) \}\)\)/, "Monitor shortcut sends its bounded template with a named check target immediately");
170170
assert.match(page, /goalDraftActive[\s\S]*t\("composer\.createGoalDraft"\)[\s\S]*t\("composer\.createGoal"/, "Create Goal mode is visibly distinct from a normal chat draft");
171171
assert.match(page, /setComposerDraft\(`manager:\$\{selectedAgentId\}`,\s*t\("composer\.createGoalTemplate"\)\)/, "Create Goal writes the localized template to the manager draft even when invoked from a Goal");
172172
assert.match(page, /personal-action-feedback/, "Typed actions surface a persistent visible receipt");

‎apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
listTypedActions,
1919
previewTypedAction,
2020
setupGoalChannel,
21+
stewardPrompts,
2122
transitionTypedAction,
2223
type GoalRepositoryContext,
2324
type LarkGoalConnection,
@@ -853,10 +854,10 @@ export function PersonalWorkspacePage({
853854
function setComposer(value: string) {
854855
setComposerDraft(composerDraftKey, value);
855856
}
856-
function fillQuickPrompt(text: string) {
857-
const existing = drafts[composerDraftKey]?.trimEnd();
858-
setComposer(existing ? `${existing}\n${text}` : text);
859-
window.requestAnimationFrame(() => composerRef.current?.focus());
857+
// The steward prompt set is owned by the client model; the quick-prompt row
858+
// reuses it so one affordance answers "what now / what blocks / what is proven".
859+
function stewardPromptText(id: string) {
860+
return stewardPrompts.find((item) => item.id === id)?.prompt ?? "";
860861
}
861862
useEffect(() => {
862863
const el = composerRef.current;
@@ -2003,15 +2004,17 @@ export function PersonalWorkspacePage({
20032004
</p>
20042005
{selectedGoal ? (
20052006
<div className="personal-quick-prompts">
2006-
<button aria-label={t("composer.nextAction")} className="is-draft" onClick={() => fillQuickPrompt(t("composer.nextActionPrompt"))} title={t("composer.prepareDraft")} type="button"><MessageCircleQuestion size={13} /><span>{t("composer.nextAction")}</span><small className="personal-prompt-subtle">{t("composer.draft")}</small></button>
2007-
<button className="is-immediate" disabled={sending} onClick={() => void sendMessage(t("composer.agentProgressPrompt"))} title={t("composer.immediate")} type="button"><Send size={13} /><span>{t("composer.agentProgress")}</span><em className="personal-prompt-badge">{t("composer.immediate")}</em></button>
2008-
<button aria-label={t("composer.monitor")} className="is-draft" onClick={() => prepareScheduleDraft("monitor", selectedGoalId)} title={t("composer.monitorHint")} type="button"><CalendarClock size={13} /><span>{t("composer.monitor")}</span><small className="personal-prompt-subtle">{t("composer.draft")}</small></button>
2007+
<button aria-label={t("composer.nextAction")} disabled={sending} onClick={() => void sendMessage(t("composer.nextActionPrompt"))} title={t("composer.sendMessageHint")} type="button"><MessageCircleQuestion size={13} /><span>{t("composer.nextAction")}</span></button>
2008+
<button aria-label={t("composer.agentProgress")} disabled={sending} onClick={() => void sendMessage(t("composer.agentProgressPrompt"))} title={t("composer.sendMessageHint")} type="button"><Send size={13} /><span>{t("composer.agentProgress")}</span></button>
2009+
<button aria-label={t("composer.monitor")} disabled={sending} onClick={() => void sendMessage(t("composer.monitorShortcutTemplate", { target: t("schedule.defaultTarget") }))} title={t("composer.sendMessageHint")} type="button"><CalendarClock size={13} /><span>{t("composer.monitor")}</span></button>
2010+
<button aria-label={t("composer.blockers")} disabled={sending || !stewardPromptText("gate")} onClick={() => void sendMessage(stewardPromptText("gate"))} title={t("composer.sendMessageHint")} type="button"><AlertCircle size={13} /><span>{t("composer.blockers")}</span></button>
2011+
<button aria-label={t("composer.evidence")} disabled={sending || !stewardPromptText("evidence")} onClick={() => void sendMessage(stewardPromptText("evidence"))} title={t("composer.sendMessageHint")} type="button"><FileText size={13} /><span>{t("composer.evidence")}</span></button>
20092012
</div>
20102013
) : (
20112014
<div className="personal-quick-prompts">
2012-
<button aria-label={t("composer.globalTasks")} className="is-draft" onClick={() => fillQuickPrompt(t("composer.globalTasksPrompt"))} title={t("composer.prepareDraft")} type="button"><MessageCircleQuestion size={13} /><span>{t("composer.globalTasks")}</span><small className="personal-prompt-subtle">{t("composer.draft")}</small></button>
2013-
<button className="is-immediate" disabled={sending} onClick={() => void sendMessage(t("composer.globalProgressPrompt"))} title={t("composer.immediate")} type="button"><Send size={13} /><span>{t("composer.globalProgress")}</span><em className="personal-prompt-badge">{t("composer.immediate")}</em></button>
2014-
<button aria-label={t("composer.createGoal")} className="is-draft" onClick={requestGoalCreate} title={t("composer.createGoalHint")} type="button"><Plus size={13} /><span>{t("composer.createGoal")}</span><small className="personal-prompt-subtle">{t("composer.draft")}</small></button>
2015+
<button aria-label={t("composer.globalTasks")} disabled={sending} onClick={() => void sendMessage(t("composer.globalTasksPrompt"))} title={t("composer.sendMessageHint")} type="button"><MessageCircleQuestion size={13} /><span>{t("composer.globalTasks")}</span></button>
2016+
<button aria-label={t("composer.globalProgress")} disabled={sending} onClick={() => void sendMessage(t("composer.globalProgressPrompt"))} title={t("composer.sendMessageHint")} type="button"><Send size={13} /><span>{t("composer.globalProgress")}</span></button>
2017+
<button aria-label={t("composer.createGoal")} onClick={requestGoalCreate} title={t("composer.createGoalHint")} type="button"><Plus size={13} /><span>{t("composer.createGoal")}</span></button>
20152018
</div>
20162019
)}
20172020
{goalDraftActive ? <div className="personal-goal-draft-status" role="status"><strong>{t("composer.createGoalDraft")}</strong><span>{t("composer.createGoalDraftDescription")}</span></div> : null}

‎apps/presentation/dashboard/src/features/personal-workspace/personal-workspace.css‎

Lines changed: 3 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)