fix: align pi rust p1 official features

This commit is contained in:
Agent Board
2026-07-11 21:07:32 +08:00
parent d16eccfe10
commit 1418f1b1e0
7 changed files with 382 additions and 41 deletions
@@ -28,6 +28,7 @@
START: '/api/page-ai/pi/start',
SEND: '/api/page-ai/pi/send',
ABORT: '/api/page-ai/pi/abort',
RPC_COMMAND: '/api/page-ai/pi/rpc-command',
UI_RESPONSE: '/api/page-ai/pi/ui-response',
EVENTS: '/api/page-ai/pi/events',
BOOTSTRAP: '/api/page-ai/pi/bootstrap',
@@ -97,6 +98,7 @@
modelOptions: [],
history: [],
pendingQueue: { steering: [], followUp: [] },
pendingImages: [],
viewingHistorySessionId: null,
contextSelection: {
currentPage: false,
@@ -1647,6 +1649,10 @@
window.location.assign('/user/ai#ai-admin-access');
return;
}
if (action === 'attach-file' || action === 'camera') {
pickPiPromptImages(action === 'camera');
return;
}
if (action === 'send-steer') {
sendCurrentInput({ streamingBehavior: 'steer' });
return;
@@ -1655,6 +1661,14 @@
sendCurrentInput({ streamingBehavior: 'followUp' });
return;
}
if (action === 'abort-bash') {
callPiRpcCommand('abort_bash', {}, 5000).then(function () {
showPiToast('已请求中止 bash', 'info');
}).catch(function (error) {
showPiToast(error && error.message ? error.message : 'bash 中止失败', 'warning');
});
return;
}
if (action === 'plan-mode') {
var input = piLabPanelEl && piLabPanelEl.querySelector('[data-page-ai-pi-lab-input]');
var current = input ? input.value.trim() : '';
@@ -1943,12 +1957,13 @@
'<div class="wolai-page-ai-pi-lab-menu-sep"></div>' +
'<div class="wolai-page-ai-pi-lab-menu-section">权限与附件</div>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="directory-permission">' + piIcon('folder') + '<span>目录权限</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="attach-file" disabled title="Pi RPC 附件上下文尚未接入">' + piIcon('image') + '<span>添加图片和文件</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="camera" disabled title="Pi RPC 附件上下文尚未接入">' + piIcon('camera') + '<span>拍照</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="attach-file">' + piIcon('image') + '<span>添加图片和文件</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="camera">' + piIcon('camera') + '<span>拍照</span></button>' +
'<div class="wolai-page-ai-pi-lab-menu-sep"></div>' +
'<div class="wolai-page-ai-pi-lab-menu-section">执行中发送</div>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="send-steer">' + piIcon('zap') + '<span>作为引导发送</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="send-followup">' + piIcon('queue') + '<span>作为排队追问发送</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="abort-bash">' + piIcon('stop') + '<span>中止 bash</span></button>' +
'<button type="button" class="wolai-page-ai-pi-lab-menu-item" data-page-ai-pi-lab-menu-action="plan-mode" title="通过 Pi Rust 官方 plan-mode 扩展进入计划评审">' + piIcon('settings') + '<span>计划评审</span></button>' +
'</div>' +
'<div class="wolai-page-ai-pi-lab-modebar" data-page-ai-pi-lab-modebar>' +
@@ -3386,6 +3401,71 @@
}).catch(function () {});
}
function callPiRpcCommand(type, params, timeoutMs) {
if (!piLabState.sessionId) return Promise.reject(new Error('Pi 会话尚未就绪'));
return fetch(API.RPC_COMMAND, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: piLabState.sessionId,
type: type,
params: params || {},
timeoutMs: timeoutMs || 10000,
}),
}).then(function (r) {
return responseJsonOrError(r, 'Pi RPC command failed');
});
}
function readFileAsPiImage(file) {
return new Promise(function (resolve, reject) {
if (!file || !/^image\//i.test(file.type || '')) {
reject(new Error('只支持图片附件;普通文件请在输入中使用 @文件路径'));
return;
}
var reader = new FileReader();
reader.onload = function () {
var dataUrl = String(reader.result || '');
var comma = dataUrl.indexOf(',');
if (comma < 0) {
reject(new Error('图片读取失败'));
return;
}
resolve({
type: 'image',
source: {
type: 'base64',
mediaType: file.type || 'image/png',
data: dataUrl.slice(comma + 1),
},
});
};
reader.onerror = function () { reject(new Error('图片读取失败')); };
reader.readAsDataURL(file);
});
}
function pickPiPromptImages(useCamera) {
var input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.multiple = !useCamera;
if (useCamera) input.setAttribute('capture', 'environment');
input.addEventListener('change', function () {
var files = Array.prototype.slice.call(input.files || []);
if (!files.length) return;
Promise.all(files.map(readFileAsPiImage)).then(function (images) {
piLabState.pendingImages = (piLabState.pendingImages || []).concat(images);
showPiToast('已添加 ' + images.length + ' 张图片', 'success');
updateButtons();
}).catch(function (error) {
showPiToast(error && error.message ? error.message : '附件读取失败', 'warning');
});
});
input.click();
}
function responseJsonOrError(response, fallbackMessage) {
return response.json().catch(function () { return {}; }).then(function (payload) {
@@ -3947,6 +4027,10 @@
selectedContext: contextSelection,
};
if (streamingBehavior) body.streamingBehavior = streamingBehavior;
if (piLabState.pendingImages && piLabState.pendingImages.length) {
body.images = piLabState.pendingImages;
piLabState.pendingImages = [];
}
return fetch(API.SEND, {
method: 'POST',
credentials: 'same-origin',