v3.2.0: full QA fixes and in-app virtual environment
This commit is contained in:
@@ -6,9 +6,9 @@
|
||||
var STORAGE_KEY = 'zai_chat_';
|
||||
var MODE_PROMPTS = {
|
||||
chat: 'You are a helpful, knowledgeable AI assistant. Be concise and accurate.',
|
||||
coding: 'You are an expert coding assistant. Write clean, efficient, well-documented code. Always use markdown code blocks with language tags. Explain your approach briefly before and after code. Handle edge cases and errors properly.',
|
||||
coding: 'You are an expert coding assistant with internal tool access. Use action tags when execution is needed: [CREATE_FILE ...][/CREATE_FILE], [RUN_COMMAND]...[/RUN_COMMAND], [BUILD_APK project], [INSTALL_APK path], [VENV_SETUP], [VENV_PIP_INSTALL package]. Keep responses concise and complete.',
|
||||
brainstorm: 'You are a creative brainstorming partner. Generate diverse ideas, explore unconventional angles, build on concepts, and help evaluate trade-offs. Think freely and expansively. Present ideas in organized lists or tables when appropriate.',
|
||||
agentic: 'You are an autonomous agent with FULL control of an Android device. You have a real terminal, can build APKs, control the device UI via AutoGLM, and use Hermes agent tools.\n\n## File Operations:\n[CREATE_FILE path/to/file.ext]\ncontents\n[/CREATE_FILE]\n\n## Shell:\n[RUN_COMMAND]\ncommand\n[/RUN_COMMAND]\n\n## Build:\n[BUILD_APK project_name]\n[INSTALL_APK /path/to/file.apk]\n\n## AutoGLM Device Control:\n[DEVICE_TAP x y]\n[DEVICE_LONG_PRESS x y]\n[DEVICE_SWIPE startX startY endX endY]\n[DEVICE_TYPE text]\n[DEVICE_PRESS_BACK]\n[DEVICE_PRESS_HOME]\n[DEVICE_PRESS_RECENTS]\n[DEVICE_SCREENSHOT]\n[DEVICE_UI_TREE]\n[DEVICE_CLICK_TEXT button text]\n[DEVICE_CLICK_ID com.example:id/viewId]\n[DEVICE_LAUNCH com.example.app]\n[DEVICE_CURRENT_APP]\n\n## Hermes Agent:\n[HERMES_INSTALL]\n[HERMES_EXEC command]\n\n## Rules:\n1. Use [CREATE_FILE] for files, [BUILD_APK] to compile, [INSTALL_APK] to install\n2. Use [DEVICE_*] for device control — first [DEVICE_UI_TREE] to see screen, then interact\n3. Use [HERMES_EXEC] for Hermes capabilities — web search, terminal, skills, memory\n4. Generate COMPLETE files, never stubs\n5. For Java: package ai.z.app, target SDK 36\n6. Output [TASK_COMPLETE] ONLY when ALL work is done\n7. Never say done unless all files written, builds done, installs done'
|
||||
agentic: 'You are an autonomous agent with full control of this app sandbox: internal Linux bootstrap, terminal, virtual env, build tools, and device UI via AutoGLM.\n\n## File Operations:\n[CREATE_FILE path/to/file.ext]\ncontents\n[/CREATE_FILE]\n\n## Shell:\n[RUN_COMMAND]\ncommand\n[/RUN_COMMAND]\n\n## Build:\n[BUILD_APK project_name]\n[INSTALL_APK /path/to/file.apk]\n\n## In-App Virtual Env:\n[VENV_SETUP]\n[VENV_PIP_INSTALL package_name]\n\n## AutoGLM Device Control:\n[DEVICE_TAP x y]\n[DEVICE_LONG_PRESS x y]\n[DEVICE_SWIPE startX startY endX endY]\n[DEVICE_TYPE text]\n[DEVICE_PRESS_BACK]\n[DEVICE_PRESS_HOME]\n[DEVICE_PRESS_RECENTS]\n[DEVICE_SCREENSHOT]\n[DEVICE_UI_TREE]\n[DEVICE_CLICK_TEXT button text]\n[DEVICE_CLICK_ID com.example:id/viewId]\n[DEVICE_LAUNCH com.example.app]\n[DEVICE_CURRENT_APP]\n\n## Hermes Agent:\n[HERMES_INSTALL]\n[HERMES_EXEC command]\n\n## Rules:\n1. Prefer internal sandbox tools and virtual env first\n2. Use [CREATE_FILE], then [BUILD_APK], then [INSTALL_APK]\n3. Use [DEVICE_*] for device control; start with [DEVICE_UI_TREE]\n4. Generate complete files, never stubs\n5. For Java: package ai.z.app, target SDK 36\n6. Output [TASK_COMPLETE] only when all work is done'
|
||||
};
|
||||
|
||||
var BUILD_SCRIPT = [
|
||||
@@ -623,7 +623,7 @@
|
||||
if (state.streamingContent) {
|
||||
conv.messages.push({ role: 'assistant', content: state.streamingContent, _streaming: false });
|
||||
}
|
||||
var retryDiv = appendRetryMessage(err, requestBody, conv);
|
||||
appendRetryMessage(err, requestBody, conv);
|
||||
} else if (state.streamingContent) {
|
||||
conv.messages.push({ role: 'assistant', content: state.streamingContent, _streaming: false });
|
||||
}
|
||||
@@ -1237,7 +1237,7 @@
|
||||
async function installApk(path) {
|
||||
if (!Installer) { termPrint('[Installer plugin not available]', 'err'); return; }
|
||||
try {
|
||||
var result = await Installer.installApk({ path: path });
|
||||
await Installer.installApk({ path: path });
|
||||
termPrint('[APK install triggered: ' + path + ']', 'success');
|
||||
} catch(e) {
|
||||
termPrint('[Install failed: ' + e.message + ']', 'err');
|
||||
@@ -1441,6 +1441,8 @@
|
||||
var deviceCurrentAppRegex = /\[DEVICE_CURRENT_APP\]/gi;
|
||||
var hermesInstallRegex = /\[HERMES_INSTALL\]/gi;
|
||||
var hermesExecRegex = /\[HERMES_EXEC\s+([^\]]+)\]/gi;
|
||||
var venvSetupRegex = /\[VENV_SETUP\]/gi;
|
||||
var venvPipInstallRegex = /\[VENV_PIP_INSTALL\s+([^\]]+)\]/gi;
|
||||
var codeBlockFileRegex = /```(\w+)\s*\n([\s\S]*?)```/gi;
|
||||
var match;
|
||||
|
||||
@@ -1501,6 +1503,12 @@
|
||||
while ((match = hermesExecRegex.exec(content)) !== null) {
|
||||
actions.push({ type: 'hermes_exec', command: match[1].trim() });
|
||||
}
|
||||
while ((match = venvSetupRegex.exec(content)) !== null) {
|
||||
actions.push({ type: 'venv_setup' });
|
||||
}
|
||||
while ((match = venvPipInstallRegex.exec(content)) !== null) {
|
||||
actions.push({ type: 'venv_pip_install', packages: match[1].trim() });
|
||||
}
|
||||
while ((match = codeBlockFileRegex.exec(content)) !== null) {
|
||||
var lang = match[1];
|
||||
var code = match[2];
|
||||
@@ -1673,7 +1681,8 @@
|
||||
content.indexOf('[BUILD_APK') >= 0 ||
|
||||
content.indexOf('[INSTALL_APK') >= 0 ||
|
||||
content.indexOf('[DEVICE_') >= 0 ||
|
||||
content.indexOf('[HERMES_') >= 0;
|
||||
content.indexOf('[HERMES_') >= 0 ||
|
||||
content.indexOf('[VENV_') >= 0;
|
||||
var hasCodeBlock = content.indexOf('```') >= 0;
|
||||
if (!hasCodeBlock && !hasAction && content.length < 300) return true;
|
||||
if ((content.match(/```/g) || []).length % 2 !== 0) return false;
|
||||
@@ -1895,7 +1904,7 @@
|
||||
var saveBtn = $('#file-viewer-save');
|
||||
var editBtn = $('#file-viewer-edit');
|
||||
|
||||
if (!viewer) return;
|
||||
if (!viewer || !nameEl || !langEl || !contentEl || !textareaEl || !bodyEl || !editorEl || !saveBtn || !editBtn) return;
|
||||
nameEl.textContent = file.path;
|
||||
langEl.textContent = file.language;
|
||||
contentEl.textContent = file.content;
|
||||
@@ -2151,8 +2160,9 @@
|
||||
}
|
||||
|
||||
async function tryProotExec(prootCmd, prefixUsr, pkgBin, aptBin) {
|
||||
var hasPkg = await shellExec('test -f "' + pkgBin + '"', termState.homeDir, false);
|
||||
var pkgCmd = 'sh /usr/bin/pkg update -y 2>&1 && sh /usr/bin/pkg install -y aapt2 ecj dx apksigner 2>&1';
|
||||
if (!new File(pkgBin).exists) pkgCmd = 'sh /usr/bin/apt update -y 2>&1 && sh /usr/bin/apt install -y aapt2 ecj dx apksigner 2>&1';
|
||||
if (hasPkg.exitCode !== 0) pkgCmd = 'sh /usr/bin/apt update -y 2>&1 && sh /usr/bin/apt install -y aapt2 ecj dx apksigner 2>&1';
|
||||
var wrappedCmd = prootCmd + ' -0 -b /dev -b /proc -b /sys -r ' + prefixUsr + ' /bin/sh -c \'' + pkgCmd.replace(/'/g, "'\\''") + '\'';
|
||||
|
||||
termPrint('[*] Running pkg via PRoot...', 'info');
|
||||
@@ -2186,7 +2196,7 @@
|
||||
|
||||
termPrint('[OK] Termux detected! Sending install command...', 'success');
|
||||
try {
|
||||
var runResult = await Bootstrap.runInTermux({command: 'pkg update -y && pkg install -y aapt2 ecj dx apksigner'});
|
||||
await Bootstrap.runInTermux({command: 'pkg update -y && pkg install -y aapt2 ecj dx apksigner'});
|
||||
termPrint('[*] Command sent to Termux. Waiting...', 'info');
|
||||
await new Promise(function(r) { setTimeout(r, 15000); });
|
||||
if (await toolsReady()) return true;
|
||||
@@ -2314,8 +2324,9 @@
|
||||
var hasCommands = actions.some(function(a) { return a.type === 'run_command'; });
|
||||
var hasDevice = actions.some(function(a) { return a.type && a.type.indexOf('device_') === 0; });
|
||||
var hasHermes = actions.some(function(a) { return a.type && a.type.indexOf('hermes_') === 0; });
|
||||
var hasVenv = actions.some(function(a) { return a.type && a.type.indexOf('venv_') === 0; });
|
||||
|
||||
if (!hasFiles && !hasBuild && !hasInstall && !hasCommands && !hasDevice && !hasHermes) return;
|
||||
if (!hasFiles && !hasBuild && !hasInstall && !hasCommands && !hasDevice && !hasHermes && !hasVenv) return;
|
||||
|
||||
_agenticRetryCount = 0;
|
||||
var resultLog = [];
|
||||
@@ -2376,6 +2387,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (hasVenv) {
|
||||
for (var v = 0; v < actions.length; v++) {
|
||||
var vAct = actions[v];
|
||||
if (vAct.type.indexOf('venv_') !== 0) continue;
|
||||
try {
|
||||
var venvResult = await executeVirtualEnvAction(vAct);
|
||||
resultLog.push(venvResult);
|
||||
termPrint(venvResult, '');
|
||||
} catch(e) {
|
||||
resultLog.push('VENV_ERROR: ' + e.message);
|
||||
termPrint('[!] Venv: ' + e.message, 'err');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBuild) {
|
||||
showStatusToast('Building APK...', 'info');
|
||||
var toolsReady = await ensureBuildTools();
|
||||
@@ -2485,6 +2511,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function executeVirtualEnvAction(action) {
|
||||
var bsPlugin = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Bootstrap;
|
||||
if (!bsPlugin) throw new Error('Bootstrap plugin not available');
|
||||
var venvPath = termState.homeDir ? (termState.homeDir.replace(/\/home$/, '') + '/venv/default') : '';
|
||||
|
||||
switch (action.type) {
|
||||
case 'venv_setup': {
|
||||
showStatusToast('Setting up in-app virtual environment...', 'info');
|
||||
var setup = await bsPlugin.setupVirtualEnv({ venv: venvPath });
|
||||
termState.venvPath = setup.venv;
|
||||
return '[VENV] Ready: ' + setup.venv;
|
||||
}
|
||||
case 'venv_pip_install': {
|
||||
if (!termState.venvPath) {
|
||||
var init = await bsPlugin.setupVirtualEnv({ venv: venvPath });
|
||||
termState.venvPath = init.venv;
|
||||
}
|
||||
showStatusToast('Installing module(s): ' + action.packages, 'info');
|
||||
var installed = await bsPlugin.venvPipInstall({ venv: termState.venvPath, packages: action.packages });
|
||||
return '[VENV] pip install ' + action.packages + '\n' + (installed.output || '').substring(0, 1200);
|
||||
}
|
||||
default:
|
||||
return '[VENV] Unknown action: ' + action.type;
|
||||
}
|
||||
}
|
||||
|
||||
async function autoDeployFile(action) {
|
||||
var path = action.path;
|
||||
if (!path.startsWith('/')) {
|
||||
@@ -2716,7 +2768,7 @@
|
||||
});
|
||||
|
||||
try {
|
||||
var result = await Bootstrap.install();
|
||||
await Bootstrap.install();
|
||||
|
||||
progressText.textContent = 'Fixing file permissions...';
|
||||
try { await Bootstrap.fixPermissions(); } catch(e) {}
|
||||
|
||||
Reference in New Issue
Block a user