feat: complete main agent message config tracing
This commit is contained in:
@@ -4,6 +4,12 @@
|
||||
|
||||
## 2026-04-04
|
||||
|
||||
### 主 Agent 消息卡补齐配置追溯与主动作执行上下文
|
||||
|
||||
- OneLiner 助手消息卡里的 `主配置历史 / 平台配置历史` 现在终于拿到真实 `version_id`,不再出现“入口在,但打开后只能停在列表顶部”的半截体验。
|
||||
- 助手消息卡里的主动作也改成了和次级动作一致的执行标签:会把 `session_id / platform / executor_key / payload` 一起带上,后续再从消息卡直接执行时,不会丢掉真实上下文。
|
||||
- 后端回归新增了消息卡 `execution_card` 配置追溯断言,前端回归也锁住了主动作统一走 `actionTag + buildOnelinerActionAttrs`,避免后续又退回到只剩一个裸 `data-action`。
|
||||
|
||||
### 主 Agent 结果卡支持直达配置版本
|
||||
|
||||
- 主 Agent 当前运行卡、执行结果卡、平台 Agent 最近执行卡,现在不只显示 `配置 vN / 平台 Agent vN`,而且可以直接点进去打开对应的历史弹层。
|
||||
|
||||
@@ -4052,6 +4052,8 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
context = _session_context_summary(account, project_id or "", plan.get("platform") or "")
|
||||
oneliner_profile = context.get("oneliner_profile") or {}
|
||||
platform_agent = context.get("platform_agent") or {}
|
||||
platform_agent_assistant = platform_agent.get("assistant") or {}
|
||||
context_assistant = context.get("assistant") or {}
|
||||
governance = context.get("governance") or {}
|
||||
effective_policy = (governance.get("effective") or {}).get("effective_policy") or {}
|
||||
governance_layers = (governance.get("effective") or {}).get("layers") or []
|
||||
@@ -4085,8 +4087,8 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
next_steps = []
|
||||
if primary_action:
|
||||
next_steps.append(f"优先执行「{primary_action.get('label', primary_action.get('key', '下一步'))}」。")
|
||||
if platform_agent.get("assistant", {}).get("name"):
|
||||
next_steps.append(f"默认调度 {platform_agent['assistant']['name']} 作为执行 Agent。")
|
||||
if platform_agent_assistant.get("name"):
|
||||
next_steps.append(f"默认调度 {platform_agent_assistant.get('name')} 作为执行 Agent。")
|
||||
if evidence:
|
||||
next_steps.append("我会优先参考该平台 Agent 最近沉淀的方法与技能。")
|
||||
if governance_layers:
|
||||
@@ -4106,7 +4108,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
if plan.get("intent_key") == "ops_admin" and account.get("role") != "super_admin":
|
||||
summary_lines.append("当前账号不是平台最高权限用户,所以我不会放出运维 Agent 入口。")
|
||||
if context.get("platform_agent"):
|
||||
summary_lines.append(f"当前 {context['platform_agent']['platform_label']} Agent 已绑定:{context['platform_agent'].get('assistant', {}).get('name') or '未绑定执行 Agent'}。")
|
||||
summary_lines.append(f"当前 {context['platform_agent']['platform_label']} Agent 已绑定:{platform_agent_assistant.get('name') or '未绑定执行 Agent'}。")
|
||||
if platform_agent.get("recent_memory"):
|
||||
summary_lines.append(f"最近有效经验:{platform_agent['recent_memory'].get('title') or '一条平台记忆'}。")
|
||||
if platform_agent.get("recent_skill"):
|
||||
@@ -4204,7 +4206,7 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
},
|
||||
}
|
||||
)
|
||||
if context.get("assistant"):
|
||||
if context_assistant:
|
||||
secondary_actions.append(
|
||||
{
|
||||
"key": "run-oneliner-action",
|
||||
@@ -4261,6 +4263,11 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
"platform": "",
|
||||
}
|
||||
)
|
||||
decorated_primary_action = _decorate_oneliner_action(
|
||||
account,
|
||||
project_id=project_id or "",
|
||||
action=primary_action or {},
|
||||
) if primary_action else {}
|
||||
secondary_actions = [
|
||||
_decorate_oneliner_action(account, project_id=project_id or "", action=item)
|
||||
for item in secondary_actions
|
||||
@@ -4275,17 +4282,28 @@ def register_oneliner_routes(app: Any, legacy: Any) -> None:
|
||||
"platform": plan.get("platform", ""),
|
||||
"platform_label": plan.get("platform_label", "待判断"),
|
||||
"platform_agent_name": platform_agent.get("name") or "",
|
||||
"assistant_name": platform_agent.get("assistant", {}).get("name") or context.get("assistant", {}).get("name") or "",
|
||||
"assistant_name": platform_agent_assistant.get("name") or context_assistant.get("name") or "",
|
||||
"readiness_label": platform_agent.get("readiness_label") or "",
|
||||
"readiness_score": platform_agent.get("readiness_score") or 0,
|
||||
"primary_action": primary_action or {},
|
||||
"primary_action": decorated_primary_action,
|
||||
"blocked_reason": blocked_reason,
|
||||
"active_admin_override_notice": active_admin_override_notice,
|
||||
"oneliner_profile_version": {
|
||||
"version_id": oneliner_profile_version.get("id", ""),
|
||||
"version_no": oneliner_profile_version.get("version_no", 0),
|
||||
"title": oneliner_profile_version.get("title", ""),
|
||||
"summary": oneliner_profile_version.get("summary", ""),
|
||||
},
|
||||
"platform_agent_profile": {
|
||||
"platform": platform_agent.get("platform") or plan.get("platform", ""),
|
||||
"platform_label": platform_agent.get("platform_label") or plan.get("platform_label", ""),
|
||||
"name": platform_agent.get("name", ""),
|
||||
"assistant_name": platform_agent_assistant.get("name") or context_assistant.get("name") or "",
|
||||
"version_id": ((platform_agent.get("current_version") or {}).get("id") or ""),
|
||||
"version_no": ((platform_agent.get("current_version") or {}).get("version_no") or 0),
|
||||
"readiness_label": platform_agent.get("readiness_label") or "",
|
||||
"readiness_score": platform_agent.get("readiness_score") or 0,
|
||||
},
|
||||
"evidence": evidence,
|
||||
"next_steps": next_steps,
|
||||
"secondary_actions": secondary_actions,
|
||||
|
||||
@@ -1401,3 +1401,67 @@ class MainAgentGovernanceTests(unittest.TestCase):
|
||||
action_keys = [item["action_key"] for item in audits_payload["items"]]
|
||||
self.assertIn("update-oneliner-profile", action_keys)
|
||||
self.assertIn("rollback-oneliner-profile", action_keys)
|
||||
|
||||
def test_oneliner_message_execution_card_tracks_config_versions(self) -> None:
|
||||
profile_response = self.client.put(
|
||||
"/v2/oneliner/profile",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={
|
||||
"project_id": self.ctx["project_id"],
|
||||
"display_name": "增长总控 OneLiner",
|
||||
"assistant_id": "",
|
||||
"default_platform": "douyin",
|
||||
"long_term_goal": "优先分析当前平台账号并收口到下一步动作",
|
||||
"notes": "验证消息卡里的配置追溯链",
|
||||
"config": {"analysis_mode": "fast"},
|
||||
"reason": "给消息卡提供明确的主配置版本",
|
||||
},
|
||||
)
|
||||
self.assertEqual(profile_response.status_code, 200, profile_response.text)
|
||||
current_profile_version = profile_response.json()["current_version"]
|
||||
|
||||
platform_response = self.client.put(
|
||||
"/v2/platform-agents/douyin/profile",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={
|
||||
"project_id": self.ctx["project_id"],
|
||||
"name": "抖音增长 Agent",
|
||||
"mission": "优先分析当前账号和高分作品",
|
||||
"notes": "验证消息卡里的平台配置追溯链",
|
||||
"status": "active",
|
||||
"config": {"focus": "analysis"},
|
||||
},
|
||||
)
|
||||
self.assertEqual(platform_response.status_code, 200, platform_response.text)
|
||||
current_platform_version = platform_response.json()["current_version"]
|
||||
|
||||
session_response = self.client.post(
|
||||
"/v2/oneliner/sessions",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={
|
||||
"project_id": self.ctx["project_id"],
|
||||
"preferred_platform": "douyin",
|
||||
"title": "消息卡配置追溯",
|
||||
},
|
||||
)
|
||||
self.assertEqual(session_response.status_code, 200, session_response.text)
|
||||
session_payload = session_response.json()
|
||||
|
||||
message_response = self.client.post(
|
||||
f"/v2/oneliner/sessions/{session_payload['id']}/messages",
|
||||
headers=self.ctx["member_headers"],
|
||||
json={
|
||||
"project_id": self.ctx["project_id"],
|
||||
"platform": "douyin",
|
||||
"content": "帮我创建 Agent",
|
||||
},
|
||||
)
|
||||
self.assertEqual(message_response.status_code, 200, message_response.text)
|
||||
payload = message_response.json()
|
||||
execution_card = (((payload.get("assistant_message") or {}).get("result")) or {}).get("execution_card") or {}
|
||||
self.assertEqual((execution_card.get("primary_action") or {}).get("key"), "open-create-assistant")
|
||||
self.assertEqual((execution_card.get("oneliner_profile_version") or {}).get("version_id"), current_profile_version["id"])
|
||||
self.assertEqual((execution_card.get("oneliner_profile_version") or {}).get("version_no"), current_profile_version["version_no"])
|
||||
self.assertEqual((execution_card.get("platform_agent_profile") or {}).get("platform"), "douyin")
|
||||
self.assertEqual((execution_card.get("platform_agent_profile") or {}).get("version_id"), current_platform_version["id"])
|
||||
self.assertEqual((execution_card.get("platform_agent_profile") or {}).get("version_no"), current_platform_version["version_no"])
|
||||
|
||||
@@ -1346,8 +1346,28 @@ function renderOneLinerMessagesHtml() {
|
||||
const executionCard = result.execution_card || {};
|
||||
const activeAdminOverrideNotice = executionCard.active_admin_override_notice || null;
|
||||
const profileVersion = executionCard.oneliner_profile_version || {};
|
||||
const platformAgentProfile = executionCard.platform_agent_profile || {};
|
||||
const actions = safeArray(plan.suggested_actions);
|
||||
const primaryAction = executionCard.primary_action || {};
|
||||
const secondaryActions = safeArray(executionCard.secondary_actions);
|
||||
const buildOnelinerActionAttrs = (item) => {
|
||||
const attrs = [
|
||||
item.executor_key ? `data-executor-key="${escapeHtml(item.executor_key)}"` : "",
|
||||
item.platform ? `data-platform="${escapeHtml(item.platform)}"` : "",
|
||||
message.session_id ? `data-session-id="${escapeHtml(message.session_id)}"` : "",
|
||||
];
|
||||
Object.entries(item.payload || {}).forEach(([payloadKey, payloadValue]) => {
|
||||
const attrKey = String(payloadKey || "")
|
||||
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
||||
.replace(/_/g, "-")
|
||||
.toLowerCase();
|
||||
const serialized = typeof payloadValue === "string"
|
||||
? payloadValue
|
||||
: JSON.stringify(payloadValue);
|
||||
attrs.push(`data-${escapeHtml(attrKey)}="${escapeHtml(serialized)}"`);
|
||||
});
|
||||
return attrs.filter(Boolean).join(" ");
|
||||
};
|
||||
return `
|
||||
<div class="oneliner-message ${roleClass}">
|
||||
<div class="oneliner-bubble">
|
||||
@@ -1375,9 +1395,14 @@ function renderOneLinerMessagesHtml() {
|
||||
${executionCard.assistant_name ? `<span class="tag green">${escapeHtml(executionCard.assistant_name)}</span>` : ""}
|
||||
${profileVersion.version_no ? `<span class="tag">配置 v${escapeHtml(formatNumber(profileVersion.version_no || 0))}</span>` : ""}
|
||||
${profileVersion.version_no ? `<span class="tag clickable-tag" data-action="open-oneliner-profile-history" data-version-id="${escapeHtml(profileVersion.version_id || "")}">看主配置历史</span>` : ""}
|
||||
${executionCard.platform && executionCard.platform_agent_profile?.version_no ? `<span class="tag clickable-tag" data-action="open-platform-agent-profile-history" data-platform="${escapeHtml(executionCard.platform)}" data-version-id="${escapeHtml(executionCard.platform_agent_profile?.version_id || "")}">看平台配置历史</span>` : ""}
|
||||
${executionCard.platform && platformAgentProfile.version_no ? `<span class="tag clickable-tag" data-action="open-platform-agent-profile-history" data-platform="${escapeHtml(executionCard.platform)}" data-version-id="${escapeHtml(platformAgentProfile.version_id || "")}">看平台配置历史</span>` : ""}
|
||||
${executionCard.readiness_label ? `<span class="tag ${executionCard.readiness_score >= 75 ? "green" : executionCard.readiness_score >= 50 ? "blue" : "orange"}">${escapeHtml(executionCard.readiness_label)} ${escapeHtml(formatNumber(executionCard.readiness_score || 0))}</span>` : ""}
|
||||
${executionCard.primary_action?.key ? `<span class="tag clickable-tag" data-action="${escapeHtml(executionCard.primary_action.key)}">${escapeHtml(executionCard.primary_action.label || "执行下一步")}</span>` : ""}
|
||||
${primaryAction.key ? actionTag(
|
||||
primaryAction.label || "执行下一步",
|
||||
primaryAction.key || "",
|
||||
buildOnelinerActionAttrs(primaryAction),
|
||||
{ disabledReason: primaryAction.disabled_reason || "" }
|
||||
) : ""}
|
||||
</div>
|
||||
${profileVersion.version_no ? `
|
||||
<div class="panel-subtitle" style="margin-top:8px;">${escapeHtml(profileVersion.summary || profileVersion.title || `当前按 OneLiner 配置 v${formatNumber(profileVersion.version_no || 0)} 执行。`)}</div>
|
||||
@@ -1412,22 +1437,7 @@ function renderOneLinerMessagesHtml() {
|
||||
${secondaryActions.map((item) => actionTag(
|
||||
item.label || item.key || "执行",
|
||||
item.key || "",
|
||||
[
|
||||
item.executor_key ? `data-executor-key="${escapeHtml(item.executor_key)}"` : "",
|
||||
item.platform ? `data-platform="${escapeHtml(item.platform)}"` : "",
|
||||
message.session_id ? `data-session-id="${escapeHtml(message.session_id)}"` : "",
|
||||
...Object.entries(item.payload || {}).map(([payloadKey, payloadValue]) => {
|
||||
const attrKey = String(payloadKey || "")
|
||||
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
||||
.replace(/_/g, "-")
|
||||
.toLowerCase();
|
||||
const serialized = typeof payloadValue === "string"
|
||||
? payloadValue
|
||||
: JSON.stringify(payloadValue);
|
||||
return `data-${escapeHtml(attrKey)}="${escapeHtml(serialized)}"`;
|
||||
})
|
||||
].filter(Boolean).join(" ")
|
||||
,
|
||||
buildOnelinerActionAttrs(item),
|
||||
{ disabledReason: item.disabled_reason || "" }
|
||||
)).join("")}
|
||||
</div>
|
||||
|
||||
@@ -961,9 +961,13 @@ test("main agent execution cards can jump to oneliner and platform profile histo
|
||||
const messages = extractBetween(APP, "function renderOneLinerMessagesHtml()", "function renderAutoConnectingScreen(screenTitle, nextStepText)");
|
||||
const runtime = extractBetween(APP, "function renderOneLinerRunsHtml()", "function renderOneLinerMessagesHtml()");
|
||||
const execution = extractBetween(APP, "function renderOneLinerExecutionPayloadHtml(payload)", "function parseOneLinerActionPayloadValue(value)");
|
||||
assert.match(messages, /const buildOnelinerActionAttrs = \(item\) =>/);
|
||||
assert.match(messages, /data-action="open-oneliner-profile-history"/);
|
||||
assert.match(messages, /data-action="open-platform-agent-profile-history"/);
|
||||
assert.match(messages, /data-version-id="\$\{escapeHtml\(profileVersion\.version_id \|\| ""\)\}"/);
|
||||
assert.match(messages, /data-version-id="\$\{escapeHtml\(platformAgentProfile\.version_id \|\| ""\)\}"/);
|
||||
assert.match(messages, /actionTag\(\s*primaryAction\.label \|\| "执行下一步"/);
|
||||
assert.match(messages, /buildOnelinerActionAttrs\(primaryAction\)/);
|
||||
assert.match(runtime, /data-version-id="\$\{escapeHtml\(currentRunConfigVersion\.version_id \|\| ""\)\}"/);
|
||||
assert.match(execution, /data-version-id="\$\{escapeHtml\(configVersion\.version_id \|\| ""\)\}"/);
|
||||
assert.match(execution, /data-version-id="\$\{escapeHtml\(platformAgentProfile\.version_id \|\| ""\)\}"/);
|
||||
|
||||
Reference in New Issue
Block a user