32fb2cdeaf
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>
112 lines
4.6 KiB
JavaScript
112 lines
4.6 KiB
JavaScript
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 [];
|
||
|
||
const asset = selected[0];
|
||
const h5ApiBase = String(context.h5ApiBase ?? '').replace(/\/$/, '');
|
||
const sessionId = String(context.agentSessionId ?? '').trim();
|
||
if (!h5ApiBase) return [];
|
||
|
||
const sessionToken = sessionId || '<CURRENT_AGENT_SESSION>';
|
||
const sessionHint = sessionId
|
||
? ''
|
||
: '- session_id 未写入上下文时,使用当前 Agent 会话 ID 替换 `<CURRENT_AGENT_SESSION>`。\n';
|
||
const workspacePath = resolveWorkspaceRelativePath(asset);
|
||
|
||
const lines = [
|
||
'【勾选资料读取(硬性)】',
|
||
`- 用户已勾选「${asset.displayName}」(id: ${asset.id})`,
|
||
'- **禁止** curl / fetch 浏览器登录接口 `GET /api/mindspace/v1/assets/:id/download`(goosed 无 cookie,会 401)',
|
||
];
|
||
|
||
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',
|
||
`curl -sS -X POST '${h5ApiBase}/api/agent/mindspace_asset_download' \\`,
|
||
" -H 'Content-Type: application/json' \\",
|
||
` -d '{"session_id":"${sessionToken}","asset_id":"${asset.id}"}'`,
|
||
'```',
|
||
'- 成功后响应 JSON 含 `relativePath`(如 `oa/report.xlsx`),后续分析/引用只用该相对路径',
|
||
'- **禁止**访问其它用户目录、MindSpace 根目录或 `./MindSpace/<username>/` 等猜测路径',
|
||
'',
|
||
);
|
||
|
||
if (isSpreadsheetAsset(asset)) {
|
||
lines.push(...buildSpreadsheetAnalysisInstructions());
|
||
}
|
||
|
||
return lines.filter(Boolean);
|
||
}
|
||
|
||
export function buildSelectedAssetDeleteInstructions(context) {
|
||
const selected = context.selectedAssets ?? [];
|
||
if (selected.length !== 1) return [];
|
||
|
||
const asset = selected[0];
|
||
const h5ApiBase = String(context.h5ApiBase ?? '').replace(/\/$/, '');
|
||
const sessionId = String(context.agentSessionId ?? '').trim();
|
||
if (!h5ApiBase) return [];
|
||
|
||
const sessionToken = sessionId || '<CURRENT_AGENT_SESSION>';
|
||
const sessionHint = sessionId
|
||
? ''
|
||
: '- session_id 未写入上下文时,使用当前 Agent 会话 ID 替换 `<CURRENT_AGENT_SESSION>`。\n';
|
||
|
||
return [
|
||
'【勾选资料删除(硬性)】',
|
||
`- 你对用户 MindSpace 拥有完整读写删改权限;用户已勾选「${asset.displayName}」(id: ${asset.id})。`,
|
||
'- 用户要求删除这份资料时:先说明将删除哪一份并等待用户明确确认(如「确定」「删吧」「确认删除」);**禁止**未确认就删。',
|
||
sessionHint,
|
||
'- 用户确认后,**必须立即**用 shell 执行(不要只口头说已删,也不要让用户自己去界面点删除):',
|
||
'```bash',
|
||
`curl -sS -X POST '${h5ApiBase}/api/agent/mindspace_asset_delete' \\`,
|
||
" -H 'Content-Type: application/json' \\",
|
||
` -d '{"session_id":"${sessionToken}","asset_id":"${asset.id}","confirmed":true}'`,
|
||
'```',
|
||
'- curl 成功后再回复「已删除」;若返回 asset_in_use,说明被页面引用,告知用户先删关联页面。',
|
||
'- 禁止删除未勾选的其它文件。',
|
||
'',
|
||
].filter(Boolean);
|
||
}
|