feat: chat uploads, vision turn isolation, and MindSpace agent improvements

Add chat file/image upload UX, attachment proxying, vision thumbnails, and per-turn image scoping so agents only use the current upload. Extend MindSpace asset context, billing token state, OA/scenario verify scripts, and related runtime config.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-11 00:23:01 +08:00
parent e3063ea806
commit 32fb2cdeaf
51 changed files with 4588 additions and 186 deletions
+52 -3
View File
@@ -1,3 +1,31 @@
function resolveWorkspaceRelativePath(asset) {
const raw = asset?.workspaceRelativePath ?? asset?.workspace_relative_path ?? '';
const trimmed = String(raw).trim().replace(/^\.?\//, '');
if (!trimmed || trimmed.includes('..')) return null;
return trimmed;
}
function isSpreadsheetAsset(asset) {
const mime = String(asset?.mimeType ?? '').toLowerCase();
const name = String(asset?.displayName ?? asset?.filename ?? '').toLowerCase();
return (
mime.includes('spreadsheet')
|| mime.includes('csv')
|| name.endsWith('.xlsx')
|| name.endsWith('.xls')
|| name.endsWith('.csv')
);
}
function buildSpreadsheetAnalysisInstructions() {
return [
'【数据表汇总校验(硬性)】',
'- 分析数值汇总时,**必须**用 Python/pandas 等对源表列做 SUM,禁止手算或估算。',
'- 写入聊天回复或 HTML 报告前,自检:各分组明细之和必须与总计一致;不一致则重新计算后再输出。',
'',
];
}
export function buildSelectedAssetReadInstructions(context) {
const selected = context.selectedAssets ?? [];
if (selected.length !== 1) return [];
@@ -11,12 +39,27 @@ export function buildSelectedAssetReadInstructions(context) {
const sessionHint = sessionId
? ''
: '- session_id 未写入上下文时,使用当前 Agent 会话 ID 替换 `<CURRENT_AGENT_SESSION>`。\n';
const workspacePath = resolveWorkspaceRelativePath(asset);
return [
const lines = [
'【勾选资料读取(硬性)】',
`- 用户已勾选「${asset.displayName}」(id: ${asset.id}`,
'- **禁止** curl / fetch 浏览器登录接口 `GET /api/mindspace/v1/assets/:id/download`goosed 无 cookie,会 401',
'- **优先**用 `list_dir oa` / `read_file` / `cat oa/文件名` 读取工作区已落盘副本',
];
if (workspacePath) {
lines.push(
`- **已落盘路径(硬性)**\`${workspacePath}\` — 直接 \`read_file ${workspacePath}\` 或脚本读取该路径`,
'- **禁止** list_dir / 工作目录探测 / 重复调用 mindspace_asset_download(文件已在工作区)',
'- 仅当读取该路径失败时,才允许调用下方 Agent 代理下载',
);
} else {
lines.push(
'- **优先**用 `list_dir oa` / `read_file` / `cat oa/文件名` 读取工作区已落盘副本',
);
}
lines.push(
sessionHint,
'- 若工作区尚无该文件,**必须**用 shell 调用 Agent 代理下载并落盘到 `oa/`',
'```bash',
@@ -27,7 +70,13 @@ export function buildSelectedAssetReadInstructions(context) {
'- 成功后响应 JSON 含 `relativePath`(如 `oa/report.xlsx`),后续分析/引用只用该相对路径',
'- **禁止**访问其它用户目录、MindSpace 根目录或 `./MindSpace/<username>/` 等猜测路径',
'',
].filter(Boolean);
);
if (isSpreadsheetAsset(asset)) {
lines.push(...buildSpreadsheetAnalysisInstructions());
}
return lines.filter(Boolean);
}
export function buildSelectedAssetDeleteInstructions(context) {