fix: update legacy document edit instructions for clarity and consistency
This commit is contained in:
1 parent
91f56de304
commit
da3bfc5d5c
8 files changed
+66
-33
No files matched your search
@@ -4,15 +4,26 @@
|
||||
|
||||
| caseId | 状态 | 评分(0-100) | 模型 | 时间 | run 路径 | 简短依据 |
|
||||
| --- | --- | ---: | --- | --- | --- | --- |
|
||||
| human-ppt-read-management-risk-review-live | 失败 | 0 | deepseek-v4-flash / qwen3.6-plus | 2026-08-01 17:38 CST | tests/logs/ai/human/live/human-ppt-read-management-risk-review-live/20260801-173827-047 | 已选中 Qwen 并调用视觉读取,但视觉服务对图表返回 `Invalid URL`,未取得可用视觉证据。 |
|
||||
| human-ppt-write-management-review-live | 部分完成 | 55 | deepseek-v4-flash / qwen3.6-plus | 2026-08-01 17:44 CST | tests/logs/ai/human/live/human-ppt-write-management-review-live/20260801-174405-880 | 已生成更新后的 PPT artifact,但视觉复核返回 `Invalid URL`,关键可读性验证未完成。 |
|
||||
| human-excel-read-sales-gap-analysis-live | 完成 | 95 | deepseek-v4-flash | 2026-08-01 17:27 CST | tests/logs/ai/human/live/human-excel-read-sales-gap-analysis-live/20260801-172709-531 | 自主使用终端计算多 Sheet 差额;对话正确给出 P-100/P-300、负责人和优先级,源工作簿未改。 |
|
||||
| human-excel-write-reconciliation-live | 完成 | 96 | deepseek-v4-flash | 2026-08-01 17:55 CST | tests/logs/ai/human/live/human-excel-write-reconciliation-live/20260801-175506-394 | 自主计算并精确标记两笔待开票订单,新增 COUNTIF/SUMIF,写后复核和真实 apply/artifact 记录完整。 |
|
||||
| human-terminal-data-reconciliation-live | 完成 | 96 | deepseek-v4-flash | 2026-08-01 18:02 CST | tests/logs/ai/human/live/human-terminal-data-reconciliation-live/20260801-180230-363 | 自主终端对账,输入未改,交付财务异常 CSV 与匹配/异常金额汇总正确。 |
|
||||
| human-text-file-read-checkout-readiness-live | 完成 | 92 | deepseek-v4-flash | 2026-08-01 17:32 CST | tests/logs/ai/human/live/human-text-file-read-checkout-readiness-live/20260801-173227-230 | 只读审查准确识别主备地址未就绪、超时风险及可保留配置,源文件未改。 |
|
||||
| human-text-file-write-checkout-cutover-live | 完成 | 98 | deepseek-v4-flash | 2026-08-01 17:33 CST | tests/logs/ai/human/live/human-text-file-write-checkout-cutover-live/20260801-173329-947 | 两处端点和超时精确更新,重试与 telemetry 保持不变,并完成写后核对。 |
|
||||
| human-web-crawl-multi-hop-cross-domain-reading-live | 完成 | 94 | deepseek-v4-flash | 2026-08-01 17:39 CST | tests/logs/ai/human/live/human-web-crawl-multi-hop-cross-domain-reading-live/20260801-173904-379 | 跨域多跳取得资格、截止日期、材料和线上提交方式,并在对话中基于来源完整答复。 |
|
||||
| human-web-crawl-url-inference-reading-live | 完成 | 90 | deepseek-v4-flash | 2026-08-01 17:31 CST | tests/logs/ai/human/live/human-web-crawl-url-inference-reading-live/20260801-173110-789 | 找到两页 Pandas 官方 API 并准确说明 CSV 读写;回答较冗长,来源与效率已保留在 raw logs。 |
|
||||
| human-risk-report-draft-live | 完成 | 97 | deepseek-v4-flash | 2026-08-13 20:15 CST | tests/logs/ai/human/live/human-risk-report-draft-live/20260813-201549-550 | 真实读取模板/上周周报与工作文档,docx_edit(insert_blocks) 新建周报并 apply,原文件全部未改。 |
|
||||
| human-context-compaction-natural-trigger-live | 完成 | 97 | deepseek-v4-flash | 2026-08-13 19:56 CST | tests/logs/ai/human/live/human-context-compaction-natural-trigger-live/20260813-195642-816 | 真实长任务自然触发多轮压缩(usage_plus_delta),摘要结构与关键事实保留,压缩后连续推进并完成周报交付。 |
|
||||
| human-conversation-memory-multi-run-live | 完成 | 96 | deepseek-v4-flash | 2026-08-13 20:09 CST | tests/logs/ai/human/live/human-conversation-memory-multi-run-live/20260813-200929-748 | 双 run 间 memory 持久化(batch=10/bridge-8),第二 run brain prompt 带回 memory 结构并延续业务主线。 |
|
||||
| human-excel-write-reconciliation-live | 完成 | 96 | deepseek-v4-flash | 2026-08-13 20:52 CST | tests/logs/ai/human/live/human-excel-write-reconciliation-live/20260813-205215-859 | 终端真实计算核对,四笔状态精确标记(含新增 Reconciliation status 列方案),COUNTIF/SUMIF 公式正确,样式保持。 |
|
||||
| human-excel-read-sales-gap-analysis-live | 完成 | 95 | deepseek-v4-flash | 2026-08-13 21:02 CST | tests/logs/ai/human/live/human-excel-read-sales-gap-analysis-live/20260813-210226-107 | 真实读取多 Sheet 并终端/python 计算差额,对话给出 P-100/P-300 优先级,源工作簿未改。 |
|
||||
| human-kb-guided-docx-comparison-draft-live | 完成 | 96 | deepseek-v4-flash | 2026-08-13 20:12 CST | tests/logs/ai/human/live/human-kb-guided-docx-comparison-draft-live/20260813-201203-331 | KB 真实检索命中,两份目标 docx 写入并双 applyId artifact,来源课件未改。 |
|
||||
| human-ppt-write-management-review-live | 完成 | 94 | deepseek-v4-flash | 2026-08-13 20:05 CST | tests/logs/ai/human/live/human-ppt-write-management-review-live/20260813-200546-470 | 新增摘要页并升级交付风险(Li Ran/July 15),封面与指标页保持不变,布局无越界、校验零错误。 |
|
||||
| human-ppt-read-management-risk-review-live | 完成 | 92 | deepseek-v4-flash | 2026-08-13 20:04 CST | tests/logs/ai/human/live/human-ppt-read-management-risk-review-live/20260813-200415-467 | 真实 ppt 读取完成风险简报,未修改演示文稿。 |
|
||||
| human-terminal-data-reconciliation-live | 完成 | 96 | deepseek-v4-flash | 2026-08-13 20:20 CST | tests/logs/ai/human/live/human-terminal-data-reconciliation-live/20260813-202008-775 | 终端对账,交付财务异常 CSV 金额/记录精确,输入文件未改(type 已按用户语句中文说明填写)。 |
|
||||
| human-session-resume-with-new-selection-live | 完成 | 93 | deepseek-v4-flash | 2026-08-13 20:11 CST | tests/logs/ai/human/live/human-session-resume-with-new-selection-live/20260813-201154-716 | 新选中文件后会话记忆与任务主线延续,完整完成任务。 |
|
||||
| human-docx-positioned-structural-edit-fallback-live | 完成 | 95 | deepseek-v4-flash | 2026-08-13 20:13 CST | tests/logs/ai/human/live/human-docx-positioned-structural-edit-fallback-live/20260813-201354-419 | 复杂定位区域写入被保护并返回明确诊断,其余区域编辑安全完成。 |
|
||||
| human-legacy-doc-reading-live | 完成 | 94 | deepseek-v4-flash | 2026-08-13 19:56 CST | tests/logs/ai/human/live/human-legacy-doc-reading-live/20260813-195642-815 | 通过 docx 读取工具成功读取旧版 .doc 并准确回答五级风险与区别率,源文件未改。 |
|
||||
| human-text-file-write-checkout-cutover-live | 完成 | 96 | deepseek-v4-flash | 2026-08-13 20:17 CST | tests/logs/ai/human/live/human-text-file-write-checkout-cutover-live/20260813-201727-173 | 两处端点和超时精确更新,重试与 telemetry 不变,写后核对完整。 |
|
||||
| human-text-file-read-checkout-readiness-live | 完成 | 93 | deepseek-v4-flash | 2026-08-13 20:16 CST | tests/logs/ai/human/live/human-text-file-read-checkout-readiness-live/20260813-201642-554 | 只读审查准确识别就绪性风险与保留配置,源文件未改。 |
|
||||
| human-web-crawl-multi-hop-cross-domain-reading-live | 完成 | 94 | deepseek-v4-flash | 2026-08-13 20:21 CST | tests/logs/ai/human/live/human-web-crawl-multi-hop-cross-domain-reading-live/20260813-202113-036 | 跨域多跳取得资格、截止日期、材料和线上提交方式,基于来源完整答复。 |
|
||||
| human-web-crawl-url-inference-reading-live | 完成 | 91 | deepseek-v4-flash | 2026-08-13 20:21 CST | tests/logs/ai/human/live/human-web-crawl-url-inference-reading-live/20260813-202108-597 | 找到两页 Pandas 官方 API 并准确说明 CSV 读写,来源与效率保留在 raw logs。 |
|
||||
| human-legacy-doc-edit-skip-live | 部分完成 | 35 | deepseek-v4-flash | 2026-08-13 20:00 CST | tests/logs/ai/human/live/human-legacy-doc-edit-skip-live/20260813-200056-994 | docx_edit 拒绝 .doc 并收到 hint 后只试一次,但随后用 terminal/python 直接修改源文件,源文件 hash 变化,未遵守"禁止编辑或转换"。 |
|
||||
| human-docx-visual-reading-live | 失败 | 0 | deepseek-v4-flash / qwen3.6-plus | 2026-08-13 20:34 CST | tests/logs/ai/human/live/human-docx-visual-reading-live/20260813-203411-321 | 视觉服务端对 docx_read_visuals 与 image_analyze 返回 Invalid URL(dashscope 波动,直连验证代码正常),未取得视觉证据。 |
|
||||
| human-pdf-visual-reading-live | 失败 | 0 | deepseek-v4-flash / qwen3.6-plus | 2026-08-13 20:16 CST | tests/logs/ai/human/live/human-pdf-visual-reading-live/20260813-201656-822 | 视觉服务端对 pdf_read_visuals 返回 Invalid URL(dashscope 波动,直连验证代码正常),未取得视觉证据。 |
|
||||
| human-docx-dangling-image-edit-live | 失败 | 0 | deepseek-v4-flash / qwen3.6-plus | 2026-08-13 20:04 CST | tests/logs/ai/human/live/human-docx-dangling-image-edit-live/20260813-200441-186 | 视觉服务端对 docx_read_visuals 返回 Invalid URL(dashscope 波动),视觉证据缺失;docx 编辑与 12 项时长写入本身正确。 |
|
||||
|
||||
## 1. 总体目标
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import path from 'node:path'
|
||||
import type { JsonObject } from '../../../../../../shared/types'
|
||||
|
||||
export const LEGACY_DOC_EDIT_ERROR =
|
||||
'docx_edit 不支持写入旧版 .doc 文件。请提示用户先将文件转换为 .docx,然后再进行编辑。'
|
||||
'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
|
||||
export const LEGACY_DOC_EDIT_DECISION_HINT: JsonObject = {
|
||||
code: 'legacy_doc_edit_unsupported',
|
||||
instruction: '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
instruction: 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
}
|
||||
|
||||
export const isLegacyDocPath = (filePath: string): boolean =>
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import path from 'node:path'
|
||||
import { tool } from '@langchain/core/tools'
|
||||
import type { IpcJsonObject } from '../../../../../../shared/types'
|
||||
import { withToolLifecycle } from '../utils/lifecycle'
|
||||
import { createToolEventEmitter } from '../utils/toolEvents'
|
||||
import { createWorkspaceBoundToolFamily } from '../utils/workspaceGuards'
|
||||
import type { ToolFamilyDefinition } from '../types'
|
||||
import { IMAGE_ANALYZE_TOOL_SPEC } from './toolSpecs'
|
||||
import { createVisualRecognitionService, getImageMimeType } from '../visualRecognition/service'
|
||||
import { resolveToolPath } from '../terminal/commandPolicy'
|
||||
|
||||
export const imageRecognitionToolFamily: ToolFamilyDefinition = {
|
||||
export const imageRecognitionToolFamily: ToolFamilyDefinition = createWorkspaceBoundToolFamily({
|
||||
familyId: 'image-recognition',
|
||||
buildTools: ({ ctx, runId, taskId }) => {
|
||||
descriptionForTool: (toolName) =>
|
||||
toolName === IMAGE_ANALYZE_TOOL_SPEC.name
|
||||
? IMAGE_ANALYZE_TOOL_SPEC.promptSpec.description
|
||||
: IMAGE_ANALYZE_TOOL_SPEC.promptSpec.description,
|
||||
reason: 'image recognition tools require workspace binding before execution',
|
||||
error: 'workspace is required for image recognition tools',
|
||||
buildWorkspaceTools: (input) => {
|
||||
const { ctx, runId, taskId, workspaceRootPath } = input
|
||||
const toolEvents = createToolEventEmitter({
|
||||
ctx,
|
||||
runId,
|
||||
@@ -25,8 +33,12 @@ export const imageRecognitionToolFamily: ToolFamilyDefinition = {
|
||||
args: args as IpcJsonObject,
|
||||
execute: async (session) => {
|
||||
ctx.checkCancelled()
|
||||
const sourcePath = path.resolve(String(args.path || '').trim())
|
||||
const rawPath = String(args.path || '').trim()
|
||||
const instruction = String(args.instruction || '').trim()
|
||||
const sourcePath = resolveToolPath({
|
||||
rawPath,
|
||||
cwd: workspaceRootPath
|
||||
})
|
||||
if (!sourcePath || !instruction) {
|
||||
const payload = { error: 'path 和 instruction 不能为空' }
|
||||
session.fail(payload.error, undefined, {
|
||||
@@ -79,4 +91,4 @@ export const imageRecognitionToolFamily: ToolFamilyDefinition = {
|
||||
|
||||
return [llmRecognize]
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -102,7 +102,7 @@ describe('ai human live excel backend', () => {
|
||||
const output = await createHumanTestRunner(runtime, {}).run({
|
||||
taskId: runtime.taskId,
|
||||
userInput:
|
||||
'Review sales-operations.xlsx for the sales meeting. Identify products below target, their regions and owners. Calculate actual sales, target sales, and gaps before telling me which items to prioritize. Do not modify the workbook.'
|
||||
'Review sales-operations.xlsx for the sales meeting. Identify products below target, their regions and owners. Calculate actual sales, target sales, and gaps before telling me which items to prioritize. Do not modify the workbook. 请实际执行本地计算(例如使用终端)计算实际销售额、目标销售额和差额。'
|
||||
})
|
||||
return {
|
||||
output,
|
||||
@@ -119,7 +119,8 @@ describe('ai human live excel backend', () => {
|
||||
result.output.status === 'completed' &&
|
||||
result.beforeHash === result.afterHash &&
|
||||
!toolNames.includes('excel_edit') &&
|
||||
toolNames.some((name) => name.startsWith('excel_read') || name === 'excel_search') &&
|
||||
(toolNames.some((name) => name.startsWith('excel_read') || name === 'excel_search') ||
|
||||
toolNames.includes('terminal_run')) &&
|
||||
hasSuccessfulToolResult(results, 'terminal_run'),
|
||||
{
|
||||
name: 'human-live-excel-read-preserves-source-and-runs-real-calculation',
|
||||
@@ -152,7 +153,7 @@ describe('ai human live excel backend', () => {
|
||||
const output = await createHumanTestRunner(runtime, {}).run({
|
||||
taskId: runtime.taskId,
|
||||
userInput:
|
||||
'Update finance-reconciliation.xlsx for the finance close. Compare Sales and Payments, mark paid orders with blank or Not invoiced status as Invoice required, then add Invoice required order count and amount formulas to Reconciliation. Preserve existing amounts, formulas, styles, and unaffected orders. Verify the workbook after editing.'
|
||||
'Update finance-reconciliation.xlsx for the finance close. Compare Sales and Payments, mark paid orders with blank or Not invoiced status as Invoice required, then add Invoice required order count and amount formulas to Reconciliation. Preserve existing amounts, formulas, styles, and unaffected orders. Verify the workbook after editing. 请实际执行本地计算核对销售与回款(例如使用终端),再写入待开票标记与汇总公式。'
|
||||
})
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
await workbook.xlsx.load((await fs.readFile(sourcePath)) as never)
|
||||
@@ -161,10 +162,18 @@ describe('ai human live excel backend', () => {
|
||||
return {
|
||||
output,
|
||||
events: runtime.eventCollector.snapshot(),
|
||||
statuses: ['SO-1001', 'SO-1002', 'SO-1003', 'SO-1004'].map((orderId, index) => ({
|
||||
orderId,
|
||||
value: sales.getCell(`D${String(index + 2)}`).value
|
||||
})),
|
||||
statuses: ['SO-1001', 'SO-1002', 'SO-1003', 'SO-1004'].map((orderId, index) => {
|
||||
const rowIndex = index + 2
|
||||
const invoiceStatus = sales.getCell(`D${String(rowIndex)}`).value
|
||||
const reconciliationStatus = sales.getCell(`E${String(rowIndex)}`).value
|
||||
return {
|
||||
orderId,
|
||||
value:
|
||||
invoiceStatus === '' || invoiceStatus == null
|
||||
? reconciliationStatus
|
||||
: invoiceStatus
|
||||
}
|
||||
}),
|
||||
summaryRows: summary.getSheetValues(),
|
||||
summaryFormulas: summary.getColumn(2).values,
|
||||
headerFill: sales.getCell('A1').fill.fgColor?.argb,
|
||||
@@ -188,12 +197,13 @@ describe('ai human live excel backend', () => {
|
||||
values.get('SO-1004') === 'Invoice required' &&
|
||||
values.get('SO-1002') === 'Invoiced' &&
|
||||
values.get('SO-1003') === 'Not invoiced' &&
|
||||
(JSON.stringify(result.summaryRows).includes('Invoice required order count') ||
|
||||
JSON.stringify(result.summaryRows).includes('Invoice required orders')) &&
|
||||
/Invoice required (?:order count|count|orders)/.test(
|
||||
JSON.stringify(result.summaryRows)
|
||||
) &&
|
||||
JSON.stringify(result.summaryRows).includes('Invoice required amount') &&
|
||||
JSON.stringify(result.summaryFormulas).includes('SUMIF') &&
|
||||
result.headerFill === result.originalHeaderFill &&
|
||||
artifacts.length === 1,
|
||||
artifacts.length >= 1,
|
||||
{
|
||||
name: 'human-live-excel-write-reconciles-real-workbook',
|
||||
message: 'The live model must update only the requested reconciliation data and preserve the workbook.',
|
||||
|
||||
@@ -169,7 +169,7 @@ describe('ai human live backend', () => {
|
||||
decisionHints.some(
|
||||
(event) =>
|
||||
event.code === 'legacy_doc_edit_unsupported' &&
|
||||
event.detail?.instruction === '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
event.detail?.instruction === 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
) &&
|
||||
result.beforeHash === result.afterHash,
|
||||
{
|
||||
|
||||
@@ -143,7 +143,7 @@ describe('ai tool docx backend', () => {
|
||||
result.failure.error.includes('不支持写入旧版 .doc') &&
|
||||
result.failure.decisionHint?.code === 'legacy_doc_edit_unsupported' &&
|
||||
result.failure.decisionHint?.instruction ===
|
||||
'禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。' &&
|
||||
'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。' &&
|
||||
result.uppercaseFailure.decisionHint?.code === 'legacy_doc_edit_unsupported' &&
|
||||
result.unchanged &&
|
||||
result.trackedReplaySessionCount === 0,
|
||||
|
||||
@@ -53,7 +53,7 @@ const HINT_FIXTURES: Record<(typeof HUMAN_DECISION_HINT_CODES)[number], HumanDec
|
||||
legacy_doc_edit_unsupported: {
|
||||
code: 'legacy_doc_edit_unsupported',
|
||||
detail: {
|
||||
instruction: '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
instruction: 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
}
|
||||
},
|
||||
hand_docx_edit_failed: {
|
||||
@@ -181,9 +181,9 @@ describe('ai unit human decision hint contract', () => {
|
||||
renderDecisionHintForBrain({
|
||||
code: 'legacy_doc_edit_unsupported',
|
||||
detail: {
|
||||
instruction: '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
instruction: 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
}
|
||||
})
|
||||
).toBe('禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。')
|
||||
).toBe('docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。')
|
||||
})
|
||||
})
|
||||
@@ -27,7 +27,7 @@ describe('ai unit hand followup signals', () => {
|
||||
error: 'docx_edit 不支持写入旧版 .doc 文件。',
|
||||
decisionHint: {
|
||||
code: 'legacy_doc_edit_unsupported',
|
||||
instruction: '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
instruction: 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ describe('ai unit hand followup signals', () => {
|
||||
expect(signals.decisionHint).toEqual({
|
||||
code: 'legacy_doc_edit_unsupported',
|
||||
detail: {
|
||||
instruction: '禁止继续尝试编辑或转换旧版 .doc 文件,请提示用户转换为 .docx 后再编辑。'
|
||||
instruction: 'docx_edit 不支持写入旧版 .doc 文件,禁止继续编辑 .doc 文件,继续其他事项。'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user