更新
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build": "pnpm vite build --mode production && node ../../scripts/verify-token-build.mjs dist",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { resolve, dirname, relative, extname } from 'node:path';
|
||||
|
||||
// Inspect only the graph reached from index.html; old chunks left in dist do not count.
|
||||
export function verifyTokenBuild(directory) {
|
||||
const root = resolve(directory);
|
||||
const visited = new Set();
|
||||
function visit(path) {
|
||||
path = resolve(path);
|
||||
const rel = relative(root, path);
|
||||
if (rel.startsWith('..') || !existsSync(path) || visited.has(path)) return;
|
||||
visited.add(path);
|
||||
const text = readFileSync(path, 'utf8');
|
||||
for (const match of text.matchAll(/["'`]((?:\.{0,2}\/)?[\w./-]+\.js)["'`]/g)) {
|
||||
const ref = match[1];
|
||||
visit(ref.startsWith('/') ? resolve(root, ref.slice(1)) : resolve(dirname(path), ref));
|
||||
}
|
||||
}
|
||||
visit(resolve(root, 'index.html'));
|
||||
const stats = [...visited].filter((path) => /[\\/]call-stats-[^\\/]+\.js$/.test(path));
|
||||
if (stats.length !== 1 || !readFileSync(stats[0], 'utf8').includes('ModelUsageStats-')) {
|
||||
throw new Error('The active call statistics page does not include Token usage. Refusing this build.');
|
||||
}
|
||||
const usage = [...visited].filter((path) => /[\\/]ModelUsageStats-[^\\/]+\.js$/.test(path));
|
||||
const hasApi = [...visited].some((path) => extname(path) === '.js' && readFileSync(path, 'utf8').includes('/stats/model-usage/log'));
|
||||
if (!usage.length || !hasApi) throw new Error('The active Token component or usage API is missing.');
|
||||
return { page: relative(root, stats[0]), component: relative(root, usage[0]), assets: visited.size };
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(verifyTokenBuild(process.argv[2] || 'dist')));
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build": "pnpm vite build --mode production && node ../../scripts/verify-token-build.mjs dist",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { resolve, dirname, relative, extname } from 'node:path';
|
||||
|
||||
// Inspect only the graph reached from index.html; old chunks left in dist do not count.
|
||||
export function verifyTokenBuild(directory) {
|
||||
const root = resolve(directory);
|
||||
const visited = new Set();
|
||||
function visit(path) {
|
||||
path = resolve(path);
|
||||
const rel = relative(root, path);
|
||||
if (rel.startsWith('..') || !existsSync(path) || visited.has(path)) return;
|
||||
visited.add(path);
|
||||
const text = readFileSync(path, 'utf8');
|
||||
for (const match of text.matchAll(/["'`]((?:\.{0,2}\/)?[\w./-]+\.js)["'`]/g)) {
|
||||
const ref = match[1];
|
||||
visit(ref.startsWith('/') ? resolve(root, ref.slice(1)) : resolve(dirname(path), ref));
|
||||
}
|
||||
}
|
||||
visit(resolve(root, 'index.html'));
|
||||
const stats = [...visited].filter((path) => /[\\/]call-stats-[^\\/]+\.js$/.test(path));
|
||||
if (stats.length !== 1 || !readFileSync(stats[0], 'utf8').includes('ModelUsageStats-')) {
|
||||
throw new Error('The active call statistics page does not include Token usage. Refusing this build.');
|
||||
}
|
||||
const usage = [...visited].filter((path) => /[\\/]ModelUsageStats-[^\\/]+\.js$/.test(path));
|
||||
const hasApi = [...visited].some((path) => extname(path) === '.js' && readFileSync(path, 'utf8').includes('/stats/model-usage/log'));
|
||||
if (!usage.length || !hasApi) throw new Error('The active Token component or usage API is missing.');
|
||||
return { page: relative(root, stats[0]), component: relative(root, usage[0]), assets: visited.size };
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(verifyTokenBuild(process.argv[2] || 'dist')));
|
||||
@@ -1,6 +0,0 @@
|
||||
/usr/local/lib/python3.12/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
----------------------------------------------------------------------
|
||||
Ran 45 tests in 9.600s
|
||||
|
||||
OK
|
||||
@@ -1,220 +0,0 @@
|
||||
Build Python: C:\wechat_rpa\.build-venv\Scripts\python.exe
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_final.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_media.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_voice2text.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_crypto.py -> archive_exporter
|
||||
256 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
257 INFO: Python: 3.12.14
|
||||
312 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
312 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
6007 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
6794 INFO: Appending 'binaries' from .spec
|
||||
6796 INFO: Appending 'datas' from .spec
|
||||
6802 INFO: checking Analysis
|
||||
6974 INFO: Building because excludes changed
|
||||
6974 INFO: Looking for Python shared library...
|
||||
6974 INFO: Using Python shared library: C:\Users\isard\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python312.dll
|
||||
6974 INFO: Running Analysis Analysis-00.toc
|
||||
6974 INFO: Target bytecode optimization level: 1
|
||||
6974 INFO: Initializing module dependency graph...
|
||||
6977 INFO: Initializing module graph hook caches...
|
||||
7001 INFO: Analyzing modules for base_library.zip ...
|
||||
8736 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
9808 INFO: Processing standard module hook 'hook-math.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10075 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
11280 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13060 INFO: Caching module dependency graph...
|
||||
13120 INFO: Analyzing C:\wechat_rpa\app_main.py
|
||||
13280 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13497 INFO: Processing standard module hook 'hook-xml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13825 INFO: Processing standard module hook 'hook-_ctypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13934 INFO: Processing standard module hook 'hook-sqlite3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
14425 INFO: Processing standard module hook 'hook-Crypto.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
15441 INFO: Processing standard module hook 'hook-pycparser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
15642 INFO: Processing standard module hook 'hook-setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
15644 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
16510 INFO: Processing standard module hook 'hook-platform.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
16514 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
16581 INFO: Processing standard module hook 'hook-sysconfig.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
16596 INFO: Processing pre-safe-import-module hook 'hook-jaraco.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
16597 INFO: Setuptools: 'jaraco' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.jaraco'!
|
||||
16612 INFO: Processing pre-safe-import-module hook 'hook-more_itertools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
16613 INFO: Setuptools: 'more_itertools' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.more_itertools'!
|
||||
16798 INFO: Processing standard module hook 'hook-_osx_support.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
16803 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
17570 INFO: Processing pre-safe-import-module hook 'hook-packaging.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
17928 INFO: Processing standard module hook 'hook-setuptools._vendor.jaraco.text.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
17931 INFO: Processing pre-safe-import-module hook 'hook-importlib_resources.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
18199 INFO: Processing pre-safe-import-module hook 'hook-backports.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
18200 INFO: Setuptools: 'backports' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.backports'!
|
||||
19040 INFO: Processing pre-safe-import-module hook 'hook-tomli.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
19041 INFO: Setuptools: 'tomli' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.tomli'!
|
||||
19792 INFO: Processing pre-safe-import-module hook 'hook-wheel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
19793 INFO: Setuptools: 'wheel' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.wheel'!
|
||||
20498 INFO: Processing standard module hook 'hook-webbrowser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
21547 INFO: Processing standard module hook 'hook-PySide6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
21853 INFO: Processing standard module hook 'hook-shiboken6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
22064 INFO: Processing standard module hook 'hook-PySide6.QtNetwork.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
26254 INFO: Processing standard module hook 'hook-PySide6.QtCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
29377 INFO: Processing standard module hook 'hook-numpy.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
31432 INFO: Processing standard module hook 'hook-difflib.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
32546 INFO: Processing standard module hook 'hook-charset_normalizer.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
33113 INFO: Processing standard module hook 'hook-av.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
34705 INFO: Processing standard module hook 'hook-certifi.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
34858 INFO: Processing standard module hook 'hook-anyio.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
36860 INFO: Processing standard module hook 'hook-pygments.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
38772 INFO: Processing standard module hook 'hook-rich.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
41267 INFO: Processing standard module hook 'hook-pydantic.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
42366 INFO: Processing standard module hook 'hook-zoneinfo.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
44608 INFO: Processing standard module hook 'hook-PIL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
44748 INFO: Processing standard module hook 'hook-PIL.Image.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
45350 INFO: Processing standard module hook 'hook-xml.etree.cElementTree.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
45574 INFO: Processing standard module hook 'hook-PIL.ImageFilter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
47663 INFO: Processing standard module hook 'hook-fsspec.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
49108 INFO: Processing standard module hook 'hook-opentelemetry.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
49962 INFO: Processing standard module hook 'hook-uvicorn.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
51430 INFO: Processing standard module hook 'hook-websockets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
52861 INFO: Processing standard module hook 'hook-urllib3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
53481 INFO: Processing standard module hook 'hook-cryptography.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
55744 INFO: hook-cryptography: cryptography does not seem to be using dynamically linked OpenSSL.
|
||||
57266 INFO: Processing standard module hook 'hook-pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
57602 INFO: Processing standard module hook 'hook-jsonschema.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
57818 INFO: Processing standard module hook 'hook-jsonschema_specifications.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
58143 INFO: Processing standard module hook 'hook-onnxruntime.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
58266 INFO: Processing pre-safe-import-module hook 'hook-tensorflow.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\pre_safe_import_module'
|
||||
60718 INFO: Processing standard module hook 'hook-PySide6.QtGui.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
95988 INFO: Processing standard module hook 'hook-PySide6.QtWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
101635 INFO: Processing standard module hook 'hook-PySide6.QtWebChannel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
103866 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
110889 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
113470 INFO: Processing standard module hook 'hook-PySide6.QtPrintSupport.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
117410 INFO: Processing pre-find-module-path hook 'hook-tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
117412 INFO: TclTkInfo: initializing cached Tcl/Tk info...
|
||||
118895 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
119053 INFO: Processing standard module hook 'hook-cv2.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
120076 INFO: Processing standard module hook 'hook-shapely.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
121120 INFO: Analyzing hidden import 'mcp.cli'
|
||||
121597 INFO: Analyzing hidden import 'mcp.client.__main__'
|
||||
121602 INFO: Analyzing hidden import 'mcp.client.auth'
|
||||
121655 INFO: Analyzing hidden import 'mcp.client.auth.extensions'
|
||||
121655 INFO: Analyzing hidden import 'mcp.client.auth.extensions.client_credentials'
|
||||
121764 INFO: Analyzing hidden import 'mcp.client.auth.extensions.identity_assertion'
|
||||
121772 INFO: Analyzing hidden import 'mcp.server.__main__'
|
||||
121774 INFO: Analyzing hidden import 'mcp.server.apps'
|
||||
121782 INFO: Analyzing hidden import 'mcp.server.fastmcp'
|
||||
121783 INFO: Analyzing hidden import 'mcp.shared.metadata_utils'
|
||||
121787 INFO: Analyzing hidden import 'av.__main__'
|
||||
121790 INFO: Analyzing hidden import 'av.container.pyio'
|
||||
121799 INFO: Analyzing hidden import 'av.datasets'
|
||||
121805 INFO: Analyzing hidden import 'av.dictionary'
|
||||
121807 INFO: Analyzing hidden import 'av.filter.link'
|
||||
121808 INFO: Analyzing hidden import 'av.opaque'
|
||||
121811 INFO: Analyzing hidden import 'av.sidedata.encparams'
|
||||
121813 INFO: Analyzing hidden import 'av.utils'
|
||||
121817 INFO: Analyzing hidden import 'faster_whisper.assets'
|
||||
121819 INFO: Processing module hooks (post-graph stage)...
|
||||
122552 WARNING: Hidden import "pycparser.lextab" not found!
|
||||
122552 WARNING: Hidden import "pycparser.yacctab" not found!
|
||||
123154 WARNING: Hidden import "tzdata" not found!
|
||||
123547 INFO: Processing standard module hook 'hook-PIL.SpiderImagePlugin.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
126839 INFO: Processing standard module hook 'hook-PySide6.QtQuick.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
130767 INFO: Processing standard module hook 'hook-PySide6.QtOpenGL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
134910 INFO: Processing standard module hook 'hook-PySide6.QtQml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
177936 INFO: Processing standard module hook 'hook-PySide6.QtPositioning.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
180570 INFO: Processing standard module hook 'hook-PySide6.QtQuickWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
181928 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
182002 INFO: Performing binary vs. data reclassification (3792 entries)
|
||||
182799 INFO: Looking for ctypes DLLs
|
||||
183428 INFO: Analyzing run-time hooks ...
|
||||
183444 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183447 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183451 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183454 INFO: Including run-time hook 'pyi_rth_setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183456 INFO: Including run-time hook 'pyi_rth_cryptography_openssl.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
183458 INFO: Including run-time hook 'pyi_rth_pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
183459 INFO: Including run-time hook 'pyi_rth_pyside6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183461 INFO: Processing pre-find-module-path hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
183463 INFO: Processing standard module hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
183468 INFO: Including run-time hook 'pyi_rth__tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
183645 INFO: Creating base_library.zip...
|
||||
184031 INFO: Looking for dynamic libraries
|
||||
188649 INFO: Extra DLL search directories (AddDllDirectory): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shiboken6', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\numpy.libs', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\av.libs', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\ctranslate2', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\ctranslate2/../_rocm_sdk_core/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shapely.libs']
|
||||
188649 INFO: Extra DLL search directories (PATH): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PySide6']
|
||||
196458 INFO: Warnings written to C:\wechat_rpa\build\wechat_rpa\warn-wechat_rpa.txt
|
||||
196768 INFO: Graph cross-reference written to C:\wechat_rpa\build\wechat_rpa\xref-wechat_rpa.html
|
||||
197016 INFO: checking PYZ
|
||||
197068 INFO: Building because toc changed
|
||||
197068 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
209763 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz completed successfully.
|
||||
209823 INFO: checking PKG
|
||||
209837 INFO: Building because name changed
|
||||
209838 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.28.pkg
|
||||
209894 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.28.pkg completed successfully.
|
||||
209896 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\runw.exe
|
||||
209896 INFO: checking EXE
|
||||
209913 INFO: Rebuilding EXE-00.toc because ZhenAI-WeCom-Assistant-v1.4.28.exe missing
|
||||
209913 INFO: Building EXE from EXE-00.toc
|
||||
209913 INFO: Copying bootloader EXE to C:\wechat_rpa\build\wechat_rpa\ZhenAI-WeCom-Assistant-v1.4.28.exe
|
||||
209973 INFO: Copying icon to EXE
|
||||
210018 INFO: Copying version information to EXE
|
||||
210067 INFO: Copying 0 resources to EXE
|
||||
210067 INFO: Embedding manifest in EXE
|
||||
210115 INFO: Appending PKG archive to EXE
|
||||
210241 INFO: Fixing EXE headers
|
||||
210672 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
210791 INFO: checking COLLECT
|
||||
210891 INFO: Building COLLECT COLLECT-00.toc
|
||||
216954 INFO: Building COLLECT COLLECT-00.toc completed successfully.
|
||||
217080 INFO: Build complete! The results are available in: C:\wechat_rpa\dist
|
||||
Embedded browser and VC runtime files verified
|
||||
192 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
192 INFO: Python: 3.12.14
|
||||
232 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
232 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
233 INFO: wrote C:\wechat_rpa\build\updater-helper\ZhenAIUpdater.spec
|
||||
248 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
834 INFO: checking Analysis
|
||||
857 INFO: checking PYZ
|
||||
865 INFO: checking PKG
|
||||
868 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\run.exe
|
||||
868 INFO: checking EXE
|
||||
869 INFO: Build complete! The results are available in: C:\wechat_rpa\dist\updater-helper
|
||||
Code signing skipped (no certificate configured): ZhenAIUpdater.exe
|
||||
Independent updater built and bundled
|
||||
Code signing skipped (no certificate configured): ZhenAI-WeCom-Assistant-v1.4.28.exe
|
||||
Packaged Qt WebEngine self-check passed
|
||||
Packaged real HTTPS and certificate verification checks passed (clean PATH)
|
||||
Packaged automatic decryption and incremental cloud upload checks passed (synthetic data, mocked transport)
|
||||
Packaged Messages navigation and OCR checks passed (synthetic UI, mocked input)
|
||||
Packaged cross-machine capture, DPI and unread click checks passed (synthetic pixels, mocked input)
|
||||
Packaged self-reply feedback and send guards passed (synthetic archive, mocked input)
|
||||
Packaged background database detection and database-first reply checks passed (synthetic data, mocked input)
|
||||
App folder: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.28
|
||||
EXE: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.28\ZhenAI-WeCom-Assistant-v1.4.28.exe
|
||||
SHA256: 5AAE5340AAD87E69EE5BE94B8A891E8CC1D72D6B26E816FEBAE33F23AE7A00D0
|
||||
@@ -1 +0,0 @@
|
||||
{"project": "C:\\wechat_rpa", "modules": ["test_protocol_contact_recovery", "test_contact_reply_guard", "test_native_protocol_pipeline", "test_protocol_voice", "test_protocol_listener_continuity", "test_protocol_session_exclusions", "test_protocol_review_assistant", "test_protocol_manual_assistant", "test_protocol_review_visibility", "test_protocol_audit_boundaries", "test_contact_relation_snapshot", "test_database_reply_priority", "test_database_timestamp_audit", "test_database_loading_performance", "test_voice_messages", "test_voice_transcription", "test_review_policy_integration"], "tests_run": 308, "failures": 0, "errors": 0, "skipped": 0, "elapsed_seconds": 17.563, "blocked_external_actions": []}
|
||||
@@ -1,30 +0,0 @@
|
||||
MakeNSIS v3.12 - Copyright 1999-2026 Contributors
|
||||
See the file COPYING for license details.
|
||||
Credits can be found in the Users Manual.
|
||||
|
||||
Command line defined: "APP_VERSION=1.4.28"
|
||||
Command line defined: "APP_FILE_VERSION=1.4.28.0"
|
||||
Command line defined: "SOURCE_DIR=C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.28"
|
||||
Processing config: C:\wechat_rpa\.installer-tools\NSIS\nsisconf.nsh
|
||||
Processing script file: "C:\wechat_rpa\installer.nsi" (UTF8)
|
||||
|
||||
Processed 1 file, writing output (x86-unicode):
|
||||
|
||||
Output: "C:\wechat_rpa\dist\installer\��AI�ͷ�-��װ��-v1.4.28.exe"
|
||||
Install: 4 pages (256 bytes), 1 section (2072 bytes), 4896 instructions (137088 bytes), 3452 strings (147400 bytes), 1 language table (302 bytes).
|
||||
Uninstall: 3 pages (256 bytes), 1 section (2072 bytes), 285 instructions (7980 bytes), 167 strings (3562 bytes), 1 language table (282 bytes).
|
||||
Datablock optimizer saved 1786 KiB (~0.1%).
|
||||
|
||||
Using zlib (compress whole) compression.
|
||||
|
||||
EXE header size: 118784 / 40960 bytes
|
||||
Install code: (287582 bytes)
|
||||
Install data: (1168969920 bytes)
|
||||
Uninstall code+data: (141472 bytes)
|
||||
Compressed data: 542052615 / 1169398974 bytes
|
||||
CRC (0x545CEDE4): 4 / 4 bytes
|
||||
|
||||
Total size: 542171403 / 1169439938 bytes (46.3%)
|
||||
Code signing skipped (no certificate configured): 甄AI客服-安装包-v1.4.28.exe
|
||||
Installer: C:\wechat_rpa\dist\installer\甄AI客服-安装包-v1.4.28.exe
|
||||
SHA256: DC5A4D73DCE176159B16D8EE72E5291B32868CDFB539DEC0FC2DFC93C8CB775F
|
||||
@@ -1,77 +0,0 @@
|
||||
test_context_refresh_observes_current_account_relation_wal (test_contact_relation_snapshot.ContactRelationTests.test_context_refresh_observes_current_account_relation_wal) ... ok
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 58 tests in 3.813s
|
||||
|
||||
OK
|
||||
@@ -1,79 +0,0 @@
|
||||
test_context_refresh_observes_current_account_relation_wal (test_contact_relation_snapshot.ContactRelationTests.test_context_refresh_observes_current_account_relation_wal) ... ok
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_relationship_wal_commits_multi_page_transaction_together (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_commits_multi_page_transaction_together) ... ok
|
||||
test_relationship_wal_ignores_uncommitted_tail (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_ignores_uncommitted_tail) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 60 tests in 3.766s
|
||||
|
||||
OK
|
||||
@@ -1,76 +0,0 @@
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 57 tests in 3.618s
|
||||
|
||||
OK
|
||||
@@ -1,21 +0,0 @@
|
||||
test_context_refresh_observes_current_account_relation_wal (test_contact_relation_snapshot.ContactRelationTests.test_context_refresh_observes_current_account_relation_wal) ... ok
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_relationship_wal_commits_multi_page_transaction_together (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_commits_multi_page_transaction_together) ... ok
|
||||
test_relationship_wal_ignores_uncommitted_tail (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_ignores_uncommitted_tail) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 16 tests in 0.935s
|
||||
|
||||
OK
|
||||
@@ -1,67 +0,0 @@
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 48 tests in 2.991s
|
||||
|
||||
OK
|
||||
@@ -1,3 +0,0 @@
|
||||
........................................................................ [ 83%]
|
||||
.............. [100%]
|
||||
86 passed in 4.06s
|
||||
@@ -1,490 +0,0 @@
|
||||
test_already_attempted_event_never_replayed_for_any_receipt_state (test_protocol_contact_recovery.ContactRecoveryTests.test_already_attempted_event_never_replayed_for_any_receipt_state) ... ok
|
||||
test_assistant_conversation_not_restored_as_auto_reply_target (test_protocol_contact_recovery.ContactRecoveryTests.test_assistant_conversation_not_restored_as_auto_reply_target) ... ok
|
||||
test_final_native_guard_can_recheck_its_own_inflight_journal (test_protocol_contact_recovery.ContactRecoveryTests.test_final_native_guard_can_recheck_its_own_inflight_journal) ... ok
|
||||
test_fresh_inbound_does_not_overwrite_manual_task_during_contact_recheck (test_protocol_contact_recovery.ContactRecoveryTests.test_fresh_inbound_does_not_overwrite_manual_task_during_contact_recheck) ... ok
|
||||
test_historical_contact_notice_cannot_erase_unknown_send_protection (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_contact_notice_cannot_erase_unknown_send_protection) ... ok
|
||||
test_historical_notice_without_saved_block_does_not_hide_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_notice_without_saved_block_does_not_hide_new_question) ... ok
|
||||
test_journal_read_failure_does_not_replay_seen_event (test_protocol_contact_recovery.ContactRecoveryTests.test_journal_read_failure_does_not_replay_seen_event) ... ok
|
||||
test_legacy_block_uses_exact_hash_and_account_not_name (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_block_uses_exact_hash_and_account_not_name) ... ok
|
||||
test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer) ... ok
|
||||
test_limit_two_backfills_and_five_second_throttle (test_protocol_contact_recovery.ContactRecoveryTests.test_limit_two_backfills_and_five_second_throttle) ... ok
|
||||
test_new_block_during_generation_invalidates_new_answer (test_protocol_contact_recovery.ContactRecoveryTests.test_new_block_during_generation_invalidates_new_answer) ... ok
|
||||
test_new_question_still_requires_fresh_review (test_protocol_contact_recovery.ContactRecoveryTests.test_new_question_still_requires_fresh_review) ... ok
|
||||
test_old_added_at_active_relation_rechecks_new_message_without_restore_notice (test_protocol_contact_recovery.ContactRecoveryTests.test_old_added_at_active_relation_rechecks_new_message_without_restore_notice) ... ok
|
||||
test_own_reply_after_block_prevents_unanswered_backfill (test_protocol_contact_recovery.ContactRecoveryTests.test_own_reply_after_block_prevents_unanswered_backfill) ... ok
|
||||
test_receiving_customer_text_alone_is_not_relationship_proof (test_protocol_contact_recovery.ContactRecoveryTests.test_receiving_customer_text_alone_is_not_relationship_proof) ... ok
|
||||
test_recovery_does_not_remove_existing_manual_or_uncertain_tasks (test_protocol_contact_recovery.ContactRecoveryTests.test_recovery_does_not_remove_existing_manual_or_uncertain_tasks) ... ok
|
||||
test_rejection_records_actual_source_and_later_new_question_can_recheck_once (test_protocol_contact_recovery.ContactRecoveryTests.test_rejection_records_actual_source_and_later_new_question_can_recheck_once) ... ok
|
||||
test_relation_change_during_generation_invalidates_reply (test_protocol_contact_recovery.ContactRecoveryTests.test_relation_change_during_generation_invalidates_reply) ... ok
|
||||
test_restart_keeps_failed_event_and_recovers_only_later_message (test_protocol_contact_recovery.ContactRecoveryTests.test_restart_keeps_failed_event_and_recovers_only_later_message) ... ok
|
||||
test_same_or_older_customer_anchor_is_not_new (test_protocol_contact_recovery.ContactRecoveryTests.test_same_or_older_customer_anchor_is_not_new) ... ok
|
||||
test_same_second_later_row_is_new_and_keeps_order (test_protocol_contact_recovery.ContactRecoveryTests.test_same_second_later_row_is_new_and_keeps_order) ... ok
|
||||
test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active (test_protocol_contact_recovery.ContactRecoveryTests.test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active) ... ok
|
||||
test_system_and_forged_direction_or_sender_are_not_new_customer_events (test_protocol_contact_recovery.ContactRecoveryTests.test_system_and_forged_direction_or_sender_are_not_new_customer_events) ... ok
|
||||
test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question) ... ok
|
||||
test_untranscribed_voice_waits_while_other_conversation_can_process (test_protocol_contact_recovery.ContactRecoveryTests.test_untranscribed_voice_waits_while_other_conversation_can_process) ... ok
|
||||
test_voice_new_question_is_transcribed_before_model_not_old_notice_manual (test_protocol_contact_recovery.ContactRecoveryTests.test_voice_new_question_is_transcribed_before_model_not_old_notice_manual) ... ok
|
||||
test_black_chat_quote_is_not_a_system_banner (test_contact_reply_guard.NoticeTests.test_black_chat_quote_is_not_a_system_banner) ... ok
|
||||
test_complete_notice_and_wrapped_ocr (test_contact_reply_guard.NoticeTests.test_complete_notice_and_wrapped_ocr) ... ok
|
||||
test_customer_quote_is_not_a_protocol_system_notice (test_contact_reply_guard.NoticeTests.test_customer_quote_is_not_a_protocol_system_notice) ... ok
|
||||
test_discussing_verification_or_single_failure_icon_is_not_evidence (test_contact_reply_guard.NoticeTests.test_discussing_verification_or_single_failure_icon_is_not_evidence) ... ok
|
||||
test_grey_centered_system_notice (test_contact_reply_guard.NoticeTests.test_grey_centered_system_notice) ... ok
|
||||
test_low_confidence_does_not_blacklist (test_contact_reply_guard.NoticeTests.test_low_confidence_does_not_blacklist) ... ok
|
||||
test_system_restoration_supersedes_old_restriction (test_contact_reply_guard.NoticeTests.test_system_restoration_supersedes_old_restriction) ... ok
|
||||
test_existing_system_notice_is_checked_before_generation (test_contact_reply_guard.ProtocolContactTests.test_existing_system_notice_is_checked_before_generation) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_failed_notice_lookup_keeps_unknown_send_protected (test_contact_reply_guard.ProtocolContactTests.test_failed_notice_lookup_keeps_unknown_send_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;callback timeout
|
||||
ok
|
||||
test_notice_arriving_during_generation_cancels_draft (test_contact_reply_guard.ProtocolContactTests.test_notice_arriving_during_generation_cancels_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_notice_blocks_one_chat_and_another_chat_still_sends (test_contact_reply_guard.ProtocolContactTests.test_notice_blocks_one_chat_and_another_chat_still_sends) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_other_send_failure_remains_protected (test_contact_reply_guard.ProtocolContactTests.test_other_send_failure_remains_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 客户端拒绝发送,需人工核对;network unavailable
|
||||
ok
|
||||
test_rejection_during_send_is_not_retried_after_restart (test_contact_reply_guard.ProtocolContactTests.test_rejection_during_send_is_not_retried_after_restart) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 该用户不是你的联系人;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 消息早于最近一次实际拒收,禁止重试旧问题
|
||||
ok
|
||||
test_restore_notice_allows_later_message (test_contact_reply_guard.ProtocolContactTests.test_restore_notice_allows_later_message) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_unknown_receipt_with_contact_notice_isolated_without_resending (test_contact_reply_guard.ProtocolContactTests.test_unknown_receipt_with_contact_notice_isolated_without_resending) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_user_quoting_notice_does_not_disable_chat (test_contact_reply_guard.ProtocolContactTests.test_user_quoting_notice_does_not_disable_chat) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_failed_outgoing_bubble_is_never_archived_as_success (test_contact_reply_guard.VisualSkipTests.test_failed_outgoing_bubble_is_never_archived_as_success) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_ocr_error_keeps_customer_task (test_contact_reply_guard.VisualSkipTests.test_ocr_error_keeps_customer_task) ... ok
|
||||
test_skip_clears_pending_and_uncommitted_exchange_then_persists (test_contact_reply_guard.VisualSkipTests.test_skip_clears_pending_and_uncommitted_exchange_then_persists) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_uncertain_send_with_rejection_skips_without_receipt_or_retry (test_contact_reply_guard.VisualSkipTests.test_uncertain_send_with_rejection_skips_without_receipt_or_retry) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_isolated_with_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_isolated_with_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_cache_change_keeps_independent_manual_block (test_protocol_voice.ProtocolVoiceTests.test_cache_change_keeps_independent_manual_block) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer (test_protocol_voice.ProtocolVoiceTests.test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_direct_judge_receives_entire_mixed_unanswered_batch (test_protocol_voice.ProtocolVoiceTests.test_direct_judge_receives_entire_mixed_unanswered_batch) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型裁判评估为高风险
|
||||
ok
|
||||
test_failed_transcription_enters_manual_and_never_calls_model (test_protocol_voice.ProtocolVoiceTests.test_failed_transcription_enters_manual_and_never_calls_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音自动转文字失败(empty_audio),请人工核对
|
||||
ok
|
||||
test_final_native_guard_rejects_changed_voice_before_send (test_protocol_voice.ProtocolVoiceTests.test_final_native_guard_rejects_changed_voice_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_human_reply_while_voice_pending_discards_old_question (test_protocol_voice.ProtocolVoiceTests.test_human_reply_while_voice_pending_discards_old_question) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
ok
|
||||
test_legacy_voice_draft_without_snapshot_regenerates_before_send (test_protocol_voice.ProtocolVoiceTests.test_legacy_voice_draft_without_snapshot_regenerates_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_missing_voice_times_out_without_global_stop_or_guess (test_protocol_voice.ProtocolVoiceTests.test_missing_voice_times_out_without_global_stop_or_guess) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音转文字等待超时,尚未取得可核验文字,请人工处理
|
||||
ok
|
||||
test_mixed_voice_and_text_waits_and_preserves_both (test_protocol_voice.ProtocolVoiceTests.test_mixed_voice_and_text_waits_and_preserves_both) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_media_after_voice_still_needs_manual (test_protocol_voice.ProtocolVoiceTests.test_new_media_after_voice_still_needs_manual) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update (test_protocol_voice.ProtocolVoiceTests.test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_same_voice_cache_changes_during_generation_discard_then_regenerate (test_protocol_voice.ProtocolVoiceTests.test_same_voice_cache_changes_during_generation_discard_then_regenerate) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_spoofed_or_cross_conversation_transcription_does_not_reach_model (test_protocol_voice.ProtocolVoiceTests.test_spoofed_or_cross_conversation_transcription_does_not_reach_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
ok
|
||||
test_transcribed_voice_reaches_model_and_selective_review_as_text (test_protocol_voice.ProtocolVoiceTests.test_transcribed_voice_reaches_model_and_selective_review_as_text) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 合成审核规则
|
||||
ok
|
||||
test_unknown_delivery_keeps_original_voice_draft_and_evidence (test_protocol_voice.ProtocolVoiceTests.test_unknown_delivery_keeps_original_voice_draft_and_evidence) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;合成未知回执
|
||||
ok
|
||||
test_database_wide_failure_propagates_without_healthy_claim_or_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_database_wide_failure_propagates_without_healthy_claim_or_send) ... ok
|
||||
test_explicit_pre_send_unavailable_stays_error_and_peers_continue (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_explicit_pre_send_unavailable_stays_error_and_peers_continue) ... ok
|
||||
test_foreign_account_task_cannot_send_while_current_account_continues (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_foreign_account_task_cannot_send_while_current_account_continues) ... ok
|
||||
test_generation_error_does_not_stop_another_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_generation_error_does_not_stop_another_conversation) ... ok
|
||||
test_malformed_message_row_does_not_drop_valid_rows (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_message_row_does_not_drop_valid_rows) ... ok
|
||||
test_malformed_task_timing_does_not_block_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_task_timing_does_not_block_peers) ... ok
|
||||
test_media_manual_handling_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_media_manual_handling_only_blocks_its_own_conversation) ... ok
|
||||
test_new_messages_and_contact_notices_cannot_replace_unknown_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_new_messages_and_contact_notices_cannot_replace_unknown_send) ... ok
|
||||
test_pending_review_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_pending_review_only_blocks_its_own_conversation) ... ok
|
||||
test_restart_keeps_unknown_and_failed_tasks_isolated (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_restart_keeps_unknown_and_failed_tasks_isolated) ... ok
|
||||
test_sending_persistence_error_preserves_no_replay_and_peer_processing (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_sending_persistence_error_preserves_no_replay_and_peer_processing) ... ok
|
||||
test_task_context_read_error_is_recorded_without_stopping_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_task_context_read_error_is_recorded_without_stopping_peers) ... ok
|
||||
test_unexpected_sender_exception_is_unknown_not_automatic_retry (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unexpected_sender_exception_is_unknown_not_automatic_retry) ... ok
|
||||
test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks) ... ok
|
||||
test_context_reloaded_for_generation_can_exclude_group (test_protocol_session_exclusions.ProtocolSessionExclusions.test_context_reloaded_for_generation_can_exclude_group) ... ok
|
||||
test_database_existing_direct_filter_rejects_group_before_content_read (test_protocol_session_exclusions.ProtocolSessionExclusions.test_database_existing_direct_filter_rejects_group_before_content_read) ... ok
|
||||
test_duplicate_excluded_event_does_not_rewrite_queue_or_repeat_log (test_protocol_session_exclusions.ProtocolSessionExclusions.test_duplicate_excluded_event_does_not_rewrite_queue_or_repeat_log) ... ok
|
||||
test_excluded_legacy_manual_or_error_tasks_are_removed_before_review (test_protocol_session_exclusions.ProtocolSessionExclusions.test_excluded_legacy_manual_or_error_tasks_are_removed_before_review) ... ok
|
||||
test_excluded_sessions_do_not_block_other_personal_session (test_protocol_session_exclusions.ProtocolSessionExclusions.test_excluded_sessions_do_not_block_other_personal_session) ... ok
|
||||
test_final_native_guard_cancels_then_clears_only_unsent_draft (test_protocol_session_exclusions.ProtocolSessionExclusions.test_final_native_guard_cancels_then_clears_only_unsent_draft) ... ok
|
||||
test_foreign_account_draft_is_never_cleared_by_current_account_policy (test_protocol_session_exclusions.ProtocolSessionExclusions.test_foreign_account_draft_is_never_cleared_by_current_account_policy) ... ok
|
||||
test_group_ids_and_structured_kinds_never_generate (test_protocol_session_exclusions.ProtocolSessionExclusions.test_group_ids_and_structured_kinds_never_generate) ... ok
|
||||
test_identity_changed_during_generation_drops_draft_before_review_or_send (test_protocol_session_exclusions.ProtocolSessionExclusions.test_identity_changed_during_generation_drops_draft_before_review_or_send) ... ok
|
||||
test_latest_context_identity_is_checked_before_generation (test_protocol_session_exclusions.ProtocolSessionExclusions.test_latest_context_identity_is_checked_before_generation) ... ok
|
||||
test_latest_last_message_metadata_is_checked_even_without_context_kind (test_protocol_session_exclusions.ProtocolSessionExclusions.test_latest_last_message_metadata_is_checked_even_without_context_kind) ... ok
|
||||
test_named_system_sessions_never_generate_or_enter_review (test_protocol_session_exclusions.ProtocolSessionExclusions.test_named_system_sessions_never_generate_or_enter_review) ... ok
|
||||
test_new_excluded_message_cannot_replace_unknown_send (test_protocol_session_exclusions.ProtocolSessionExclusions.test_new_excluded_message_cannot_replace_unknown_send) ... ok
|
||||
test_personal_message_mentions_of_groups_or_application_are_not_filtered (test_protocol_session_exclusions.ProtocolSessionExclusions.test_personal_message_mentions_of_groups_or_application_are_not_filtered) ... ok
|
||||
test_personal_name_containing_group_word_is_not_group_identity (test_protocol_session_exclusions.ProtocolSessionExclusions.test_personal_name_containing_group_word_is_not_group_identity) ... ok
|
||||
test_restart_discards_old_drafts_and_reviews_preserving_dedup (test_protocol_session_exclusions.ProtocolSessionExclusions.test_restart_discards_old_drafts_and_reviews_preserving_dedup) ... ok
|
||||
test_restart_keeps_attempted_delivery_evidence (test_protocol_session_exclusions.ProtocolSessionExclusions.test_restart_keeps_attempted_delivery_evidence) ... ok
|
||||
test_unknown_delivery_after_excluded_guard_preserves_evidence (test_protocol_session_exclusions.ProtocolSessionExclusions.test_unknown_delivery_after_excluded_guard_preserves_evidence) ... ok
|
||||
test_active_send_evidence_is_never_auto_completed (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_active_send_evidence_is_never_auto_completed) ... ok
|
||||
test_automated_outbound_does_not_complete_pending_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_automated_outbound_does_not_complete_pending_review) ... ok
|
||||
test_busy_send_lock_yields_without_error_then_sends_next_round (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_busy_send_lock_yields_without_error_then_sends_next_round) ... ok
|
||||
test_close_stops_coordinator (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_close_stops_coordinator) ... ok
|
||||
test_completion_save_failure_rolls_back_queue_and_can_retry (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_completion_save_failure_rolls_back_queue_and_can_retry) ... ok
|
||||
test_coordination_read_error_cannot_clear_a_registered_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_coordination_read_error_cannot_clear_a_registered_review) ... ok
|
||||
test_disabled_coordinator_cannot_override_global_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_disabled_coordinator_cannot_override_global_review) ... ok
|
||||
test_human_reply_completes_review_discards_draft_and_keeps_seen (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_human_reply_completes_review_discards_draft_and_keeps_seen) ... ok
|
||||
test_late_phone_sync_does_not_swallow_newer_already_queued_question (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_late_phone_sync_does_not_swallow_newer_already_queued_question) ... ok
|
||||
test_new_inbound_while_old_review_is_pending_keeps_review_and_new_draft (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_new_inbound_while_old_review_is_pending_keeps_review_and_new_draft) ... ok
|
||||
test_new_model_risk_still_requires_a_new_review_after_resumption (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_new_model_risk_still_requires_a_new_review_after_resumption) ... ok
|
||||
test_next_message_resumes_automatic_reply_despite_global_review_mode (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_next_message_resumes_automatic_reply_despite_global_review_mode) ... ok
|
||||
test_old_synced_outbound_and_missing_server_receipt_do_not_complete (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_old_synced_outbound_and_missing_server_receipt_do_not_complete) ... ok
|
||||
test_private_assistant_chat_is_never_auto_replied_to (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_private_assistant_chat_is_never_auto_replied_to) ... ok
|
||||
test_registers_one_review_with_persisted_id_and_trigger (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_registers_one_review_with_persisted_id_and_trigger) ... ok
|
||||
test_restart_reconciles_human_reply_then_keeps_subsequent_customer_message (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_restart_reconciles_human_reply_then_keeps_subsequent_customer_message) ... ok
|
||||
test_selective_review_always_precedes_resumed_global_mode (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_selective_review_always_precedes_resumed_global_mode) ... ok
|
||||
test_uncertain_send_releases_shared_lock_and_preserves_receipt_check (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_uncertain_send_releases_shared_lock_and_preserves_receipt_check) ... ok
|
||||
test_actual_store_late_phone_sync_preserves_newer_question (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_actual_store_late_phone_sync_preserves_newer_question) ... ok
|
||||
test_cancel_queue_save_failure_does_not_cancel_existing_review (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_queue_save_failure_does_not_cancel_existing_review) ... ok
|
||||
test_cancel_store_failure_retries_after_restart_before_new_question (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_store_failure_retries_after_restart_before_new_question) ... ok
|
||||
test_cancel_works_after_configuration_is_disabled (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_works_after_configuration_is_disabled) ... ok
|
||||
test_durable_completion_survives_protocol_save_failure_without_new_episode (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_durable_completion_survives_protocol_save_failure_without_new_episode) ... ok
|
||||
test_durable_manual_resolution_and_new_risk_get_distinct_episode (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_durable_manual_resolution_and_new_risk_get_distinct_episode) ... ok
|
||||
test_explicit_cancel_closes_old_reminder_without_auto_resume (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_explicit_cancel_closes_old_reminder_without_auto_resume) ... ok
|
||||
test_explicit_handoff_closes_reminder_and_preserves_evidence (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_explicit_handoff_closes_reminder_and_preserves_evidence) ... ok
|
||||
test_local_approval_closes_pending_without_future_global_review_bypass (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_local_approval_closes_pending_without_future_global_review_bypass) ... ok
|
||||
test_real_store_bot_receipt_is_not_a_manual_approval (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_real_store_bot_receipt_is_not_a_manual_approval) ... ok
|
||||
test_recovered_confirmed_local_approval_closes_old_reminder (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_recovered_confirmed_local_approval_closes_old_reminder) ... ok
|
||||
test_active_send_and_unresolved_receipt_phase_never_complete (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_active_send_and_unresolved_receipt_phase_never_complete) ... ok
|
||||
test_cancelled_manual_task_does_not_restore_global_auto_mode (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_cancelled_manual_task_does_not_restore_global_auto_mode) ... ok
|
||||
test_explicit_disabled_or_cancel_requested_tasks_are_not_resumed (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_explicit_disabled_or_cancel_requested_tasks_are_not_resumed) ... ok
|
||||
test_failed_send_can_finish_only_on_later_human_evidence (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_failed_send_can_finish_only_on_later_human_evidence) ... ok
|
||||
test_further_incoming_text_preserves_manual_episode_until_human_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_further_incoming_text_preserves_manual_episode_until_human_reply) ... ok
|
||||
test_generation_error_is_notified_and_human_answer_resolves_it (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_generation_error_is_notified_and_human_answer_resolves_it) ... ok
|
||||
test_late_human_sync_keeps_question_sent_after_that_human_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_late_human_sync_keeps_question_sent_after_that_human_reply) ... ok
|
||||
test_legacy_manual_task_with_exact_trigger_can_verify_reply_after_restart (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_legacy_manual_task_with_exact_trigger_can_verify_reply_after_restart) ... ok
|
||||
test_manual_customer_task_finishes_then_future_safe_message_resumes_auto (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_manual_customer_task_finishes_then_future_safe_message_resumes_auto) ... ok
|
||||
test_manual_media_registers_once_without_an_approvable_draft (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_manual_media_registers_once_without_an_approvable_draft) ... ok
|
||||
test_new_risk_after_manual_completion_creates_new_review_episode (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_new_risk_after_manual_completion_creates_new_review_episode) ... ok
|
||||
test_new_unknown_send_registers_manual_notification_then_only_human_finishes (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_new_unknown_send_registers_manual_notification_then_only_human_finishes) ... ok
|
||||
test_other_account_or_bot_outbound_does_not_finish_manual_task (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_other_account_or_bot_outbound_does_not_finish_manual_task) ... ok
|
||||
test_restart_preserves_manual_episode_and_completes_verified_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_restart_preserves_manual_episode_and_completes_verified_reply) ... ok
|
||||
test_terminal_completion_queue_save_failure_restores_evidence_before_retry (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_terminal_completion_queue_save_failure_restores_evidence_before_retry) ... ok
|
||||
test_terminal_unknown_is_completed_by_new_human_reply_without_replaying_or_altering_journal (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_terminal_unknown_is_completed_by_new_human_reply_without_replaying_or_altering_journal) ... ok
|
||||
test_unconfirmed_ai_draft_echo_cannot_be_used_as_manual_completion (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_unconfirmed_ai_draft_echo_cannot_be_used_as_manual_completion) ... ok
|
||||
test_foreign_account_task_cannot_be_approved_deleted_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_foreign_account_task_cannot_be_approved_deleted_or_retried) ... ok
|
||||
test_high_risk_reason_available_in_automatic_mode (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_high_risk_reason_available_in_automatic_mode) ... ok
|
||||
test_media_batch_is_visible_manual_work_without_approvable_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_media_batch_is_visible_manual_work_without_approvable_draft) ... ok
|
||||
test_next_valid_batch_discards_old_manual_requirement (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_next_valid_batch_discards_old_manual_requirement) ... ok
|
||||
test_old_saved_review_and_manual_tasks_restore_metadata_only (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_old_saved_review_and_manual_tasks_restore_metadata_only) ... ok
|
||||
test_overlong_batch_cannot_be_approved_as_a_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_overlong_batch_cannot_be_approved_as_a_draft) ... ok
|
||||
test_retry_clears_old_metadata_then_rechecks_media_without_sending (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_retry_clears_old_metadata_then_rechecks_media_without_sending) ... ok
|
||||
test_review_draft_reason_persists_then_explicit_approval_sends_once (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_review_draft_reason_persists_then_explicit_approval_sends_once) ... ok
|
||||
test_unknown_receipt_cannot_be_approved_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_unknown_receipt_cannot_be_approved_or_retried) ... ok
|
||||
test_cancelled_context_history_only_keeps_unanswered (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_cancelled_context_history_only_keeps_unanswered) ... ok
|
||||
test_context_enabled_retains_both_roles_and_unanswered_batch (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_context_enabled_retains_both_roles_and_unanswered_batch) ... ok
|
||||
test_exactly_100_unanswered_messages_preserve_every_part (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_exactly_100_unanswered_messages_preserve_every_part) ... ok
|
||||
test_existing_approved_draft_with_media_is_not_sent (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_existing_approved_draft_with_media_is_not_sent) ... ok
|
||||
test_image_then_related_text_stays_manual (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_image_then_related_text_stays_manual) ... ok
|
||||
test_old_media_before_own_reply_does_not_block_new_text (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_old_media_before_own_reply_does_not_block_new_text) ... ok
|
||||
test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail) ... ok
|
||||
test_own_reply_within_long_history_makes_current_batch_complete (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_own_reply_within_long_history_makes_current_batch_complete) ... ok
|
||||
test_restart_preserves_uncertain_conversation_and_processes_others (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_restart_preserves_uncertain_conversation_and_processes_others) ... ok
|
||||
test_unanswered_batch_not_lost_with_short_context_limit (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_unanswered_batch_not_lost_with_short_context_limit) ... ok
|
||||
test_uncertain_receipt_for_other_account_does_not_pause_current (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_uncertain_receipt_for_other_account_does_not_pause_current) ... ok
|
||||
test_context_refresh_observes_current_account_relation_wal (test_contact_relation_snapshot.ContactRelationTests.test_context_refresh_observes_current_account_relation_wal) ... ok
|
||||
test_deleted_or_blocklisted_is_never_active (test_contact_relation_snapshot.ContactRelationTests.test_deleted_or_blocklisted_is_never_active) ... ok
|
||||
test_encrypted_user_db_applies_wal_like_message_db (test_contact_relation_snapshot.ContactRelationTests.test_encrypted_user_db_applies_wal_like_message_db) ... ok
|
||||
test_exact_active_relation_retains_original_add_time (test_contact_relation_snapshot.ContactRelationTests.test_exact_active_relation_retains_original_add_time) ... ok
|
||||
test_group_self_and_other_account_conversation_are_unknown (test_contact_relation_snapshot.ContactRelationTests.test_group_self_and_other_account_conversation_are_unknown) ... ok
|
||||
test_missing_denial_table_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_denial_table_is_unknown) ... ok
|
||||
test_missing_or_duplicate_relation_is_unknown (test_contact_relation_snapshot.ContactRelationTests.test_missing_or_duplicate_relation_is_unknown) ... ok
|
||||
test_missing_path_does_not_create_database (test_contact_relation_snapshot.ContactRelationTests.test_missing_path_does_not_create_database) ... ok
|
||||
test_private_chat_identity_is_supported (test_contact_relation_snapshot.ContactRelationTests.test_private_chat_identity_is_supported) ... ok
|
||||
test_reader_only_uses_its_own_account_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_only_uses_its_own_account_snapshot) ... ok
|
||||
test_reader_rejects_foreign_cache_and_missing_snapshot (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_foreign_cache_and_missing_snapshot) ... ok
|
||||
test_reader_rejects_source_changed_before_or_during_read (test_contact_relation_snapshot.ContactRelationTests.test_reader_rejects_source_changed_before_or_during_read) ... ok
|
||||
test_relationship_wal_commits_multi_page_transaction_together (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_commits_multi_page_transaction_together) ... ok
|
||||
test_relationship_wal_ignores_uncommitted_tail (test_contact_relation_snapshot.ContactRelationTests.test_relationship_wal_ignores_uncommitted_tail) ... ok
|
||||
test_unknown_status_stranger_or_invalid_added_time_not_active (test_contact_relation_snapshot.ContactRelationTests.test_unknown_status_stranger_or_invalid_added_time_not_active) ... ok
|
||||
test_wal_only_relation_updates_are_observed (test_contact_relation_snapshot.ContactRelationTests.test_wal_only_relation_updates_are_observed) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
test_conflicting_event_or_live_identity_never_queries_another_account (test_voice_messages.VisualDatabaseBindingTests.test_conflicting_event_or_live_identity_never_queries_another_account) ... ok
|
||||
test_legacy_task_uses_bound_account_and_conversation_without_database_event (test_voice_messages.VisualDatabaseBindingTests.test_legacy_task_uses_bound_account_and_conversation_without_database_event) ... ok
|
||||
test_returned_foreign_account_is_rejected_even_if_reader_ignored_filter (test_voice_messages.VisualDatabaseBindingTests.test_returned_foreign_account_is_rejected_even_if_reader_ignored_filter) ... ok
|
||||
test_fails_asr_to_manual_and_ignores_other_conversation_snapshot (test_voice_messages.VisualVoiceTests.test_fails_asr_to_manual_and_ignores_other_conversation_snapshot) ... ok
|
||||
test_timeout_notifies_manual_instead_of_sending_guess (test_voice_messages.VisualVoiceTests.test_timeout_notifies_manual_instead_of_sending_guess) ... ok
|
||||
test_waits_without_manual_state_then_allows_transcribed_text (test_voice_messages.VisualVoiceTests.test_waits_without_manual_state_then_allows_transcribed_text) ... ok
|
||||
test_ambiguous_files_and_other_account_do_not_enqueue (test_voice_messages.VoiceDatabaseTests.test_ambiguous_files_and_other_account_do_not_enqueue) ... ok
|
||||
test_cache_collision_across_conversations_is_rejected (test_voice_messages.VoiceDatabaseTests.test_cache_collision_across_conversations_is_rejected) ... ok
|
||||
test_cache_index_is_background_and_does_not_hold_database_reader (test_voice_messages.VoiceDatabaseTests.test_cache_index_is_background_and_does_not_hold_database_reader) ... ok
|
||||
test_cache_update_on_same_message_becomes_visible_without_new_incoming (test_voice_messages.VoiceDatabaseTests.test_cache_update_on_same_message_becomes_visible_without_new_incoming) ... ok
|
||||
test_empty_asr_result_is_error_not_answer (test_voice_messages.VoiceDatabaseTests.test_empty_asr_result_is_error_not_answer) ... ok
|
||||
test_exact_current_account_path_enqueues_then_returns_transcript (test_voice_messages.VoiceDatabaseTests.test_exact_current_account_path_enqueues_then_returns_transcript) ... ok
|
||||
test_missing_table_and_empty_text_are_not_transcriptions (test_voice_messages.VoiceDatabaseTests.test_missing_table_and_empty_text_are_not_transcriptions) ... ok
|
||||
test_mixed_batch_waits_for_all_voices_and_rejects_foreign_binding (test_voice_messages.VoiceDatabaseTests.test_mixed_batch_waits_for_all_voices_and_rejects_foreign_binding) ... ok
|
||||
test_old_history_and_voice_before_human_reply_are_not_enqueued (test_voice_messages.VoiceDatabaseTests.test_old_history_and_voice_before_human_reply_are_not_enqueued) ... ok
|
||||
test_reads_server_id_cache_as_real_text_preserving_voice_type (test_voice_messages.VoiceDatabaseTests.test_reads_server_id_cache_as_real_text_preserving_voice_type) ... ok
|
||||
test_refresh_does_not_regress_ready_voice_during_slow_model_call (test_voice_messages.VoiceDatabaseTests.test_refresh_does_not_regress_ready_voice_during_slow_model_call) ... ok
|
||||
test_row_id_is_not_server_id_and_binary_payload_never_reaches_model (test_voice_messages.VoiceDatabaseTests.test_row_id_is_not_server_id_and_binary_payload_never_reaches_model) ... ok
|
||||
test_same_server_id_in_other_account_is_not_used (test_voice_messages.VoiceDatabaseTests.test_same_server_id_in_other_account_is_not_used) ... ok
|
||||
test_accounts_conversations_and_message_ids_do_not_share_results (test_voice_transcription.VoiceTranscriptionTests.test_accounts_conversations_and_message_ids_do_not_share_results) ... ok
|
||||
test_bad_header_is_not_sent_to_model (test_voice_transcription.VoiceTranscriptionTests.test_bad_header_is_not_sent_to_model) ... ok
|
||||
test_change_during_recognition_drops_old_result (test_voice_transcription.VoiceTranscriptionTests.test_change_during_recognition_drops_old_result) ... ok
|
||||
test_close_discards_text_and_stops_new_jobs (test_voice_transcription.VoiceTranscriptionTests.test_close_discards_text_and_stops_new_jobs) ... ok
|
||||
test_close_during_recognition_never_repopulates_cache (test_voice_transcription.VoiceTranscriptionTests.test_close_during_recognition_never_repopulates_cache) ... ok
|
||||
test_duration_limit_rejects_instead_of_truncating (test_voice_transcription.VoiceTranscriptionTests.test_duration_limit_rejects_instead_of_truncating) ... ok
|
||||
test_empty_recognition_never_becomes_ready (test_voice_transcription.VoiceTranscriptionTests.test_empty_recognition_never_becomes_ready) ... ok
|
||||
test_failed_job_retries_only_after_backoff (test_voice_transcription.VoiceTranscriptionTests.test_failed_job_retries_only_after_backoff) ... ok
|
||||
test_failures_back_off_and_do_not_leak_exception_details (test_voice_transcription.VoiceTranscriptionTests.test_failures_back_off_and_do_not_leak_exception_details) ... ok
|
||||
test_group_wrong_account_self_invalid_server_denied (test_voice_transcription.VoiceTranscriptionTests.test_group_wrong_account_self_invalid_server_denied) ... ok
|
||||
test_invalid_model_manifest_fails_without_network (test_voice_transcription.VoiceTranscriptionTests.test_invalid_model_manifest_fails_without_network) ... ok
|
||||
test_low_confidence_segment_is_rejected (test_voice_transcription.VoiceTranscriptionTests.test_low_confidence_segment_is_rejected) ... ok
|
||||
test_missing_allowed_root_rejected (test_voice_transcription.VoiceTranscriptionTests.test_missing_allowed_root_rejected) ... ok
|
||||
test_missing_file_has_readable_error_without_path (test_voice_transcription.VoiceTranscriptionTests.test_missing_file_has_readable_error_without_path) ... ok
|
||||
test_missing_model_fails_without_network (test_voice_transcription.VoiceTranscriptionTests.test_missing_model_fails_without_network) ... ok
|
||||
test_model_loading_is_forced_offline (test_voice_transcription.VoiceTranscriptionTests.test_model_loading_is_forced_offline) ... ok
|
||||
test_outside_root_rejected (test_voice_transcription.VoiceTranscriptionTests.test_outside_root_rejected) ... ok
|
||||
test_queue_is_bounded (test_voice_transcription.VoiceTranscriptionTests.test_queue_is_bounded) ... ok
|
||||
test_request_is_fast_while_worker_waits (test_voice_transcription.VoiceTranscriptionTests.test_request_is_fast_while_worker_waits) ... ok
|
||||
test_same_message_changed_audio_is_not_cached (test_voice_transcription.VoiceTranscriptionTests.test_same_message_changed_audio_is_not_cached) ... ok
|
||||
test_same_message_same_audio_is_recognized_once (test_voice_transcription.VoiceTranscriptionTests.test_same_message_same_audio_is_recognized_once) ... ok
|
||||
test_silence_is_not_sent_to_model (test_voice_transcription.VoiceTranscriptionTests.test_silence_is_not_sent_to_model) ... ok
|
||||
test_silk_pcm_output_limit_is_enforced (test_voice_transcription.VoiceTranscriptionTests.test_silk_pcm_output_limit_is_enforced) ... ok
|
||||
test_silk_real_decode_of_synthetic_pcm (test_voice_transcription.VoiceTranscriptionTests.test_silk_real_decode_of_synthetic_pcm) ... ok
|
||||
test_size_limit_prevents_worker (test_voice_transcription.VoiceTranscriptionTests.test_size_limit_prevents_worker) ... ok
|
||||
test_wav_transcribes_and_preserves_digest (test_voice_transcription.VoiceTranscriptionTests.test_wav_transcribes_and_preserves_digest) ... ok
|
||||
test_current_shadow_plan_releases_legacy_high_risk_once (test_review_policy_integration.ProtocolPolicyIntegration.test_current_shadow_plan_releases_legacy_high_risk_once) ... ok
|
||||
test_gateway_shadow_verdict_is_recorded_and_sent_without_approval (test_review_policy_integration.ProtocolPolicyIntegration.test_gateway_shadow_verdict_is_recorded_and_sent_without_approval) ... ok
|
||||
test_gateway_strict_verdict_overrides_stale_shadow_cache (test_review_policy_integration.ProtocolPolicyIntegration.test_gateway_strict_verdict_overrides_stale_shadow_cache) ... ok
|
||||
test_score_only_high_risk_still_requires_approval (test_review_policy_integration.ProtocolPolicyIntegration.test_score_only_high_risk_still_requires_approval) ... ok
|
||||
test_disabling_keyword_rule_releases_existing_draft (test_review_policy_integration.VisualPolicyIntegration.test_disabling_keyword_rule_releases_existing_draft) ... [待回复恢复] 已从磁盘恢复 1 个未完成任务。
|
||||
ok
|
||||
test_new_strict_verdict_overrides_old_shadow_config (test_review_policy_integration.VisualPolicyIntegration.test_new_strict_verdict_overrides_old_shadow_config) ... ok
|
||||
test_old_judge_callback_cannot_modify_new_turn (test_review_policy_integration.VisualPolicyIntegration.test_old_judge_callback_cannot_modify_new_turn) ... ok
|
||||
test_shadow_mode_survives_restart_and_releases_obsolete_review (test_review_policy_integration.VisualPolicyIntegration.test_shadow_mode_survives_restart_and_releases_obsolete_review) ... [待回复恢复] 已从磁盘恢复 1 个未完成任务。
|
||||
ok
|
||||
test_shadow_never_clears_unknown_receipt (test_review_policy_integration.VisualPolicyIntegration.test_shadow_never_clears_unknown_receipt) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 308 tests in 17.436s
|
||||
|
||||
OK
|
||||
@@ -1,360 +0,0 @@
|
||||
test_already_attempted_event_never_replayed_for_any_receipt_state (test_protocol_contact_recovery.ContactRecoveryTests.test_already_attempted_event_never_replayed_for_any_receipt_state) ... ok
|
||||
test_assistant_conversation_not_restored_as_auto_reply_target (test_protocol_contact_recovery.ContactRecoveryTests.test_assistant_conversation_not_restored_as_auto_reply_target) ... ok
|
||||
test_final_native_guard_can_recheck_its_own_inflight_journal (test_protocol_contact_recovery.ContactRecoveryTests.test_final_native_guard_can_recheck_its_own_inflight_journal) ... ok
|
||||
test_fresh_inbound_does_not_overwrite_manual_task_during_contact_recheck (test_protocol_contact_recovery.ContactRecoveryTests.test_fresh_inbound_does_not_overwrite_manual_task_during_contact_recheck) ... ok
|
||||
test_historical_contact_notice_cannot_erase_unknown_send_protection (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_contact_notice_cannot_erase_unknown_send_protection) ... ok
|
||||
test_historical_notice_without_saved_block_does_not_hide_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_notice_without_saved_block_does_not_hide_new_question) ... ok
|
||||
test_journal_read_failure_does_not_replay_seen_event (test_protocol_contact_recovery.ContactRecoveryTests.test_journal_read_failure_does_not_replay_seen_event) ... ok
|
||||
test_legacy_block_uses_exact_hash_and_account_not_name (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_block_uses_exact_hash_and_account_not_name) ... ok
|
||||
test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer) ... ok
|
||||
test_limit_two_backfills_and_five_second_throttle (test_protocol_contact_recovery.ContactRecoveryTests.test_limit_two_backfills_and_five_second_throttle) ... ok
|
||||
test_new_block_during_generation_invalidates_new_answer (test_protocol_contact_recovery.ContactRecoveryTests.test_new_block_during_generation_invalidates_new_answer) ... ok
|
||||
test_new_question_still_requires_fresh_review (test_protocol_contact_recovery.ContactRecoveryTests.test_new_question_still_requires_fresh_review) ... ok
|
||||
test_old_added_at_active_relation_rechecks_new_message_without_restore_notice (test_protocol_contact_recovery.ContactRecoveryTests.test_old_added_at_active_relation_rechecks_new_message_without_restore_notice) ... ok
|
||||
test_own_reply_after_block_prevents_unanswered_backfill (test_protocol_contact_recovery.ContactRecoveryTests.test_own_reply_after_block_prevents_unanswered_backfill) ... ok
|
||||
test_receiving_customer_text_alone_is_not_relationship_proof (test_protocol_contact_recovery.ContactRecoveryTests.test_receiving_customer_text_alone_is_not_relationship_proof) ... ok
|
||||
test_recovery_does_not_remove_existing_manual_or_uncertain_tasks (test_protocol_contact_recovery.ContactRecoveryTests.test_recovery_does_not_remove_existing_manual_or_uncertain_tasks) ... ok
|
||||
test_rejection_records_actual_source_and_later_new_question_can_recheck_once (test_protocol_contact_recovery.ContactRecoveryTests.test_rejection_records_actual_source_and_later_new_question_can_recheck_once) ... ok
|
||||
test_relation_change_during_generation_invalidates_reply (test_protocol_contact_recovery.ContactRecoveryTests.test_relation_change_during_generation_invalidates_reply) ... ok
|
||||
test_restart_keeps_failed_event_and_recovers_only_later_message (test_protocol_contact_recovery.ContactRecoveryTests.test_restart_keeps_failed_event_and_recovers_only_later_message) ... ok
|
||||
test_same_or_older_customer_anchor_is_not_new (test_protocol_contact_recovery.ContactRecoveryTests.test_same_or_older_customer_anchor_is_not_new) ... ok
|
||||
test_same_second_later_row_is_new_and_keeps_order (test_protocol_contact_recovery.ContactRecoveryTests.test_same_second_later_row_is_new_and_keeps_order) ... ok
|
||||
test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active (test_protocol_contact_recovery.ContactRecoveryTests.test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active) ... ok
|
||||
test_system_and_forged_direction_or_sender_are_not_new_customer_events (test_protocol_contact_recovery.ContactRecoveryTests.test_system_and_forged_direction_or_sender_are_not_new_customer_events) ... ok
|
||||
test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question) ... ok
|
||||
test_untranscribed_voice_waits_while_other_conversation_can_process (test_protocol_contact_recovery.ContactRecoveryTests.test_untranscribed_voice_waits_while_other_conversation_can_process) ... ok
|
||||
test_voice_new_question_is_transcribed_before_model_not_old_notice_manual (test_protocol_contact_recovery.ContactRecoveryTests.test_voice_new_question_is_transcribed_before_model_not_old_notice_manual) ... ok
|
||||
test_black_chat_quote_is_not_a_system_banner (test_contact_reply_guard.NoticeTests.test_black_chat_quote_is_not_a_system_banner) ... ok
|
||||
test_complete_notice_and_wrapped_ocr (test_contact_reply_guard.NoticeTests.test_complete_notice_and_wrapped_ocr) ... ok
|
||||
test_customer_quote_is_not_a_protocol_system_notice (test_contact_reply_guard.NoticeTests.test_customer_quote_is_not_a_protocol_system_notice) ... ok
|
||||
test_discussing_verification_or_single_failure_icon_is_not_evidence (test_contact_reply_guard.NoticeTests.test_discussing_verification_or_single_failure_icon_is_not_evidence) ... ok
|
||||
test_grey_centered_system_notice (test_contact_reply_guard.NoticeTests.test_grey_centered_system_notice) ... ok
|
||||
test_low_confidence_does_not_blacklist (test_contact_reply_guard.NoticeTests.test_low_confidence_does_not_blacklist) ... ok
|
||||
test_system_restoration_supersedes_old_restriction (test_contact_reply_guard.NoticeTests.test_system_restoration_supersedes_old_restriction) ... ok
|
||||
test_existing_system_notice_is_checked_before_generation (test_contact_reply_guard.ProtocolContactTests.test_existing_system_notice_is_checked_before_generation) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_failed_notice_lookup_keeps_unknown_send_protected (test_contact_reply_guard.ProtocolContactTests.test_failed_notice_lookup_keeps_unknown_send_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;callback timeout
|
||||
ok
|
||||
test_notice_arriving_during_generation_cancels_draft (test_contact_reply_guard.ProtocolContactTests.test_notice_arriving_during_generation_cancels_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_notice_blocks_one_chat_and_another_chat_still_sends (test_contact_reply_guard.ProtocolContactTests.test_notice_blocks_one_chat_and_another_chat_still_sends) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_other_send_failure_remains_protected (test_contact_reply_guard.ProtocolContactTests.test_other_send_failure_remains_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 客户端拒绝发送,需人工核对;network unavailable
|
||||
ok
|
||||
test_rejection_during_send_is_not_retried_after_restart (test_contact_reply_guard.ProtocolContactTests.test_rejection_during_send_is_not_retried_after_restart) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 该用户不是你的联系人;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 消息早于最近一次实际拒收,禁止重试旧问题
|
||||
ok
|
||||
test_restore_notice_allows_later_message (test_contact_reply_guard.ProtocolContactTests.test_restore_notice_allows_later_message) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_unknown_receipt_with_contact_notice_isolated_without_resending (test_contact_reply_guard.ProtocolContactTests.test_unknown_receipt_with_contact_notice_isolated_without_resending) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_user_quoting_notice_does_not_disable_chat (test_contact_reply_guard.ProtocolContactTests.test_user_quoting_notice_does_not_disable_chat) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_failed_outgoing_bubble_is_never_archived_as_success (test_contact_reply_guard.VisualSkipTests.test_failed_outgoing_bubble_is_never_archived_as_success) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_ocr_error_keeps_customer_task (test_contact_reply_guard.VisualSkipTests.test_ocr_error_keeps_customer_task) ... ok
|
||||
test_skip_clears_pending_and_uncommitted_exchange_then_persists (test_contact_reply_guard.VisualSkipTests.test_skip_clears_pending_and_uncommitted_exchange_then_persists) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_uncertain_send_with_rejection_skips_without_receipt_or_retry (test_contact_reply_guard.VisualSkipTests.test_uncertain_send_with_rejection_skips_without_receipt_or_retry) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_isolated_with_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_isolated_with_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_cache_change_keeps_independent_manual_block (test_protocol_voice.ProtocolVoiceTests.test_cache_change_keeps_independent_manual_block) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer (test_protocol_voice.ProtocolVoiceTests.test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_direct_judge_receives_entire_mixed_unanswered_batch (test_protocol_voice.ProtocolVoiceTests.test_direct_judge_receives_entire_mixed_unanswered_batch) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型裁判评估为高风险
|
||||
ok
|
||||
test_failed_transcription_enters_manual_and_never_calls_model (test_protocol_voice.ProtocolVoiceTests.test_failed_transcription_enters_manual_and_never_calls_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音自动转文字失败(empty_audio),请人工核对
|
||||
ok
|
||||
test_final_native_guard_rejects_changed_voice_before_send (test_protocol_voice.ProtocolVoiceTests.test_final_native_guard_rejects_changed_voice_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_human_reply_while_voice_pending_discards_old_question (test_protocol_voice.ProtocolVoiceTests.test_human_reply_while_voice_pending_discards_old_question) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
ok
|
||||
test_legacy_voice_draft_without_snapshot_regenerates_before_send (test_protocol_voice.ProtocolVoiceTests.test_legacy_voice_draft_without_snapshot_regenerates_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_missing_voice_times_out_without_global_stop_or_guess (test_protocol_voice.ProtocolVoiceTests.test_missing_voice_times_out_without_global_stop_or_guess) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音转文字等待超时,尚未取得可核验文字,请人工处理
|
||||
ok
|
||||
test_mixed_voice_and_text_waits_and_preserves_both (test_protocol_voice.ProtocolVoiceTests.test_mixed_voice_and_text_waits_and_preserves_both) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_media_after_voice_still_needs_manual (test_protocol_voice.ProtocolVoiceTests.test_new_media_after_voice_still_needs_manual) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update (test_protocol_voice.ProtocolVoiceTests.test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_same_voice_cache_changes_during_generation_discard_then_regenerate (test_protocol_voice.ProtocolVoiceTests.test_same_voice_cache_changes_during_generation_discard_then_regenerate) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_spoofed_or_cross_conversation_transcription_does_not_reach_model (test_protocol_voice.ProtocolVoiceTests.test_spoofed_or_cross_conversation_transcription_does_not_reach_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
ok
|
||||
test_transcribed_voice_reaches_model_and_selective_review_as_text (test_protocol_voice.ProtocolVoiceTests.test_transcribed_voice_reaches_model_and_selective_review_as_text) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 合成审核规则
|
||||
ok
|
||||
test_unknown_delivery_keeps_original_voice_draft_and_evidence (test_protocol_voice.ProtocolVoiceTests.test_unknown_delivery_keeps_original_voice_draft_and_evidence) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;合成未知回执
|
||||
ok
|
||||
test_database_wide_failure_propagates_without_healthy_claim_or_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_database_wide_failure_propagates_without_healthy_claim_or_send) ... ok
|
||||
test_explicit_pre_send_unavailable_stays_error_and_peers_continue (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_explicit_pre_send_unavailable_stays_error_and_peers_continue) ... ok
|
||||
test_foreign_account_task_cannot_send_while_current_account_continues (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_foreign_account_task_cannot_send_while_current_account_continues) ... ok
|
||||
test_generation_error_does_not_stop_another_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_generation_error_does_not_stop_another_conversation) ... ok
|
||||
test_malformed_message_row_does_not_drop_valid_rows (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_message_row_does_not_drop_valid_rows) ... ok
|
||||
test_malformed_task_timing_does_not_block_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_task_timing_does_not_block_peers) ... ok
|
||||
test_media_manual_handling_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_media_manual_handling_only_blocks_its_own_conversation) ... ok
|
||||
test_new_messages_and_contact_notices_cannot_replace_unknown_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_new_messages_and_contact_notices_cannot_replace_unknown_send) ... ok
|
||||
test_pending_review_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_pending_review_only_blocks_its_own_conversation) ... ok
|
||||
test_restart_keeps_unknown_and_failed_tasks_isolated (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_restart_keeps_unknown_and_failed_tasks_isolated) ... ok
|
||||
test_sending_persistence_error_preserves_no_replay_and_peer_processing (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_sending_persistence_error_preserves_no_replay_and_peer_processing) ... ok
|
||||
test_task_context_read_error_is_recorded_without_stopping_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_task_context_read_error_is_recorded_without_stopping_peers) ... ok
|
||||
test_unexpected_sender_exception_is_unknown_not_automatic_retry (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unexpected_sender_exception_is_unknown_not_automatic_retry) ... ok
|
||||
test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks) ... ok
|
||||
test_context_reloaded_for_generation_can_exclude_group (test_protocol_session_exclusions.ProtocolSessionExclusions.test_context_reloaded_for_generation_can_exclude_group) ... ok
|
||||
test_database_existing_direct_filter_rejects_group_before_content_read (test_protocol_session_exclusions.ProtocolSessionExclusions.test_database_existing_direct_filter_rejects_group_before_content_read) ... ok
|
||||
test_duplicate_excluded_event_does_not_rewrite_queue_or_repeat_log (test_protocol_session_exclusions.ProtocolSessionExclusions.test_duplicate_excluded_event_does_not_rewrite_queue_or_repeat_log) ... ok
|
||||
test_excluded_legacy_manual_or_error_tasks_are_removed_before_review (test_protocol_session_exclusions.ProtocolSessionExclusions.test_excluded_legacy_manual_or_error_tasks_are_removed_before_review) ... ok
|
||||
test_excluded_sessions_do_not_block_other_personal_session (test_protocol_session_exclusions.ProtocolSessionExclusions.test_excluded_sessions_do_not_block_other_personal_session) ... ok
|
||||
test_final_native_guard_cancels_then_clears_only_unsent_draft (test_protocol_session_exclusions.ProtocolSessionExclusions.test_final_native_guard_cancels_then_clears_only_unsent_draft) ... ok
|
||||
test_foreign_account_draft_is_never_cleared_by_current_account_policy (test_protocol_session_exclusions.ProtocolSessionExclusions.test_foreign_account_draft_is_never_cleared_by_current_account_policy) ... ok
|
||||
test_group_ids_and_structured_kinds_never_generate (test_protocol_session_exclusions.ProtocolSessionExclusions.test_group_ids_and_structured_kinds_never_generate) ... ok
|
||||
test_identity_changed_during_generation_drops_draft_before_review_or_send (test_protocol_session_exclusions.ProtocolSessionExclusions.test_identity_changed_during_generation_drops_draft_before_review_or_send) ... ok
|
||||
test_latest_context_identity_is_checked_before_generation (test_protocol_session_exclusions.ProtocolSessionExclusions.test_latest_context_identity_is_checked_before_generation) ... ok
|
||||
test_latest_last_message_metadata_is_checked_even_without_context_kind (test_protocol_session_exclusions.ProtocolSessionExclusions.test_latest_last_message_metadata_is_checked_even_without_context_kind) ... ok
|
||||
test_named_system_sessions_never_generate_or_enter_review (test_protocol_session_exclusions.ProtocolSessionExclusions.test_named_system_sessions_never_generate_or_enter_review) ... ok
|
||||
test_new_excluded_message_cannot_replace_unknown_send (test_protocol_session_exclusions.ProtocolSessionExclusions.test_new_excluded_message_cannot_replace_unknown_send) ... ok
|
||||
test_personal_message_mentions_of_groups_or_application_are_not_filtered (test_protocol_session_exclusions.ProtocolSessionExclusions.test_personal_message_mentions_of_groups_or_application_are_not_filtered) ... ok
|
||||
test_personal_name_containing_group_word_is_not_group_identity (test_protocol_session_exclusions.ProtocolSessionExclusions.test_personal_name_containing_group_word_is_not_group_identity) ... ok
|
||||
test_restart_discards_old_drafts_and_reviews_preserving_dedup (test_protocol_session_exclusions.ProtocolSessionExclusions.test_restart_discards_old_drafts_and_reviews_preserving_dedup) ... ok
|
||||
test_restart_keeps_attempted_delivery_evidence (test_protocol_session_exclusions.ProtocolSessionExclusions.test_restart_keeps_attempted_delivery_evidence) ... ok
|
||||
test_unknown_delivery_after_excluded_guard_preserves_evidence (test_protocol_session_exclusions.ProtocolSessionExclusions.test_unknown_delivery_after_excluded_guard_preserves_evidence) ... ok
|
||||
test_active_send_evidence_is_never_auto_completed (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_active_send_evidence_is_never_auto_completed) ... ok
|
||||
test_automated_outbound_does_not_complete_pending_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_automated_outbound_does_not_complete_pending_review) ... ok
|
||||
test_busy_send_lock_yields_without_error_then_sends_next_round (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_busy_send_lock_yields_without_error_then_sends_next_round) ... ok
|
||||
test_close_stops_coordinator (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_close_stops_coordinator) ... ok
|
||||
test_completion_save_failure_rolls_back_queue_and_can_retry (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_completion_save_failure_rolls_back_queue_and_can_retry) ... ok
|
||||
test_coordination_read_error_cannot_clear_a_registered_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_coordination_read_error_cannot_clear_a_registered_review) ... ok
|
||||
test_disabled_coordinator_cannot_override_global_review (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_disabled_coordinator_cannot_override_global_review) ... ok
|
||||
test_human_reply_completes_review_discards_draft_and_keeps_seen (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_human_reply_completes_review_discards_draft_and_keeps_seen) ... ok
|
||||
test_late_phone_sync_does_not_swallow_newer_already_queued_question (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_late_phone_sync_does_not_swallow_newer_already_queued_question) ... ok
|
||||
test_new_inbound_while_old_review_is_pending_keeps_review_and_new_draft (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_new_inbound_while_old_review_is_pending_keeps_review_and_new_draft) ... ok
|
||||
test_new_model_risk_still_requires_a_new_review_after_resumption (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_new_model_risk_still_requires_a_new_review_after_resumption) ... ok
|
||||
test_next_message_resumes_automatic_reply_despite_global_review_mode (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_next_message_resumes_automatic_reply_despite_global_review_mode) ... ok
|
||||
test_old_synced_outbound_and_missing_server_receipt_do_not_complete (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_old_synced_outbound_and_missing_server_receipt_do_not_complete) ... ok
|
||||
test_private_assistant_chat_is_never_auto_replied_to (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_private_assistant_chat_is_never_auto_replied_to) ... ok
|
||||
test_registers_one_review_with_persisted_id_and_trigger (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_registers_one_review_with_persisted_id_and_trigger) ... ok
|
||||
test_restart_reconciles_human_reply_then_keeps_subsequent_customer_message (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_restart_reconciles_human_reply_then_keeps_subsequent_customer_message) ... ok
|
||||
test_selective_review_always_precedes_resumed_global_mode (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_selective_review_always_precedes_resumed_global_mode) ... ok
|
||||
test_uncertain_send_releases_shared_lock_and_preserves_receipt_check (test_protocol_review_assistant.ProtocolReviewAssistantTests.test_uncertain_send_releases_shared_lock_and_preserves_receipt_check) ... ok
|
||||
test_actual_store_late_phone_sync_preserves_newer_question (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_actual_store_late_phone_sync_preserves_newer_question) ... ok
|
||||
test_cancel_queue_save_failure_does_not_cancel_existing_review (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_queue_save_failure_does_not_cancel_existing_review) ... ok
|
||||
test_cancel_store_failure_retries_after_restart_before_new_question (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_store_failure_retries_after_restart_before_new_question) ... ok
|
||||
test_cancel_works_after_configuration_is_disabled (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_cancel_works_after_configuration_is_disabled) ... ok
|
||||
test_durable_completion_survives_protocol_save_failure_without_new_episode (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_durable_completion_survives_protocol_save_failure_without_new_episode) ... ok
|
||||
test_durable_manual_resolution_and_new_risk_get_distinct_episode (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_durable_manual_resolution_and_new_risk_get_distinct_episode) ... ok
|
||||
test_explicit_cancel_closes_old_reminder_without_auto_resume (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_explicit_cancel_closes_old_reminder_without_auto_resume) ... ok
|
||||
test_explicit_handoff_closes_reminder_and_preserves_evidence (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_explicit_handoff_closes_reminder_and_preserves_evidence) ... ok
|
||||
test_local_approval_closes_pending_without_future_global_review_bypass (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_local_approval_closes_pending_without_future_global_review_bypass) ... ok
|
||||
test_real_store_bot_receipt_is_not_a_manual_approval (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_real_store_bot_receipt_is_not_a_manual_approval) ... ok
|
||||
test_recovered_confirmed_local_approval_closes_old_reminder (test_protocol_review_assistant.ProtocolSharedCoordinatorTests.test_recovered_confirmed_local_approval_closes_old_reminder) ... ok
|
||||
test_active_send_and_unresolved_receipt_phase_never_complete (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_active_send_and_unresolved_receipt_phase_never_complete) ... ok
|
||||
test_cancelled_manual_task_does_not_restore_global_auto_mode (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_cancelled_manual_task_does_not_restore_global_auto_mode) ... ok
|
||||
test_explicit_disabled_or_cancel_requested_tasks_are_not_resumed (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_explicit_disabled_or_cancel_requested_tasks_are_not_resumed) ... ok
|
||||
test_failed_send_can_finish_only_on_later_human_evidence (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_failed_send_can_finish_only_on_later_human_evidence) ... ok
|
||||
test_further_incoming_text_preserves_manual_episode_until_human_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_further_incoming_text_preserves_manual_episode_until_human_reply) ... ok
|
||||
test_generation_error_is_notified_and_human_answer_resolves_it (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_generation_error_is_notified_and_human_answer_resolves_it) ... ok
|
||||
test_late_human_sync_keeps_question_sent_after_that_human_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_late_human_sync_keeps_question_sent_after_that_human_reply) ... ok
|
||||
test_legacy_manual_task_with_exact_trigger_can_verify_reply_after_restart (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_legacy_manual_task_with_exact_trigger_can_verify_reply_after_restart) ... ok
|
||||
test_manual_customer_task_finishes_then_future_safe_message_resumes_auto (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_manual_customer_task_finishes_then_future_safe_message_resumes_auto) ... ok
|
||||
test_manual_media_registers_once_without_an_approvable_draft (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_manual_media_registers_once_without_an_approvable_draft) ... ok
|
||||
test_new_risk_after_manual_completion_creates_new_review_episode (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_new_risk_after_manual_completion_creates_new_review_episode) ... ok
|
||||
test_new_unknown_send_registers_manual_notification_then_only_human_finishes (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_new_unknown_send_registers_manual_notification_then_only_human_finishes) ... ok
|
||||
test_other_account_or_bot_outbound_does_not_finish_manual_task (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_other_account_or_bot_outbound_does_not_finish_manual_task) ... ok
|
||||
test_restart_preserves_manual_episode_and_completes_verified_reply (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_restart_preserves_manual_episode_and_completes_verified_reply) ... ok
|
||||
test_terminal_completion_queue_save_failure_restores_evidence_before_retry (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_terminal_completion_queue_save_failure_restores_evidence_before_retry) ... ok
|
||||
test_terminal_unknown_is_completed_by_new_human_reply_without_replaying_or_altering_journal (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_terminal_unknown_is_completed_by_new_human_reply_without_replaying_or_altering_journal) ... ok
|
||||
test_unconfirmed_ai_draft_echo_cannot_be_used_as_manual_completion (test_protocol_manual_assistant.ProtocolManualAssistantTests.test_unconfirmed_ai_draft_echo_cannot_be_used_as_manual_completion) ... ok
|
||||
test_foreign_account_task_cannot_be_approved_deleted_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_foreign_account_task_cannot_be_approved_deleted_or_retried) ... ok
|
||||
test_high_risk_reason_available_in_automatic_mode (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_high_risk_reason_available_in_automatic_mode) ... ok
|
||||
test_media_batch_is_visible_manual_work_without_approvable_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_media_batch_is_visible_manual_work_without_approvable_draft) ... ok
|
||||
test_next_valid_batch_discards_old_manual_requirement (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_next_valid_batch_discards_old_manual_requirement) ... ok
|
||||
test_old_saved_review_and_manual_tasks_restore_metadata_only (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_old_saved_review_and_manual_tasks_restore_metadata_only) ... ok
|
||||
test_overlong_batch_cannot_be_approved_as_a_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_overlong_batch_cannot_be_approved_as_a_draft) ... ok
|
||||
test_retry_clears_old_metadata_then_rechecks_media_without_sending (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_retry_clears_old_metadata_then_rechecks_media_without_sending) ... ok
|
||||
test_review_draft_reason_persists_then_explicit_approval_sends_once (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_review_draft_reason_persists_then_explicit_approval_sends_once) ... ok
|
||||
test_unknown_receipt_cannot_be_approved_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_unknown_receipt_cannot_be_approved_or_retried) ... ok
|
||||
test_cancelled_context_history_only_keeps_unanswered (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_cancelled_context_history_only_keeps_unanswered) ... ok
|
||||
test_context_enabled_retains_both_roles_and_unanswered_batch (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_context_enabled_retains_both_roles_and_unanswered_batch) ... ok
|
||||
test_exactly_100_unanswered_messages_preserve_every_part (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_exactly_100_unanswered_messages_preserve_every_part) ... ok
|
||||
test_existing_approved_draft_with_media_is_not_sent (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_existing_approved_draft_with_media_is_not_sent) ... ok
|
||||
test_image_then_related_text_stays_manual (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_image_then_related_text_stays_manual) ... ok
|
||||
test_old_media_before_own_reply_does_not_block_new_text (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_old_media_before_own_reply_does_not_block_new_text) ... ok
|
||||
test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail) ... ok
|
||||
test_own_reply_within_long_history_makes_current_batch_complete (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_own_reply_within_long_history_makes_current_batch_complete) ... ok
|
||||
test_restart_preserves_uncertain_conversation_and_processes_others (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_restart_preserves_uncertain_conversation_and_processes_others) ... ok
|
||||
test_unanswered_batch_not_lost_with_short_context_limit (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_unanswered_batch_not_lost_with_short_context_limit) ... ok
|
||||
test_uncertain_receipt_for_other_account_does_not_pause_current (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_uncertain_receipt_for_other_account_does_not_pause_current) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 194 tests in 9.165s
|
||||
|
||||
OK
|
||||
@@ -1,275 +0,0 @@
|
||||
test_already_attempted_event_never_replayed_for_any_receipt_state (test_protocol_contact_recovery.ContactRecoveryTests.test_already_attempted_event_never_replayed_for_any_receipt_state) ... ok
|
||||
test_assistant_conversation_not_restored_as_auto_reply_target (test_protocol_contact_recovery.ContactRecoveryTests.test_assistant_conversation_not_restored_as_auto_reply_target) ... ok
|
||||
test_final_native_guard_can_recheck_its_own_inflight_journal (test_protocol_contact_recovery.ContactRecoveryTests.test_final_native_guard_can_recheck_its_own_inflight_journal) ... ok
|
||||
test_historical_contact_notice_cannot_erase_unknown_send_protection (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_contact_notice_cannot_erase_unknown_send_protection) ... ok
|
||||
test_historical_notice_without_saved_block_does_not_hide_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_historical_notice_without_saved_block_does_not_hide_new_question) ... ok
|
||||
test_journal_read_failure_does_not_replay_seen_event (test_protocol_contact_recovery.ContactRecoveryTests.test_journal_read_failure_does_not_replay_seen_event) ... ok
|
||||
test_legacy_block_uses_exact_hash_and_account_not_name (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_block_uses_exact_hash_and_account_not_name) ... ok
|
||||
test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer (test_protocol_contact_recovery.ContactRecoveryTests.test_legacy_float_and_seen_swallow_are_recovered_without_restarting_customer) ... ok
|
||||
test_limit_two_backfills_and_five_second_throttle (test_protocol_contact_recovery.ContactRecoveryTests.test_limit_two_backfills_and_five_second_throttle) ... ok
|
||||
test_new_block_during_generation_invalidates_new_answer (test_protocol_contact_recovery.ContactRecoveryTests.test_new_block_during_generation_invalidates_new_answer) ... ok
|
||||
test_new_question_still_requires_fresh_review (test_protocol_contact_recovery.ContactRecoveryTests.test_new_question_still_requires_fresh_review) ... ok
|
||||
test_old_added_at_active_relation_rechecks_new_message_without_restore_notice (test_protocol_contact_recovery.ContactRecoveryTests.test_old_added_at_active_relation_rechecks_new_message_without_restore_notice) ... ok
|
||||
test_own_reply_after_block_prevents_unanswered_backfill (test_protocol_contact_recovery.ContactRecoveryTests.test_own_reply_after_block_prevents_unanswered_backfill) ... ok
|
||||
test_receiving_customer_text_alone_is_not_relationship_proof (test_protocol_contact_recovery.ContactRecoveryTests.test_receiving_customer_text_alone_is_not_relationship_proof) ... ok
|
||||
test_recovery_does_not_remove_existing_manual_or_uncertain_tasks (test_protocol_contact_recovery.ContactRecoveryTests.test_recovery_does_not_remove_existing_manual_or_uncertain_tasks) ... ok
|
||||
test_rejection_records_actual_source_and_later_new_question_can_recheck_once (test_protocol_contact_recovery.ContactRecoveryTests.test_rejection_records_actual_source_and_later_new_question_can_recheck_once) ... ok
|
||||
test_relation_change_during_generation_invalidates_reply (test_protocol_contact_recovery.ContactRecoveryTests.test_relation_change_during_generation_invalidates_reply) ... ok
|
||||
test_restart_keeps_failed_event_and_recovers_only_later_message (test_protocol_contact_recovery.ContactRecoveryTests.test_restart_keeps_failed_event_and_recovers_only_later_message) ... ok
|
||||
test_same_or_older_customer_anchor_is_not_new (test_protocol_contact_recovery.ContactRecoveryTests.test_same_or_older_customer_anchor_is_not_new) ... ok
|
||||
test_same_second_later_row_is_new_and_keeps_order (test_protocol_contact_recovery.ContactRecoveryTests.test_same_second_later_row_is_new_and_keeps_order) ... ok
|
||||
test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active (test_protocol_contact_recovery.ContactRecoveryTests.test_structured_blocked_seen_event_is_recovered_when_relation_becomes_active) ... ok
|
||||
test_system_and_forged_direction_or_sender_are_not_new_customer_events (test_protocol_contact_recovery.ContactRecoveryTests.test_system_and_forged_direction_or_sender_are_not_new_customer_events) ... ok
|
||||
test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question (test_protocol_contact_recovery.ContactRecoveryTests.test_unknown_blocked_or_cross_identity_relation_does_not_enable_new_question) ... ok
|
||||
test_untranscribed_voice_waits_while_other_conversation_can_process (test_protocol_contact_recovery.ContactRecoveryTests.test_untranscribed_voice_waits_while_other_conversation_can_process) ... ok
|
||||
test_voice_new_question_is_transcribed_before_model_not_old_notice_manual (test_protocol_contact_recovery.ContactRecoveryTests.test_voice_new_question_is_transcribed_before_model_not_old_notice_manual) ... ok
|
||||
test_black_chat_quote_is_not_a_system_banner (test_contact_reply_guard.NoticeTests.test_black_chat_quote_is_not_a_system_banner) ... ok
|
||||
test_complete_notice_and_wrapped_ocr (test_contact_reply_guard.NoticeTests.test_complete_notice_and_wrapped_ocr) ... ok
|
||||
test_customer_quote_is_not_a_protocol_system_notice (test_contact_reply_guard.NoticeTests.test_customer_quote_is_not_a_protocol_system_notice) ... ok
|
||||
test_discussing_verification_or_single_failure_icon_is_not_evidence (test_contact_reply_guard.NoticeTests.test_discussing_verification_or_single_failure_icon_is_not_evidence) ... ok
|
||||
test_grey_centered_system_notice (test_contact_reply_guard.NoticeTests.test_grey_centered_system_notice) ... ok
|
||||
test_low_confidence_does_not_blacklist (test_contact_reply_guard.NoticeTests.test_low_confidence_does_not_blacklist) ... ok
|
||||
test_system_restoration_supersedes_old_restriction (test_contact_reply_guard.NoticeTests.test_system_restoration_supersedes_old_restriction) ... ok
|
||||
test_existing_system_notice_is_checked_before_generation (test_contact_reply_guard.ProtocolContactTests.test_existing_system_notice_is_checked_before_generation) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_failed_notice_lookup_keeps_unknown_send_protected (test_contact_reply_guard.ProtocolContactTests.test_failed_notice_lookup_keeps_unknown_send_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;callback timeout
|
||||
ok
|
||||
test_notice_arriving_during_generation_cancels_draft (test_contact_reply_guard.ProtocolContactTests.test_notice_arriving_during_generation_cancels_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_notice_blocks_one_chat_and_another_chat_still_sends (test_contact_reply_guard.ProtocolContactTests.test_notice_blocks_one_chat_and_another_chat_still_sends) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 当前账号客户关系尚未核验为有效
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_other_send_failure_remains_protected (test_contact_reply_guard.ProtocolContactTests.test_other_send_failure_remains_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 客户端拒绝发送,需人工核对;network unavailable
|
||||
ok
|
||||
test_rejection_during_send_is_not_retried_after_restart (test_contact_reply_guard.ProtocolContactTests.test_rejection_during_send_is_not_retried_after_restart) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 该用户不是你的联系人;继续监听,新的客户消息将重新核验
|
||||
[协议联系人核验] 同名客户 · 消息早于最近一次实际拒收,禁止重试旧问题
|
||||
ok
|
||||
test_restore_notice_allows_later_message (test_contact_reply_guard.ProtocolContactTests.test_restore_notice_allows_later_message) ... [协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_unknown_receipt_with_contact_notice_isolated_without_resending (test_contact_reply_guard.ProtocolContactTests.test_unknown_receipt_with_contact_notice_isolated_without_resending) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议联系人核验] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复;继续监听,新的客户消息将重新核验
|
||||
ok
|
||||
test_user_quoting_notice_does_not_disable_chat (test_contact_reply_guard.ProtocolContactTests.test_user_quoting_notice_does_not_disable_chat) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_failed_outgoing_bubble_is_never_archived_as_success (test_contact_reply_guard.VisualSkipTests.test_failed_outgoing_bubble_is_never_archived_as_success) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_ocr_error_keeps_customer_task (test_contact_reply_guard.VisualSkipTests.test_ocr_error_keeps_customer_task) ... ok
|
||||
test_skip_clears_pending_and_uncommitted_exchange_then_persists (test_contact_reply_guard.VisualSkipTests.test_skip_clears_pending_and_uncommitted_exchange_then_persists) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_uncertain_send_with_rejection_skips_without_receipt_or_retry (test_contact_reply_guard.VisualSkipTests.test_uncertain_send_with_rejection_skips_without_receipt_or_retry) ... [会话过滤] 对方开启联系人验证,当前不是联系人,已跳过自动回复;6 小时后重新检查会话状态。
|
||||
ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_isolated_with_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_isolated_with_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_cache_change_keeps_independent_manual_block (test_protocol_voice.ProtocolVoiceTests.test_cache_change_keeps_independent_manual_block) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer (test_protocol_voice.ProtocolVoiceTests.test_changed_voice_revokes_approval_and_rechecks_review_on_new_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_direct_judge_receives_entire_mixed_unanswered_batch (test_protocol_voice.ProtocolVoiceTests.test_direct_judge_receives_entire_mixed_unanswered_batch) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型裁判评估为高风险
|
||||
ok
|
||||
test_failed_transcription_enters_manual_and_never_calls_model (test_protocol_voice.ProtocolVoiceTests.test_failed_transcription_enters_manual_and_never_calls_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音自动转文字失败(empty_audio),请人工核对
|
||||
ok
|
||||
test_final_native_guard_rejects_changed_voice_before_send (test_protocol_voice.ProtocolVoiceTests.test_final_native_guard_rejects_changed_voice_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_human_reply_while_voice_pending_discards_old_question (test_protocol_voice.ProtocolVoiceTests.test_human_reply_while_voice_pending_discards_old_question) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
ok
|
||||
test_legacy_voice_draft_without_snapshot_regenerates_before_send (test_protocol_voice.ProtocolVoiceTests.test_legacy_voice_draft_without_snapshot_regenerates_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_missing_voice_times_out_without_global_stop_or_guess (test_protocol_voice.ProtocolVoiceTests.test_missing_voice_times_out_without_global_stop_or_guess) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;语音转文字等待超时,尚未取得可核验文字,请人工处理
|
||||
ok
|
||||
test_mixed_voice_and_text_waits_and_preserves_both (test_protocol_voice.ProtocolVoiceTests.test_mixed_voice_and_text_waits_and_preserves_both) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_media_after_voice_still_needs_manual (test_protocol_voice.ProtocolVoiceTests.test_new_media_after_voice_still_needs_manual) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update (test_protocol_voice.ProtocolVoiceTests.test_pending_voice_delays_only_its_conversation_then_resumes_on_cache_update) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 语音正在本机转文字
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_same_voice_cache_changes_during_generation_discard_then_regenerate (test_protocol_voice.ProtocolVoiceTests.test_same_voice_cache_changes_during_generation_discard_then_regenerate) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_spoofed_or_cross_conversation_transcription_does_not_reach_model (test_protocol_voice.ProtocolVoiceTests.test_spoofed_or_cross_conversation_transcription_does_not_reach_model) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 等待企业微信语音文件或转写缓存
|
||||
ok
|
||||
test_transcribed_voice_reaches_model_and_selective_review_as_text (test_protocol_voice.ProtocolVoiceTests.test_transcribed_voice_reaches_model_and_selective_review_as_text) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 合成审核规则
|
||||
ok
|
||||
test_unknown_delivery_keeps_original_voice_draft_and_evidence (test_protocol_voice.ProtocolVoiceTests.test_unknown_delivery_keeps_original_voice_draft_and_evidence) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;合成未知回执
|
||||
ok
|
||||
test_database_wide_failure_propagates_without_healthy_claim_or_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_database_wide_failure_propagates_without_healthy_claim_or_send) ... ok
|
||||
test_explicit_pre_send_unavailable_stays_error_and_peers_continue (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_explicit_pre_send_unavailable_stays_error_and_peers_continue) ... ok
|
||||
test_foreign_account_task_cannot_send_while_current_account_continues (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_foreign_account_task_cannot_send_while_current_account_continues) ... ok
|
||||
test_generation_error_does_not_stop_another_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_generation_error_does_not_stop_another_conversation) ... ok
|
||||
test_malformed_message_row_does_not_drop_valid_rows (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_message_row_does_not_drop_valid_rows) ... ok
|
||||
test_malformed_task_timing_does_not_block_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_task_timing_does_not_block_peers) ... ok
|
||||
test_media_manual_handling_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_media_manual_handling_only_blocks_its_own_conversation) ... ok
|
||||
test_new_messages_and_contact_notices_cannot_replace_unknown_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_new_messages_and_contact_notices_cannot_replace_unknown_send) ... ok
|
||||
test_pending_review_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_pending_review_only_blocks_its_own_conversation) ... ok
|
||||
test_restart_keeps_unknown_and_failed_tasks_isolated (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_restart_keeps_unknown_and_failed_tasks_isolated) ... ok
|
||||
test_sending_persistence_error_preserves_no_replay_and_peer_processing (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_sending_persistence_error_preserves_no_replay_and_peer_processing) ... ok
|
||||
test_task_context_read_error_is_recorded_without_stopping_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_task_context_read_error_is_recorded_without_stopping_peers) ... ok
|
||||
test_unexpected_sender_exception_is_unknown_not_automatic_retry (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unexpected_sender_exception_is_unknown_not_automatic_retry) ... ok
|
||||
test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 109 tests in 3.976s
|
||||
|
||||
OK
|
||||
@@ -1,95 +0,0 @@
|
||||
test_absent_optional_phone_tables_do_not_affect_customer_list (test_review_assistant_contacts.ContactDirectoryTest.test_absent_optional_phone_tables_do_not_affect_customer_list) ... ok
|
||||
test_blocked_session_is_not_a_selectable_target (test_review_assistant_contacts.ContactDirectoryTest.test_blocked_session_is_not_a_selectable_target) ... ok
|
||||
test_both_s_id_orders_are_supported_but_no_address_is_synthesized (test_review_assistant_contacts.ContactDirectoryTest.test_both_s_id_orders_are_supported_but_no_address_is_synthesized) ... ok
|
||||
test_customer_remarks_precede_true_remarks_and_user_names_and_all_are_searchable (test_review_assistant_contacts.ContactDirectoryTest.test_customer_remarks_precede_true_remarks_and_user_names_and_all_are_searchable) ... ok
|
||||
test_default_roots_include_protocol_cache_before_archived_copy (test_review_assistant_contacts.ContactDirectoryTest.test_default_roots_include_protocol_cache_before_archived_copy) ... ok
|
||||
test_deleted_blacklisted_and_internal_users_are_excluded (test_review_assistant_contacts.ContactDirectoryTest.test_deleted_blacklisted_and_internal_users_are_excluded) ... ok
|
||||
test_existing_wecom_and_wechat_targets_keep_exact_identity_and_kind (test_review_assistant_contacts.ContactDirectoryTest.test_existing_wecom_and_wechat_targets_keep_exact_identity_and_kind) ... ok
|
||||
test_fresh_validation_bypasses_cached_membership_and_rechecks_account (test_review_assistant_contacts.ContactDirectoryTest.test_fresh_validation_bypasses_cached_membership_and_rechecks_account) ... ok
|
||||
test_latest_wal_revision_wins_between_account_caches (test_review_assistant_contacts.ContactDirectoryTest.test_latest_wal_revision_wins_between_account_caches) ... ok
|
||||
test_lookup_does_not_change_database_files_or_read_sensitive_columns (test_review_assistant_contacts.ContactDirectoryTest.test_lookup_does_not_change_database_files_or_read_sensitive_columns) ... ok
|
||||
test_missing_or_incomplete_customer_relation_table_fails_closed (test_review_assistant_contacts.ContactDirectoryTest.test_missing_or_incomplete_customer_relation_table_fails_closed) ... ok
|
||||
test_missing_user_database_returns_clear_failure_not_keyerror (test_review_assistant_contacts.ContactDirectoryTest.test_missing_user_database_returns_clear_failure_not_keyerror) ... ok
|
||||
test_no_conversation_customer_is_visible_but_cannot_be_selected (test_review_assistant_contacts.ContactDirectoryTest.test_no_conversation_customer_is_visible_but_cannot_be_selected) ... ok
|
||||
test_no_message_cache_lists_customers_pending_without_fake_targets (test_review_assistant_contacts.ContactDirectoryTest.test_no_message_cache_lists_customers_pending_without_fake_targets) ... ok
|
||||
test_only_my_customer_relationships_are_listed_not_phone_contacts_or_arbitrary_chats (test_review_assistant_contacts.ContactDirectoryTest.test_only_my_customer_relationships_are_listed_not_phone_contacts_or_arbitrary_chats) ... ok
|
||||
test_other_account_directory_is_never_read (test_review_assistant_contacts.ContactDirectoryTest.test_other_account_directory_is_never_read) ... ok
|
||||
test_refresh_invalidates_cache_for_new_customer_relationship (test_review_assistant_contacts.ContactDirectoryTest.test_refresh_invalidates_cache_for_new_customer_relationship) ... ok
|
||||
test_same_name_customers_remain_separate_and_pagination_is_after_filter (test_review_assistant_contacts.ContactDirectoryTest.test_same_name_customers_remain_separate_and_pagination_is_after_filter) ... ok
|
||||
test_strangers_unadded_self_and_invalid_uids_are_not_my_customers (test_review_assistant_contacts.ContactDirectoryTest.test_strangers_unadded_self_and_invalid_uids_are_not_my_customers) ... ok
|
||||
test_system_customer_names_and_session_metadata_cannot_enable_sends (test_review_assistant_contacts.ContactDirectoryTest.test_system_customer_names_and_session_metadata_cannot_enable_sends) ... ok
|
||||
test_unknown_name_does_not_become_fake_nickname_or_raw_s_identifier (test_review_assistant_contacts.ContactDirectoryTest.test_unknown_name_does_not_become_fake_nickname_or_raw_s_identifier) ... ok
|
||||
test_unknown_relation_status_is_visible_but_cannot_be_selected (test_review_assistant_contacts.ContactDirectoryTest.test_unknown_relation_status_is_visible_but_cannot_be_selected) ... ok
|
||||
test_wal_change_invalidates_customer_relationship_cache (test_review_assistant_contacts.ContactDirectoryTest.test_wal_change_invalidates_customer_relationship_cache) ... ok
|
||||
test_only_exact_account_bound_direct_ids_are_accepted (test_review_assistant_contacts.RecipientPeerTest.test_only_exact_account_bound_direct_ids_are_accepted) ... ok
|
||||
test_account_mismatch_never_reads_the_old_accounts_database (test_review_assistant_ui.ReminderContactTest.test_account_mismatch_never_reads_the_old_accounts_database) ... ok
|
||||
test_account_switch_during_validation_rejects_selection (test_review_assistant_ui.ReminderContactTest.test_account_switch_during_validation_rejects_selection) ... ok
|
||||
test_duplicate_names_remain_separate_and_identifiable (test_review_assistant_ui.ReminderContactTest.test_duplicate_names_remain_separate_and_identifiable) ... ok
|
||||
test_group_internal_or_unknown_recipient_cannot_be_saved (test_review_assistant_ui.ReminderContactTest.test_group_internal_or_unknown_recipient_cannot_be_saved) ... ok
|
||||
test_lists_relation_customers_with_s_and_m_chats_without_message_content (test_review_assistant_ui.ReminderContactTest.test_lists_relation_customers_with_s_and_m_chats_without_message_content) ... ok
|
||||
test_missing_account_does_not_fall_back_to_another_account (test_review_assistant_ui.ReminderContactTest.test_missing_account_does_not_fall_back_to_another_account) ... ok
|
||||
test_preview_is_static_and_does_not_load_real_customer_data (test_review_assistant_ui.ReminderContactTest.test_preview_is_static_and_does_not_load_real_customer_data) ... ok
|
||||
test_queries_are_read_only_and_do_not_initialize_or_modify_databases (test_review_assistant_ui.ReminderContactTest.test_queries_are_read_only_and_do_not_initialize_or_modify_databases) ... ok
|
||||
test_recipient_validation_uses_id_and_rechecks_identity (test_review_assistant_ui.ReminderContactTest.test_recipient_validation_uses_id_and_rechecks_identity) ... ok
|
||||
test_search_and_pagination_are_independent_of_message_preview (test_review_assistant_ui.ReminderContactTest.test_search_and_pagination_are_independent_of_message_preview) ... ok
|
||||
test_active_identity_only_uses_native_readonly_scope (test_review_assistant_ui.ReminderIdentityTest.test_active_identity_only_uses_native_readonly_scope) ... ok
|
||||
test_native_unavailable_is_clear_and_does_not_use_another_account (test_review_assistant_ui.ReminderIdentityTest.test_native_unavailable_is_clear_and_does_not_use_another_account) ... ok
|
||||
test_refresh_cannot_race_pending_recipient_validation (test_review_assistant_ui.ReminderPickerTest.test_refresh_cannot_race_pending_recipient_validation) ... ok
|
||||
test_refresh_remains_available_after_account_or_cache_error (test_review_assistant_ui.ReminderPickerTest.test_refresh_remains_available_after_account_or_cache_error) ... ok
|
||||
test_refresh_rereads_cached_list_and_preserves_query_from_first_page (test_review_assistant_ui.ReminderPickerTest.test_refresh_rereads_cached_list_and_preserves_query_from_first_page) ... ok
|
||||
test_same_name_rows_keep_exact_identity_and_validate_selected_one (test_review_assistant_ui.ReminderPickerTest.test_same_name_rows_keep_exact_identity_and_validate_selected_one) ... ok
|
||||
test_stale_list_and_late_validation_after_cancel_are_ignored (test_review_assistant_ui.ReminderPickerTest.test_stale_list_and_late_validation_after_cancel_are_ignored) ... ok
|
||||
test_stale_validation_result_cannot_accept_after_a_newer_request (test_review_assistant_ui.ReminderPickerTest.test_stale_validation_result_cannot_accept_after_a_newer_request) ... ok
|
||||
test_unmapped_contact_is_visible_but_cannot_be_accepted (test_review_assistant_ui.ReminderPickerTest.test_unmapped_contact_is_visible_but_cannot_be_accepted) ... ok
|
||||
test_wrong_account_cannot_load_or_accept_and_retry_stays_available (test_review_assistant_ui.ReminderPickerTest.test_wrong_account_cannot_load_or_accept_and_retry_stays_available) ... ok
|
||||
test_only_explicit_refresh_reads_notification_summary (test_review_assistant_ui.ReminderRefreshTest.test_only_explicit_refresh_reads_notification_summary) ... ok
|
||||
test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it (test_review_assistant_ui.ReminderRefreshTest.test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it) ... ok
|
||||
test_warning_for_old_target_is_not_applied_to_new_target_or_other_account (test_review_assistant_ui.ReminderRefreshTest.test_warning_for_old_target_is_not_applied_to_new_target_or_other_account) ... ok
|
||||
test_default_disabled_and_cannot_enable_without_recipient (test_review_assistant_ui.ReminderSettingsTest.test_default_disabled_and_cannot_enable_without_recipient) ... ok
|
||||
test_enable_revalidates_target_and_does_not_change_other_accounts (test_review_assistant_ui.ReminderSettingsTest.test_enable_revalidates_target_and_does_not_change_other_accounts) ... ok
|
||||
test_expected_account_mismatch_or_validation_failure_never_saves (test_review_assistant_ui.ReminderSettingsTest.test_expected_account_mismatch_or_validation_failure_never_saves) ... ok
|
||||
test_explicit_disable_only_needs_current_account_not_deleted_contact (test_review_assistant_ui.ReminderSettingsTest.test_explicit_disable_only_needs_current_account_not_deleted_contact) ... ok
|
||||
test_persist_failure_does_not_claim_config_is_enabled (test_review_assistant_ui.ReminderSettingsTest.test_persist_failure_does_not_claim_config_is_enabled) ... ok
|
||||
test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat (test_review_assistant_ui.ReminderSettingsTest.test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat) ... ok
|
||||
test_replacing_an_enabled_contact_requires_explicit_reenable (test_review_assistant_ui.ReminderSettingsTest.test_replacing_an_enabled_contact_requires_explicit_reenable) ... ok
|
||||
test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure (test_review_assistant_ui.ReminderSettingsTest.test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure) ... ok
|
||||
test_s_recipient_round_trip_preserves_raw_id_and_customer_kind (test_review_assistant_ui.ReminderSettingsTest.test_s_recipient_round_trip_preserves_raw_id_and_customer_kind) ... ok
|
||||
test_selection_persists_exact_verified_recipient_and_stays_off (test_review_assistant_ui.ReminderSettingsTest.test_selection_persists_exact_verified_recipient_and_stays_off) ... ok
|
||||
test_snapshot_does_not_probe_scan_or_query_databases (test_review_assistant_ui.ReminderSettingsTest.test_snapshot_does_not_probe_scan_or_query_databases) ... ok
|
||||
test_stale_async_reply_and_shutdown_do_not_save (test_review_assistant_ui.ReminderSettingsTest.test_stale_async_reply_and_shutdown_do_not_save) ... ok
|
||||
test_successful_reselection_clears_matching_warning_without_enabling (test_review_assistant_ui.ReminderSettingsTest.test_successful_reselection_clears_matching_warning_without_enabling) ... ok
|
||||
test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle (test_review_assistant_ui.ReminderWebTest.test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle) ... ok
|
||||
test_all_view_keeps_sendable_and_directory_groups_separate (test_review_assistant_contact_order.ContactOrderingTest.test_all_view_keeps_sendable_and_directory_groups_separate) ... ok
|
||||
test_chinese_names_and_decorative_prefixes_sort_consistently (test_review_assistant_contact_order.ContactOrderingTest.test_chinese_names_and_decorative_prefixes_sort_consistently) ... ok
|
||||
test_invalid_filters_fail_without_reading_other_data (test_review_assistant_contact_order.ContactOrderingTest.test_invalid_filters_fail_without_reading_other_data) ... ok
|
||||
test_numeric_nickname_and_duplicate_name_order_is_stable (test_review_assistant_contact_order.ContactOrderingTest.test_numeric_nickname_and_duplicate_name_order_is_stable) ... ok
|
||||
test_recent_sort_happens_before_page_slice (test_review_assistant_contact_order.ContactOrderingTest.test_recent_sort_happens_before_page_slice) ... ok
|
||||
test_state_filter_counts_include_full_search_results_before_paging (test_review_assistant_contact_order.ContactOrderingTest.test_state_filter_counts_include_full_search_results_before_paging) ... ok
|
||||
test_unknown_names_are_last_for_name_sort (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_are_last_for_name_sort) ... ok
|
||||
test_unknown_names_explicitly_show_identity_without_inventing_a_name (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_explicitly_show_identity_without_inventing_a_name) ... ok
|
||||
test_named_saved_recipient_keeps_name_and_full_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_named_saved_recipient_keeps_name_and_full_identity) ... ok
|
||||
test_old_generic_saved_name_becomes_explicit_unknown_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_old_generic_saved_name_becomes_explicit_unknown_identity) ... ok
|
||||
test_reselecting_same_recipient_still_names_the_saved_contact (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_reselecting_same_recipient_still_names_the_saved_contact) ... ok
|
||||
test_s_identity_displays_peer_for_both_endpoint_orders (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_s_identity_displays_peer_for_both_endpoint_orders) ... ok
|
||||
test_save_keeps_verified_identity_and_clear_feedback (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_save_keeps_verified_identity_and_clear_feedback) ... ok
|
||||
test_state_uses_current_account_mapping_and_never_rewrites_old_m (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_state_uses_current_account_mapping_and_never_rewrites_old_m) ... ok
|
||||
test_compact_screen_keeps_footer_visible_and_details_scrollable (test_review_assistant_picker_layout.PickerLayoutTest.test_compact_screen_keeps_footer_visible_and_details_scrollable) ... ok
|
||||
test_configured_recipient_mark_survives_selection_and_group_change (test_review_assistant_picker_layout.PickerLayoutTest.test_configured_recipient_mark_survives_selection_and_group_change) ... ok
|
||||
test_confirmation_validates_exact_selected_identity (test_review_assistant_picker_layout.PickerLayoutTest.test_confirmation_validates_exact_selected_identity) ... ok
|
||||
test_defaults_to_all_customers_and_queries_backend_sort_before_pagination (test_review_assistant_picker_layout.PickerLayoutTest.test_defaults_to_all_customers_and_queries_backend_sort_before_pagination) ... ok
|
||||
test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm (test_review_assistant_picker_layout.PickerLayoutTest.test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm) ... ok
|
||||
test_named_selection_is_blue_and_checked_after_focus_moves (test_review_assistant_picker_layout.PickerLayoutTest.test_named_selection_is_blue_and_checked_after_focus_moves) ... ok
|
||||
test_no_sendable_matches_shows_how_to_open_directory (test_review_assistant_picker_layout.PickerLayoutTest.test_no_sendable_matches_shows_how_to_open_directory) ... ok
|
||||
test_pending_validation_blocks_navigation_and_cancel_ignores_late_result (test_review_assistant_picker_layout.PickerLayoutTest.test_pending_validation_blocks_navigation_and_cancel_ignores_late_result) ... ok
|
||||
test_query_change_invalidates_inflight_list_before_debounce (test_review_assistant_picker_layout.PickerLayoutTest.test_query_change_invalidates_inflight_list_before_debounce) ... ok
|
||||
test_refresh_clears_old_selection_and_preserves_search_and_sort (test_review_assistant_picker_layout.PickerLayoutTest.test_refresh_clears_old_selection_and_preserves_search_and_sort) ... ok
|
||||
test_s_details_show_customer_peer_and_confirmation_preserves_raw_id (test_review_assistant_picker_layout.PickerLayoutTest.test_s_details_show_customer_peer_and_confirmation_preserves_raw_id) ... ok
|
||||
test_same_name_rows_have_distinct_tail_numbers_before_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_same_name_rows_have_distinct_tail_numbers_before_selection) ... ok
|
||||
test_stale_validation_and_list_from_other_account_are_ignored (test_review_assistant_picker_layout.PickerLayoutTest.test_stale_validation_and_list_from_other_account_are_ignored) ... ok
|
||||
test_unknown_name_is_explicit_and_gets_same_visible_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_unknown_name_is_explicit_and_gets_same_visible_selection) ... ok
|
||||
test_wrong_account_or_returned_identity_never_accepts (test_review_assistant_picker_layout.PickerLayoutTest.test_wrong_account_or_returned_identity_never_accepts) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 90 tests in 8.091s
|
||||
|
||||
OK
|
||||
@@ -1,71 +0,0 @@
|
||||
test_account_mismatch_never_reads_the_old_accounts_database (test_review_assistant_ui.ReminderContactTest.test_account_mismatch_never_reads_the_old_accounts_database) ... ok
|
||||
test_account_switch_during_validation_rejects_selection (test_review_assistant_ui.ReminderContactTest.test_account_switch_during_validation_rejects_selection) ... ok
|
||||
test_duplicate_names_remain_separate_and_identifiable (test_review_assistant_ui.ReminderContactTest.test_duplicate_names_remain_separate_and_identifiable) ... ok
|
||||
test_group_internal_or_unknown_recipient_cannot_be_saved (test_review_assistant_ui.ReminderContactTest.test_group_internal_or_unknown_recipient_cannot_be_saved) ... ok
|
||||
test_lists_relation_customers_with_s_and_m_chats_without_message_content (test_review_assistant_ui.ReminderContactTest.test_lists_relation_customers_with_s_and_m_chats_without_message_content) ... ok
|
||||
test_missing_account_does_not_fall_back_to_another_account (test_review_assistant_ui.ReminderContactTest.test_missing_account_does_not_fall_back_to_another_account) ... ok
|
||||
test_preview_is_static_and_does_not_load_real_customer_data (test_review_assistant_ui.ReminderContactTest.test_preview_is_static_and_does_not_load_real_customer_data) ... ok
|
||||
test_queries_are_read_only_and_do_not_initialize_or_modify_databases (test_review_assistant_ui.ReminderContactTest.test_queries_are_read_only_and_do_not_initialize_or_modify_databases) ... ok
|
||||
test_recipient_validation_uses_id_and_rechecks_identity (test_review_assistant_ui.ReminderContactTest.test_recipient_validation_uses_id_and_rechecks_identity) ... ok
|
||||
test_search_and_pagination_are_independent_of_message_preview (test_review_assistant_ui.ReminderContactTest.test_search_and_pagination_are_independent_of_message_preview) ... ok
|
||||
test_active_identity_only_uses_native_readonly_scope (test_review_assistant_ui.ReminderIdentityTest.test_active_identity_only_uses_native_readonly_scope) ... ok
|
||||
test_native_unavailable_is_clear_and_does_not_use_another_account (test_review_assistant_ui.ReminderIdentityTest.test_native_unavailable_is_clear_and_does_not_use_another_account) ... ok
|
||||
test_refresh_cannot_race_pending_recipient_validation (test_review_assistant_ui.ReminderPickerTest.test_refresh_cannot_race_pending_recipient_validation) ... ok
|
||||
test_refresh_remains_available_after_account_or_cache_error (test_review_assistant_ui.ReminderPickerTest.test_refresh_remains_available_after_account_or_cache_error) ... ok
|
||||
test_refresh_rereads_cached_list_and_preserves_query_from_first_page (test_review_assistant_ui.ReminderPickerTest.test_refresh_rereads_cached_list_and_preserves_query_from_first_page) ... ok
|
||||
test_same_name_rows_keep_exact_identity_and_validate_selected_one (test_review_assistant_ui.ReminderPickerTest.test_same_name_rows_keep_exact_identity_and_validate_selected_one) ... ok
|
||||
test_stale_list_and_late_validation_after_cancel_are_ignored (test_review_assistant_ui.ReminderPickerTest.test_stale_list_and_late_validation_after_cancel_are_ignored) ... ok
|
||||
test_stale_validation_result_cannot_accept_after_a_newer_request (test_review_assistant_ui.ReminderPickerTest.test_stale_validation_result_cannot_accept_after_a_newer_request) ... ok
|
||||
test_unmapped_contact_is_visible_but_cannot_be_accepted (test_review_assistant_ui.ReminderPickerTest.test_unmapped_contact_is_visible_but_cannot_be_accepted) ... ok
|
||||
test_wrong_account_cannot_load_or_accept_and_retry_stays_available (test_review_assistant_ui.ReminderPickerTest.test_wrong_account_cannot_load_or_accept_and_retry_stays_available) ... ok
|
||||
test_only_explicit_refresh_reads_notification_summary (test_review_assistant_ui.ReminderRefreshTest.test_only_explicit_refresh_reads_notification_summary) ... ok
|
||||
test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it (test_review_assistant_ui.ReminderRefreshTest.test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it) ... ok
|
||||
test_warning_for_old_target_is_not_applied_to_new_target_or_other_account (test_review_assistant_ui.ReminderRefreshTest.test_warning_for_old_target_is_not_applied_to_new_target_or_other_account) ... ok
|
||||
test_default_disabled_and_cannot_enable_without_recipient (test_review_assistant_ui.ReminderSettingsTest.test_default_disabled_and_cannot_enable_without_recipient) ... ok
|
||||
test_enable_revalidates_target_and_does_not_change_other_accounts (test_review_assistant_ui.ReminderSettingsTest.test_enable_revalidates_target_and_does_not_change_other_accounts) ... ok
|
||||
test_expected_account_mismatch_or_validation_failure_never_saves (test_review_assistant_ui.ReminderSettingsTest.test_expected_account_mismatch_or_validation_failure_never_saves) ... ok
|
||||
test_explicit_disable_only_needs_current_account_not_deleted_contact (test_review_assistant_ui.ReminderSettingsTest.test_explicit_disable_only_needs_current_account_not_deleted_contact) ... ok
|
||||
test_persist_failure_does_not_claim_config_is_enabled (test_review_assistant_ui.ReminderSettingsTest.test_persist_failure_does_not_claim_config_is_enabled) ... ok
|
||||
test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat (test_review_assistant_ui.ReminderSettingsTest.test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat) ... ok
|
||||
test_replacing_an_enabled_contact_requires_explicit_reenable (test_review_assistant_ui.ReminderSettingsTest.test_replacing_an_enabled_contact_requires_explicit_reenable) ... ok
|
||||
test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure (test_review_assistant_ui.ReminderSettingsTest.test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure) ... ok
|
||||
test_s_recipient_round_trip_preserves_raw_id_and_customer_kind (test_review_assistant_ui.ReminderSettingsTest.test_s_recipient_round_trip_preserves_raw_id_and_customer_kind) ... ok
|
||||
test_selection_persists_exact_verified_recipient_and_stays_off (test_review_assistant_ui.ReminderSettingsTest.test_selection_persists_exact_verified_recipient_and_stays_off) ... ok
|
||||
test_snapshot_does_not_probe_scan_or_query_databases (test_review_assistant_ui.ReminderSettingsTest.test_snapshot_does_not_probe_scan_or_query_databases) ... ok
|
||||
test_stale_async_reply_and_shutdown_do_not_save (test_review_assistant_ui.ReminderSettingsTest.test_stale_async_reply_and_shutdown_do_not_save) ... ok
|
||||
test_successful_reselection_clears_matching_warning_without_enabling (test_review_assistant_ui.ReminderSettingsTest.test_successful_reselection_clears_matching_warning_without_enabling) ... ok
|
||||
test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle (test_review_assistant_ui.ReminderWebTest.test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle) ... ok
|
||||
test_all_view_keeps_sendable_and_directory_groups_separate (test_review_assistant_contact_order.ContactOrderingTest.test_all_view_keeps_sendable_and_directory_groups_separate) ... ok
|
||||
test_chinese_names_and_decorative_prefixes_sort_consistently (test_review_assistant_contact_order.ContactOrderingTest.test_chinese_names_and_decorative_prefixes_sort_consistently) ... ok
|
||||
test_invalid_filters_fail_without_reading_other_data (test_review_assistant_contact_order.ContactOrderingTest.test_invalid_filters_fail_without_reading_other_data) ... ok
|
||||
test_numeric_nickname_and_duplicate_name_order_is_stable (test_review_assistant_contact_order.ContactOrderingTest.test_numeric_nickname_and_duplicate_name_order_is_stable) ... ok
|
||||
test_recent_sort_happens_before_page_slice (test_review_assistant_contact_order.ContactOrderingTest.test_recent_sort_happens_before_page_slice) ... ok
|
||||
test_state_filter_counts_include_full_search_results_before_paging (test_review_assistant_contact_order.ContactOrderingTest.test_state_filter_counts_include_full_search_results_before_paging) ... ok
|
||||
test_unknown_names_are_last_for_name_sort (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_are_last_for_name_sort) ... ok
|
||||
test_unknown_names_explicitly_show_identity_without_inventing_a_name (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_explicitly_show_identity_without_inventing_a_name) ... ok
|
||||
test_named_saved_recipient_keeps_name_and_full_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_named_saved_recipient_keeps_name_and_full_identity) ... ok
|
||||
test_old_generic_saved_name_becomes_explicit_unknown_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_old_generic_saved_name_becomes_explicit_unknown_identity) ... ok
|
||||
test_reselecting_same_recipient_still_names_the_saved_contact (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_reselecting_same_recipient_still_names_the_saved_contact) ... ok
|
||||
test_s_identity_displays_peer_for_both_endpoint_orders (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_s_identity_displays_peer_for_both_endpoint_orders) ... ok
|
||||
test_save_keeps_verified_identity_and_clear_feedback (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_save_keeps_verified_identity_and_clear_feedback) ... ok
|
||||
test_state_uses_current_account_mapping_and_never_rewrites_old_m (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_state_uses_current_account_mapping_and_never_rewrites_old_m) ... ok
|
||||
test_compact_screen_keeps_footer_visible_and_details_scrollable (test_review_assistant_picker_layout.PickerLayoutTest.test_compact_screen_keeps_footer_visible_and_details_scrollable) ... ok
|
||||
test_configured_recipient_mark_survives_selection_and_group_change (test_review_assistant_picker_layout.PickerLayoutTest.test_configured_recipient_mark_survives_selection_and_group_change) ... ok
|
||||
test_confirmation_validates_exact_selected_identity (test_review_assistant_picker_layout.PickerLayoutTest.test_confirmation_validates_exact_selected_identity) ... ok
|
||||
test_defaults_to_all_customers_and_queries_backend_sort_before_pagination (test_review_assistant_picker_layout.PickerLayoutTest.test_defaults_to_all_customers_and_queries_backend_sort_before_pagination) ... ok
|
||||
test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm (test_review_assistant_picker_layout.PickerLayoutTest.test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm) ... ok
|
||||
test_named_selection_is_blue_and_checked_after_focus_moves (test_review_assistant_picker_layout.PickerLayoutTest.test_named_selection_is_blue_and_checked_after_focus_moves) ... ok
|
||||
test_no_sendable_matches_shows_how_to_open_directory (test_review_assistant_picker_layout.PickerLayoutTest.test_no_sendable_matches_shows_how_to_open_directory) ... ok
|
||||
test_pending_validation_blocks_navigation_and_cancel_ignores_late_result (test_review_assistant_picker_layout.PickerLayoutTest.test_pending_validation_blocks_navigation_and_cancel_ignores_late_result) ... ok
|
||||
test_query_change_invalidates_inflight_list_before_debounce (test_review_assistant_picker_layout.PickerLayoutTest.test_query_change_invalidates_inflight_list_before_debounce) ... ok
|
||||
test_refresh_clears_old_selection_and_preserves_search_and_sort (test_review_assistant_picker_layout.PickerLayoutTest.test_refresh_clears_old_selection_and_preserves_search_and_sort) ... ok
|
||||
test_s_details_show_customer_peer_and_confirmation_preserves_raw_id (test_review_assistant_picker_layout.PickerLayoutTest.test_s_details_show_customer_peer_and_confirmation_preserves_raw_id) ... ok
|
||||
test_same_name_rows_have_distinct_tail_numbers_before_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_same_name_rows_have_distinct_tail_numbers_before_selection) ... ok
|
||||
test_stale_validation_and_list_from_other_account_are_ignored (test_review_assistant_picker_layout.PickerLayoutTest.test_stale_validation_and_list_from_other_account_are_ignored) ... ok
|
||||
test_unknown_name_is_explicit_and_gets_same_visible_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_unknown_name_is_explicit_and_gets_same_visible_selection) ... ok
|
||||
test_wrong_account_or_returned_identity_never_accepts (test_review_assistant_picker_layout.PickerLayoutTest.test_wrong_account_or_returned_identity_never_accepts) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 66 tests in 6.755s
|
||||
|
||||
OK
|
||||
@@ -1,68 +0,0 @@
|
||||
test_default_disabled_and_cannot_enable_without_recipient (test_review_assistant_ui.ReminderSettingsTest.test_default_disabled_and_cannot_enable_without_recipient) ... ok
|
||||
test_enable_revalidates_target_and_does_not_change_other_accounts (test_review_assistant_ui.ReminderSettingsTest.test_enable_revalidates_target_and_does_not_change_other_accounts) ... ok
|
||||
test_expected_account_mismatch_or_validation_failure_never_saves (test_review_assistant_ui.ReminderSettingsTest.test_expected_account_mismatch_or_validation_failure_never_saves) ... ok
|
||||
test_explicit_disable_only_needs_current_account_not_deleted_contact (test_review_assistant_ui.ReminderSettingsTest.test_explicit_disable_only_needs_current_account_not_deleted_contact) ... ok
|
||||
test_persist_failure_does_not_claim_config_is_enabled (test_review_assistant_ui.ReminderSettingsTest.test_persist_failure_does_not_claim_config_is_enabled) ... ok
|
||||
test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat (test_review_assistant_ui.ReminderSettingsTest.test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat) ... ok
|
||||
test_replacing_an_enabled_contact_requires_explicit_reenable (test_review_assistant_ui.ReminderSettingsTest.test_replacing_an_enabled_contact_requires_explicit_reenable) ... ok
|
||||
test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure (test_review_assistant_ui.ReminderSettingsTest.test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure) ... ok
|
||||
test_s_recipient_round_trip_preserves_raw_id_and_customer_kind (test_review_assistant_ui.ReminderSettingsTest.test_s_recipient_round_trip_preserves_raw_id_and_customer_kind) ... ok
|
||||
test_selection_persists_exact_verified_recipient_and_stays_off (test_review_assistant_ui.ReminderSettingsTest.test_selection_persists_exact_verified_recipient_and_stays_off) ... ok
|
||||
test_snapshot_does_not_probe_scan_or_query_databases (test_review_assistant_ui.ReminderSettingsTest.test_snapshot_does_not_probe_scan_or_query_databases) ... ok
|
||||
test_stale_async_reply_and_shutdown_do_not_save (test_review_assistant_ui.ReminderSettingsTest.test_stale_async_reply_and_shutdown_do_not_save) ... ok
|
||||
test_successful_reselection_clears_matching_warning_without_enabling (test_review_assistant_ui.ReminderSettingsTest.test_successful_reselection_clears_matching_warning_without_enabling) ... ok
|
||||
test_refresh_cannot_race_pending_recipient_validation (test_review_assistant_ui.ReminderPickerTest.test_refresh_cannot_race_pending_recipient_validation) ... ok
|
||||
test_refresh_remains_available_after_account_or_cache_error (test_review_assistant_ui.ReminderPickerTest.test_refresh_remains_available_after_account_or_cache_error) ... ok
|
||||
test_refresh_rereads_cached_list_and_preserves_query_from_first_page (test_review_assistant_ui.ReminderPickerTest.test_refresh_rereads_cached_list_and_preserves_query_from_first_page) ... ok
|
||||
test_same_name_rows_keep_exact_identity_and_validate_selected_one (test_review_assistant_ui.ReminderPickerTest.test_same_name_rows_keep_exact_identity_and_validate_selected_one) ... ok
|
||||
test_stale_list_and_late_validation_after_cancel_are_ignored (test_review_assistant_ui.ReminderPickerTest.test_stale_list_and_late_validation_after_cancel_are_ignored) ... ok
|
||||
test_stale_validation_result_cannot_accept_after_a_newer_request (test_review_assistant_ui.ReminderPickerTest.test_stale_validation_result_cannot_accept_after_a_newer_request) ... ok
|
||||
test_unmapped_contact_is_visible_but_cannot_be_accepted (test_review_assistant_ui.ReminderPickerTest.test_unmapped_contact_is_visible_but_cannot_be_accepted) ... FAIL
|
||||
test_wrong_account_cannot_load_or_accept_and_retry_stays_available (test_review_assistant_ui.ReminderPickerTest.test_wrong_account_cannot_load_or_accept_and_retry_stays_available) ... ok
|
||||
test_only_explicit_refresh_reads_notification_summary (test_review_assistant_ui.ReminderRefreshTest.test_only_explicit_refresh_reads_notification_summary) ... ok
|
||||
test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it (test_review_assistant_ui.ReminderRefreshTest.test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it) ... ok
|
||||
test_warning_for_old_target_is_not_applied_to_new_target_or_other_account (test_review_assistant_ui.ReminderRefreshTest.test_warning_for_old_target_is_not_applied_to_new_target_or_other_account) ... ok
|
||||
test_active_identity_only_uses_native_readonly_scope (test_review_assistant_ui.ReminderIdentityTest.test_active_identity_only_uses_native_readonly_scope) ... ok
|
||||
test_native_unavailable_is_clear_and_does_not_use_another_account (test_review_assistant_ui.ReminderIdentityTest.test_native_unavailable_is_clear_and_does_not_use_another_account) ... ok
|
||||
test_all_view_keeps_sendable_and_directory_groups_separate (test_review_assistant_contact_order.ContactOrderingTest.test_all_view_keeps_sendable_and_directory_groups_separate) ... ok
|
||||
test_chinese_names_and_decorative_prefixes_sort_consistently (test_review_assistant_contact_order.ContactOrderingTest.test_chinese_names_and_decorative_prefixes_sort_consistently) ... ok
|
||||
test_invalid_filters_fail_without_reading_other_data (test_review_assistant_contact_order.ContactOrderingTest.test_invalid_filters_fail_without_reading_other_data) ... ok
|
||||
test_numeric_nickname_and_duplicate_name_order_is_stable (test_review_assistant_contact_order.ContactOrderingTest.test_numeric_nickname_and_duplicate_name_order_is_stable) ... ok
|
||||
test_recent_sort_happens_before_page_slice (test_review_assistant_contact_order.ContactOrderingTest.test_recent_sort_happens_before_page_slice) ... ok
|
||||
test_state_filter_counts_include_full_search_results_before_paging (test_review_assistant_contact_order.ContactOrderingTest.test_state_filter_counts_include_full_search_results_before_paging) ... ok
|
||||
test_unknown_names_are_last_for_name_sort (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_are_last_for_name_sort) ... ok
|
||||
test_unknown_names_explicitly_show_identity_without_inventing_a_name (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_explicitly_show_identity_without_inventing_a_name) ... ok
|
||||
test_named_saved_recipient_keeps_name_and_full_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_named_saved_recipient_keeps_name_and_full_identity) ... ok
|
||||
test_old_generic_saved_name_becomes_explicit_unknown_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_old_generic_saved_name_becomes_explicit_unknown_identity) ... ok
|
||||
test_reselecting_same_recipient_still_names_the_saved_contact (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_reselecting_same_recipient_still_names_the_saved_contact) ... ok
|
||||
test_s_identity_displays_peer_for_both_endpoint_orders (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_s_identity_displays_peer_for_both_endpoint_orders) ... ok
|
||||
test_save_keeps_verified_identity_and_clear_feedback (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_save_keeps_verified_identity_and_clear_feedback) ... ok
|
||||
test_state_uses_current_account_mapping_and_never_rewrites_old_m (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_state_uses_current_account_mapping_and_never_rewrites_old_m) ... ok
|
||||
test_compact_screen_keeps_footer_visible_and_details_scrollable (test_review_assistant_picker_layout.PickerLayoutTest.test_compact_screen_keeps_footer_visible_and_details_scrollable) ... ok
|
||||
test_configured_recipient_mark_survives_selection_and_group_change (test_review_assistant_picker_layout.PickerLayoutTest.test_configured_recipient_mark_survives_selection_and_group_change) ... ok
|
||||
test_confirmation_validates_exact_selected_identity (test_review_assistant_picker_layout.PickerLayoutTest.test_confirmation_validates_exact_selected_identity) ... ok
|
||||
test_defaults_to_all_customers_and_queries_backend_sort_before_pagination (test_review_assistant_picker_layout.PickerLayoutTest.test_defaults_to_all_customers_and_queries_backend_sort_before_pagination) ... ok
|
||||
test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm (test_review_assistant_picker_layout.PickerLayoutTest.test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm) ... ok
|
||||
test_named_selection_is_blue_and_checked_after_focus_moves (test_review_assistant_picker_layout.PickerLayoutTest.test_named_selection_is_blue_and_checked_after_focus_moves) ... ok
|
||||
test_no_sendable_matches_shows_how_to_open_directory (test_review_assistant_picker_layout.PickerLayoutTest.test_no_sendable_matches_shows_how_to_open_directory) ... ok
|
||||
test_pending_validation_blocks_navigation_and_cancel_ignores_late_result (test_review_assistant_picker_layout.PickerLayoutTest.test_pending_validation_blocks_navigation_and_cancel_ignores_late_result) ... ok
|
||||
test_query_change_invalidates_inflight_list_before_debounce (test_review_assistant_picker_layout.PickerLayoutTest.test_query_change_invalidates_inflight_list_before_debounce) ... ok
|
||||
test_refresh_clears_old_selection_and_preserves_search_and_sort (test_review_assistant_picker_layout.PickerLayoutTest.test_refresh_clears_old_selection_and_preserves_search_and_sort) ... ok
|
||||
test_s_details_show_customer_peer_and_confirmation_preserves_raw_id (test_review_assistant_picker_layout.PickerLayoutTest.test_s_details_show_customer_peer_and_confirmation_preserves_raw_id) ... ok
|
||||
test_same_name_rows_have_distinct_tail_numbers_before_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_same_name_rows_have_distinct_tail_numbers_before_selection) ... ok
|
||||
test_stale_validation_and_list_from_other_account_are_ignored (test_review_assistant_picker_layout.PickerLayoutTest.test_stale_validation_and_list_from_other_account_are_ignored) ... ok
|
||||
test_unknown_name_is_explicit_and_gets_same_visible_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_unknown_name_is_explicit_and_gets_same_visible_selection) ... ok
|
||||
test_wrong_account_or_returned_identity_never_accepts (test_review_assistant_picker_layout.PickerLayoutTest.test_wrong_account_or_returned_identity_never_accepts) ... ok
|
||||
|
||||
======================================================================
|
||||
FAIL: test_unmapped_contact_is_visible_but_cannot_be_accepted (test_review_assistant_ui.ReminderPickerTest.test_unmapped_contact_is_visible_but_cannot_be_accepted)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "C:\kefu\wechat_rpa\test_review_assistant_ui.py", line 396, in test_unmapped_contact_is_visible_but_cannot_be_accepted
|
||||
self.assertIn('123456789012345', self.dialog.details_identity.text())
|
||||
AssertionError: '123456789012345' not found in '企业微信客户 · 客户编号:10001'
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 55 tests in 0.895s
|
||||
|
||||
FAILED (failures=1)
|
||||
@@ -1 +0,0 @@
|
||||
{"checks":56,"overflow":0,"pageErrors":[]}
|
||||
@@ -1,4 +0,0 @@
|
||||
----------------------------------------------------------------------
|
||||
Ran 35 tests in 2.070s
|
||||
|
||||
OK
|
||||
@@ -1,72 +0,0 @@
|
||||
[16736:15596:0916/154521.205:ERROR:direct_composition_support.cc(225)] GetGpuDriverOverlayInfo: Failed to retrieve video device
|
||||
----------------------------------------------------------------------
|
||||
Ran 138 tests in 3.595s
|
||||
|
||||
OK
|
||||
[待回复恢复] 已从磁盘恢复 1 个未完成任务。
|
||||
[引擎B] 数据直读检测已启动
|
||||
[+] 窗口激活模式已开启:企业微信未显示时会自动还原到前台
|
||||
[i] 数据库新消息与未读标记共同触发回复任务,窗口异常时保留任务并重试
|
||||
[+] 人机共存已开启:鼠标静止 5 秒后才自动操作
|
||||
[+] 连续消息合并等待:7 秒
|
||||
[+] 发送前等待:1.5 秒
|
||||
[+] 发送模式:人工审核草稿(AI 只把回复填进输入框,不会自动按回车;需要自动发送请在设置里切到“自动发送”)
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 此消息类型需要人工处理;当前协议版只自动处理文本消息
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 发送结果待人工核对,已暂停监听;timeout
|
||||
[引擎B] 已登记新消息 → test
|
||||
@@ -1,238 +0,0 @@
|
||||
$ pnpm vite build --mode production
|
||||
vite v8.2.1 building client environment for production...
|
||||
[2K
|
||||
transforming...✓ 7447 modules transformed.
|
||||
rendering chunks...
|
||||
✨configuration file is build successfully!
|
||||
dist/_app-config-5.7.0-7362080d.js 0.20 kB
|
||||
dist/index.html 3.35 kB
|
||||
dist/css/login-Cj5PKODp.css 0.06 kB
|
||||
dist/css/auth-zsf-kax4.css 0.38 kB
|
||||
dist/css/config-CYorFwo-.css 0.56 kB
|
||||
dist/css/loading-DXYS4l2z.css 0.56 kB
|
||||
dist/css/vue-router-CJxWTMt5.css 0.69 kB
|
||||
dist/css/theme-toggle-CJLHZmGO.css 1.63 kB
|
||||
dist/css/tippy-DkTQMyWH.css 6.65 kB
|
||||
dist/css/basic-CE2ii0IK.css 23.49 kB
|
||||
dist/css/bootstrap-D3jHjRmY.css 153.26 kB
|
||||
dist/js/_plugin-vue_export-helper-BDNMzG2s.js 0.08 kB
|
||||
dist/js/devWarning-DlchpATv.js 0.10 kB
|
||||
dist/js/motionUtil-BeNb4tZl.js 0.11 kB
|
||||
dist/js/vben-C1vbzhcL.js 0.12 kB
|
||||
dist/js/omit-C0ksMpVM.js 0.14 kB
|
||||
dist/js/profile-B411QZNQ.js 0.15 kB
|
||||
dist/js/profile-tkuLhW9J.js 0.15 kB
|
||||
dist/js/useState-DlRKQDQX.js 0.16 kB
|
||||
dist/js/warning-BLl3S_cO.js 0.17 kB
|
||||
dist/js/useMemo-m5GuU0Kd.js 0.17 kB
|
||||
dist/js/useRefs-QDevZzkt.js 0.17 kB
|
||||
dist/js/useFlexGapSupport-D07fCJnk.js 0.18 kB
|
||||
dist/js/rotate-cw-CyWoHUpq.js 0.19 kB
|
||||
dist/js/Keyframes-K60KFfv3.js 0.20 kB
|
||||
dist/js/isVisible-B1N4qR6W.js 0.23 kB
|
||||
dist/js/coming-soon-C9te2Fo9.js 0.23 kB
|
||||
dist/js/initDefaultProps-D8Mki4gM.js 0.25 kB
|
||||
dist/js/useBreakpoint-4zwrQO2u.js 0.26 kB
|
||||
dist/js/page-DM9HIydN.js 0.27 kB
|
||||
dist/js/createContext-LBMERH-r.js 0.28 kB
|
||||
dist/js/page-YH8FPpYF.js 0.28 kB
|
||||
dist/js/src-DS89XIkw.js 0.28 kB
|
||||
dist/js/statusUtils-WKRwVnP6.js 0.29 kB
|
||||
dist/js/src-DkoRg56f.js 0.30 kB
|
||||
dist/js/forbidden-Bmiwnz_B.js 0.31 kB
|
||||
dist/js/not-found-CmXcaUT6.js 0.31 kB
|
||||
dist/js/internal-error-CMwA7W1E.js 0.31 kB
|
||||
dist/js/offline-Dx824lFG.js 0.31 kB
|
||||
dist/js/demos-Bb7WGJxd.js 0.32 kB
|
||||
dist/js/demos-BSnMPpZY.js 0.32 kB
|
||||
dist/js/download-DUHREPuF.js 0.42 kB
|
||||
dist/js/_arrayIncludesWith-D3sQWlhs.js 0.43 kB
|
||||
dist/js/isPlainObject-iVjSthyR.js 0.43 kB
|
||||
dist/js/raf-CR9Bw2Uc.js 0.45 kB
|
||||
dist/js/auth-title-DCLZf2Gr.js 0.48 kB
|
||||
dist/js/useMergedState-zH37e67U.js 0.49 kB
|
||||
dist/js/css-BflejRyY.js 0.50 kB
|
||||
dist/js/shallowequal-D7g0B-CQ.js 0.52 kB
|
||||
dist/js/extends-C_p2ba5S.js 0.52 kB
|
||||
dist/js/use-archive-load-BINKTMOh.js 0.52 kB
|
||||
dist/js/en-DA5aUWwj.js 0.58 kB
|
||||
dist/js/date-picker-C1ofm_9t.js 0.59 kB
|
||||
dist/js/render-content-3dfOk9Gq.js 0.59 kB
|
||||
dist/js/isObjectLike-DNah0Hql.js 0.66 kB
|
||||
dist/js/use-access-CQdD7p8C.js 0.69 kB
|
||||
dist/js/objectWithoutProperties-BjoYlK0I.js 0.69 kB
|
||||
dist/js/merge-C-fCyOMx.js 0.69 kB
|
||||
dist/js/defu-1oANYd5X.js 0.70 kB
|
||||
dist/js/rolldown-runtime-hePW80VL.js 0.71 kB
|
||||
dist/js/styleChecker-CeGG85sE.js 0.79 kB
|
||||
dist/js/useApi-CROJJdhE-oP73ypFI.js 0.83 kB
|
||||
dist/js/common-DWRZ7B_7.js 0.85 kB
|
||||
dist/js/common-BE0LVHtH.js 0.88 kB
|
||||
dist/js/Primitive-Bi_oIzTM.js 0.90 kB
|
||||
dist/js/compact-item-BbW5OmKl.js 0.94 kB
|
||||
dist/js/LeftOutlined-HmT5OMoh.js 1.01 kB
|
||||
dist/js/RightOutlined-DwLwVX1C.js 1.01 kB
|
||||
dist/js/DownOutlined-Cq6F7QWr.js 1.01 kB
|
||||
dist/js/vnode-CRVBf7wj.js 1.01 kB
|
||||
dist/js/CheckOutlined-Dy5-Q7N5.js 1.01 kB
|
||||
dist/js/knowledge-BMccf88i.js 1.03 kB
|
||||
dist/js/FormItemContext-CEmO5XmM.js 1.11 kB
|
||||
dist/js/CheckCircleFilled-CvJ3C2gR.js 1.11 kB
|
||||
dist/js/LoadingOutlined-tpSKTswf.js 1.15 kB
|
||||
dist/js/preload-helper-DaercurD.js 1.22 kB
|
||||
dist/js/objectSpread2-BmonrgTA.js 1.29 kB
|
||||
dist/js/_baseIteratee-NxSP5AT6.js 1.29 kB
|
||||
dist/js/EyeOutlined-w8ODygj3.js 1.30 kB
|
||||
dist/js/ActionButton-DlhIPLDf.js 1.33 kB
|
||||
dist/js/SearchOutlined-CndaZ08h.js 1.34 kB
|
||||
dist/js/loading-Cw3fZBrE.js 1.35 kB
|
||||
dist/js/collapseMotion-BfalGvoQ.js 1.47 kB
|
||||
dist/js/CloseOutlined-BdX5pn5u.js 1.48 kB
|
||||
dist/js/colors-C2RrYxlT.js 1.48 kB
|
||||
dist/js/zh-cn-DTVg5rYV.js 1.52 kB
|
||||
dist/js/CloseCircleFilled-C9x0ZM0q.js 1.56 kB
|
||||
dist/js/debounce-DNW4oWi1.js 1.58 kB
|
||||
dist/js/archive-account-selector-Bd0_0sw5.js 1.63 kB
|
||||
dist/js/notification-setting-7bFohVCQ.js 1.69 kB
|
||||
dist/js/page-CuTJnSJp.js 1.70 kB
|
||||
dist/js/audit-BqW7o0mf.js 1.72 kB
|
||||
dist/js/base-setting-DMOVS08n.js 1.82 kB
|
||||
dist/js/security-setting-C-Wxwv7E.js 1.90 kB
|
||||
dist/js/slide-D__jeCTu.js 1.92 kB
|
||||
dist/js/move-kOZGsaQl.js 1.96 kB
|
||||
dist/js/password-setting-BzxgKWpd.js 1.98 kB
|
||||
dist/js/archive-PnuNQRb2.js 1.99 kB
|
||||
dist/js/KeyCode-DNtAKsAc.js 2.00 kB
|
||||
dist/js/change-password-Bfkvbb8A.js 2.03 kB
|
||||
dist/js/hasIn-BIluNPSA.js 2.06 kB
|
||||
dist/js/isMobile-DH4W6rzp.js 2.09 kB
|
||||
dist/js/pickAttrs-SF6-8m9R.js 2.18 kB
|
||||
dist/js/Portal-jWUJieln.js 2.26 kB
|
||||
dist/js/space-B06wu9Uj.js 2.30 kB
|
||||
dist/js/forget-password-rFqeb0Do.js 2.31 kB
|
||||
dist/js/zoom-C1lAvwDy.js 2.37 kB
|
||||
dist/js/Checkbox-CaX94bng.js 2.41 kB
|
||||
dist/js/time-picker-G9rC4smS.js 2.60 kB
|
||||
dist/js/dist-zStm9ma4.js 2.70 kB
|
||||
dist/js/responsiveObserve-CPvTZIYq.js 2.70 kB
|
||||
dist/js/use-preferences-2Ls4-wCJ.js 2.91 kB
|
||||
dist/js/auto-complete-UyB6Un0I.js 2.95 kB
|
||||
dist/js/Compact-Icyx2uFm.js 3.04 kB
|
||||
dist/js/FormLabel-CiUM-Zyy.js 3.27 kB
|
||||
dist/js/authentication-DmobrOr_.js 3.37 kB
|
||||
dist/js/fallback-B3eN2qYq.js 3.37 kB
|
||||
dist/js/register-Blo6FBMi.js 3.40 kB
|
||||
dist/js/authentication-BYliOcm3.js 3.53 kB
|
||||
dist/js/divider-B8AbMF6d.js 3.58 kB
|
||||
dist/js/_getTag-2z2WZcIh.js 3.72 kB
|
||||
dist/js/wave-BBnUlIB_.js 3.82 kB
|
||||
dist/js/style-DQ50flCp.js 3.88 kB
|
||||
dist/js/Switch-DRsr_95y.js 3.96 kB
|
||||
dist/js/users-CIDvnaf9.js 4.03 kB
|
||||
dist/js/profile-DVrkm3XP.js 4.07 kB
|
||||
dist/js/overview-iGlyPA69.js 4.12 kB
|
||||
dist/js/en_US-Cv9hrLhb.js 4.17 kB
|
||||
dist/js/nprogress-CcparBbP.js 4.18 kB
|
||||
dist/js/motion-BmOd6fTF.js 4.38 kB
|
||||
dist/js/ui-NNY_r1AM.js 4.39 kB
|
||||
dist/js/row-B32lsdNE.js 4.44 kB
|
||||
dist/js/ui-CCmUukCu.js 4.64 kB
|
||||
dist/js/BaseInput-D9ryi2LY.js 4.67 kB
|
||||
dist/js/tag-BFecLZmQ.js 4.83 kB
|
||||
dist/js/checkbox-DbdxvqS7.js 4.83 kB
|
||||
dist/js/vue.runtime.esm-bundler-DXMo22CJ.js 4.95 kB
|
||||
dist/js/exports-MUTZlKIh.js 4.99 kB
|
||||
dist/jse/index-index-DVg113Hz.js 5.12 kB
|
||||
dist/js/roles-mfmVdw-x.js 5.22 kB
|
||||
dist/js/alert-CkUknOsQ.js 5.34 kB
|
||||
dist/js/model-plan-hTQhhez2.js 5.35 kB
|
||||
dist/js/Col-8hLsgOob.js 5.55 kB
|
||||
dist/js/VisuallyHiddenInput-CDz4_yZw.js 5.82 kB
|
||||
dist/js/core-CY2B_m7j.js 6.17 kB
|
||||
dist/js/storage-B-nMfgzG.js 6.27 kB
|
||||
dist/js/desktop-accounts-QRKFv2yk.js 6.31 kB
|
||||
dist/js/spin-3P-IVef6.js 6.52 kB
|
||||
dist/js/vc-overflow-DrtZeojQ.js 6.58 kB
|
||||
dist/js/icon-500-z_hKUj8N.js 7.10 kB
|
||||
dist/js/dayjs.min-DCUUuXM3.js 7.18 kB
|
||||
dist/js/rate-DdROH9ca.js 7.42 kB
|
||||
dist/js/popconfirm-BqMuKaMZ.js 7.43 kB
|
||||
dist/js/ResizeObserver.es-DbHj_W6-.js 7.62 kB
|
||||
dist/js/preferences-C8rVqNJ_.js 7.71 kB
|
||||
dist/js/preferences-Dy8TIlZp.js 7.73 kB
|
||||
dist/js/descriptions-BP4B3brJ.js 7.74 kB
|
||||
dist/js/conversations-BNlYvq_3.js 7.86 kB
|
||||
dist/js/icon-offline-f1WNoXZl.js 8.11 kB
|
||||
dist/js/useMaxLevel-C03eqd6z.js 8.16 kB
|
||||
dist/js/about-D2GlBBMu.js 8.61 kB
|
||||
dist/js/switch-CtSw_Hgg.js 8.85 kB
|
||||
dist/js/dist-DUuDCbWu.js 9.09 kB
|
||||
dist/js/vue-types-CFReUAWV.js 9.32 kB
|
||||
dist/js/icon-403-lLbU1N7U.js 9.41 kB
|
||||
dist/js/model-catalog-CIFENCQS.js 9.51 kB
|
||||
dist/js/AntdIcon-BN7vh055.js 9.67 kB
|
||||
dist/js/people-qBN9o8Fh.js 9.80 kB
|
||||
dist/js/modal-Ju-U4s3Q.js 9.82 kB
|
||||
dist/js/avatar-Df6A0OqG.js 10.24 kB
|
||||
dist/js/radio-CpXH5nLt.js 10.84 kB
|
||||
dist/js/release-Bqzc8_mc.js 11.74 kB
|
||||
dist/js/vc-virtual-list-DrQCcmQa.js 12.30 kB
|
||||
dist/js/button-B2y2NpJm.js 12.54 kB
|
||||
dist/js/style-Cw28xPuj.js 12.90 kB
|
||||
dist/js/icon-coming-soon-Di5CuiXP.js 12.91 kB
|
||||
dist/js/agents-B34lWKK9.js 13.06 kB
|
||||
dist/js/style-DuMcmENf.js 14.17 kB
|
||||
dist/js/desktop-config-DD30L8hd.js 14.30 kB
|
||||
dist/js/mentions-BBcMTLcD.js 14.43 kB
|
||||
dist/js/module-CyhaP5hi.js 14.48 kB
|
||||
dist/js/tooltip-DP9wufYH.js 14.61 kB
|
||||
dist/js/batch-dialog-C7bOLEk8.js 15.07 kB
|
||||
dist/js/progress-Br8rQILc.js 15.21 kB
|
||||
dist/js/drawer-CUkdSsdG.js 15.46 kB
|
||||
dist/js/preferences-zaQWU8vR.js 15.72 kB
|
||||
dist/js/select-DyNDAEL2.js 17.30 kB
|
||||
dist/js/call-stats-BfEi90FU.js 17.65 kB
|
||||
dist/js/dist-D5mNzO5q.js 20.16 kB
|
||||
dist/js/cascader-CJ-rRoA3.js 20.46 kB
|
||||
dist/js/input-number-B39v8Wj_.js 20.62 kB
|
||||
dist/js/tree-select-DuuuRFbI.js 20.68 kB
|
||||
dist/js/button-Cr_3AtOU.js 22.74 kB
|
||||
dist/js/image-I8Dw4v_6.js 23.31 kB
|
||||
dist/js/center-HpTMTDUz.js 23.99 kB
|
||||
dist/js/runtime-dom.esm-bundler-CirRHyjC.js 24.25 kB
|
||||
dist/js/icon-404-BI3hQ7ZR.js 24.36 kB
|
||||
dist/js/input-DgEff0DC.js 26.32 kB
|
||||
dist/js/cn-BpFrWzX2.js 27.30 kB
|
||||
dist/js/use-vben-form-Ci_vT-oC.js 28.39 kB
|
||||
dist/js/index.esm-DUQ5US9x.js 29.07 kB
|
||||
dist/js/job-wizard-QRJKD6Ml.js 29.10 kB
|
||||
dist/js/motion-d62SeGv9.js 34.66 kB
|
||||
dist/js/menu-QtUfh_QH.js 35.32 kB
|
||||
dist/js/upload-VFOuMjmy.js 36.93 kB
|
||||
dist/js/theme-toggle-DsxDItCJ.js 37.70 kB
|
||||
dist/js/style-CsqQHR1O.js 38.38 kB
|
||||
dist/js/config-provider-D1kcLCP5.js 39.10 kB
|
||||
dist/js/style-D8C_GS0s.js 39.14 kB
|
||||
dist/js/vue-router-WvyJJp1v.js 39.29 kB
|
||||
dist/js/vc-trigger-BzbjrH10.js 41.81 kB
|
||||
dist/js/login-BRxKLa70.js 44.58 kB
|
||||
dist/js/sortable.complete.esm-DPqKnM38.js 45.70 kB
|
||||
dist/js/useConfigInject-z_xeO0pP.js 48.02 kB
|
||||
dist/js/tippy-DY7-gSO2.js 51.03 kB
|
||||
dist/js/src-DxaB-oAj.js 52.95 kB
|
||||
dist/js/form-CZK1ilUa.js 57.54 kB
|
||||
dist/js/console-BEstjdZV.js 60.12 kB
|
||||
dist/js/icon-button-ShH4zO6U.js 73.90 kB
|
||||
dist/js/bootstrap-3hz92aGF.js 81.36 kB
|
||||
dist/js/runtime-core.esm-bundler-DkysjgTd.js 85.22 kB
|
||||
dist/js/generatePicker-DXnF1F4V.js 101.38 kB
|
||||
dist/js/auth-BlognHBz.js 119.83 kB
|
||||
dist/js/src-D78l4oCk.js 128.85 kB
|
||||
dist/js/table--97p0aBW.js 137.05 kB
|
||||
dist/js/store-DWy_0h89.js 156.39 kB
|
||||
dist/js/config-Bw_4j2RP.js 244.86 kB
|
||||
dist/js/basic-DtL3okpt.js 366.39 kB
|
||||
|
||||
✓ built in 13.28s
|
||||
ZIP file created: C:\kefu\admin-web\apps\web-antd\dist.zip (1132039 total bytes)
|
||||
Folder has been zipped to: C:\kefu\admin-web\apps\web-antd\dist.zip
|
||||
@@ -1,8 +0,0 @@
|
||||
/usr/local/lib/python3.12/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
已重建 1 条向量索引
|
||||
已重建 0 条向量索引
|
||||
----------------------------------------------------------------------
|
||||
Ran 72 tests in 15.480s
|
||||
|
||||
OK
|
||||
@@ -1,8 +0,0 @@
|
||||
/usr/local/lib/python3.12/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
已重建 1 条向量索引
|
||||
已重建 0 条向量索引
|
||||
----------------------------------------------------------------------
|
||||
Ran 81 tests in 18.445s
|
||||
|
||||
OK
|
||||
@@ -1,8 +0,0 @@
|
||||
/usr/local/lib/python3.12/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
已重建 1 条向量索引
|
||||
已重建 0 条向量索引
|
||||
----------------------------------------------------------------------
|
||||
Ran 92 tests in 22.432s
|
||||
|
||||
OK
|
||||
@@ -1,243 +0,0 @@
|
||||
$ pnpm vite build --mode production
|
||||
vite v8.2.1 building client environment for production...
|
||||
[2K
|
||||
transforming...✓ 7453 modules transformed.
|
||||
rendering chunks...
|
||||
✨configuration file is build successfully!
|
||||
dist/_app-config-5.7.0-7362080d.js 0.20 kB
|
||||
dist/index.html 3.35 kB
|
||||
dist/css/login-Cj5PKODp.css 0.06 kB
|
||||
dist/css/auth-zsf-kax4.css 0.38 kB
|
||||
dist/css/config-CYorFwo-.css 0.56 kB
|
||||
dist/css/loading-DXYS4l2z.css 0.56 kB
|
||||
dist/css/vue-router-CJxWTMt5.css 0.69 kB
|
||||
dist/css/theme-toggle-CJLHZmGO.css 1.63 kB
|
||||
dist/css/tippy-DkTQMyWH.css 6.65 kB
|
||||
dist/css/basic-CE2ii0IK.css 23.49 kB
|
||||
dist/css/bootstrap-Dn-qZ8jd.css 153.51 kB
|
||||
dist/js/_plugin-vue_export-helper-BDNMzG2s.js 0.08 kB
|
||||
dist/js/devWarning-DlchpATv.js 0.10 kB
|
||||
dist/js/motionUtil-BeNb4tZl.js 0.11 kB
|
||||
dist/js/vben-C1vbzhcL.js 0.12 kB
|
||||
dist/js/omit-C0ksMpVM.js 0.14 kB
|
||||
dist/js/profile-B411QZNQ.js 0.15 kB
|
||||
dist/js/profile-tkuLhW9J.js 0.15 kB
|
||||
dist/js/useState-DlRKQDQX.js 0.16 kB
|
||||
dist/js/warning-BLl3S_cO.js 0.17 kB
|
||||
dist/js/useMemo-m5GuU0Kd.js 0.17 kB
|
||||
dist/js/useRefs-QDevZzkt.js 0.17 kB
|
||||
dist/js/useFlexGapSupport-D07fCJnk.js 0.18 kB
|
||||
dist/js/rotate-cw-CyWoHUpq.js 0.19 kB
|
||||
dist/js/Keyframes-K60KFfv3.js 0.20 kB
|
||||
dist/js/isVisible-B1N4qR6W.js 0.23 kB
|
||||
dist/js/coming-soon-C9te2Fo9.js 0.23 kB
|
||||
dist/js/initDefaultProps-D8Mki4gM.js 0.25 kB
|
||||
dist/js/useBreakpoint-4zwrQO2u.js 0.26 kB
|
||||
dist/js/page-DM9HIydN.js 0.27 kB
|
||||
dist/js/createContext-LBMERH-r.js 0.28 kB
|
||||
dist/js/page-YH8FPpYF.js 0.28 kB
|
||||
dist/js/src-DS89XIkw.js 0.28 kB
|
||||
dist/js/statusUtils-WKRwVnP6.js 0.29 kB
|
||||
dist/js/src-DkoRg56f.js 0.30 kB
|
||||
dist/js/forbidden-Bmiwnz_B.js 0.31 kB
|
||||
dist/js/not-found-CmXcaUT6.js 0.31 kB
|
||||
dist/js/internal-error-CMwA7W1E.js 0.31 kB
|
||||
dist/js/offline-Dx824lFG.js 0.31 kB
|
||||
dist/js/demos-Bb7WGJxd.js 0.32 kB
|
||||
dist/js/demos-BSnMPpZY.js 0.32 kB
|
||||
dist/js/download-DUHREPuF.js 0.42 kB
|
||||
dist/js/_arrayIncludesWith-D3sQWlhs.js 0.43 kB
|
||||
dist/js/isPlainObject-iVjSthyR.js 0.43 kB
|
||||
dist/js/raf-CR9Bw2Uc.js 0.45 kB
|
||||
dist/js/auth-title-DCLZf2Gr.js 0.48 kB
|
||||
dist/js/useMergedState-zH37e67U.js 0.49 kB
|
||||
dist/js/css-BflejRyY.js 0.50 kB
|
||||
dist/js/shallowequal-D7g0B-CQ.js 0.52 kB
|
||||
dist/js/extends-C_p2ba5S.js 0.52 kB
|
||||
dist/js/use-archive-load-BINKTMOh.js 0.52 kB
|
||||
dist/js/en-DA5aUWwj.js 0.58 kB
|
||||
dist/js/date-picker-C1ofm_9t.js 0.59 kB
|
||||
dist/js/render-content-3dfOk9Gq.js 0.59 kB
|
||||
dist/js/isObjectLike-DNah0Hql.js 0.66 kB
|
||||
dist/js/use-access-CQdD7p8C.js 0.69 kB
|
||||
dist/js/objectWithoutProperties-BjoYlK0I.js 0.69 kB
|
||||
dist/js/merge-C-fCyOMx.js 0.69 kB
|
||||
dist/js/defu-1oANYd5X.js 0.70 kB
|
||||
dist/js/rolldown-runtime-hePW80VL.js 0.71 kB
|
||||
dist/js/styleChecker-CeGG85sE.js 0.79 kB
|
||||
dist/js/useApi-CROJJdhE-oP73ypFI.js 0.83 kB
|
||||
dist/js/common-DWRZ7B_7.js 0.85 kB
|
||||
dist/js/common-BE0LVHtH.js 0.88 kB
|
||||
dist/js/Primitive-Bi_oIzTM.js 0.90 kB
|
||||
dist/js/compact-item-BbW5OmKl.js 0.94 kB
|
||||
dist/js/batch-xzXgOops.js 1.00 kB
|
||||
dist/js/LeftOutlined-HmT5OMoh.js 1.01 kB
|
||||
dist/js/RightOutlined-DwLwVX1C.js 1.01 kB
|
||||
dist/js/DownOutlined-Cq6F7QWr.js 1.01 kB
|
||||
dist/js/vnode-CRVBf7wj.js 1.01 kB
|
||||
dist/js/CheckOutlined-Dy5-Q7N5.js 1.01 kB
|
||||
dist/js/FormItemContext-CEmO5XmM.js 1.11 kB
|
||||
dist/js/CheckCircleFilled-CvJ3C2gR.js 1.11 kB
|
||||
dist/js/LoadingOutlined-tpSKTswf.js 1.15 kB
|
||||
dist/js/preload-helper-DaercurD.js 1.22 kB
|
||||
dist/js/objectSpread2-BmonrgTA.js 1.29 kB
|
||||
dist/js/_baseIteratee-NxSP5AT6.js 1.29 kB
|
||||
dist/js/EyeOutlined-w8ODygj3.js 1.30 kB
|
||||
dist/js/ActionButton-DlhIPLDf.js 1.33 kB
|
||||
dist/js/SearchOutlined-CndaZ08h.js 1.34 kB
|
||||
dist/js/loading-Cw3fZBrE.js 1.35 kB
|
||||
dist/js/knowledge-DQ4Davea.js 1.40 kB
|
||||
dist/js/collapseMotion-BfalGvoQ.js 1.47 kB
|
||||
dist/js/CloseOutlined-BdX5pn5u.js 1.48 kB
|
||||
dist/js/colors-C2RrYxlT.js 1.48 kB
|
||||
dist/js/zh-cn-DTVg5rYV.js 1.52 kB
|
||||
dist/js/CloseCircleFilled-C9x0ZM0q.js 1.56 kB
|
||||
dist/js/debounce-DNW4oWi1.js 1.58 kB
|
||||
dist/js/archive-account-selector-BXFRdqNp.js 1.63 kB
|
||||
dist/js/notification-setting-7bFohVCQ.js 1.69 kB
|
||||
dist/js/page-CuTJnSJp.js 1.70 kB
|
||||
dist/js/audit-nFpknLL4.js 1.75 kB
|
||||
dist/js/base-setting-DMOVS08n.js 1.82 kB
|
||||
dist/js/security-setting-C-Wxwv7E.js 1.90 kB
|
||||
dist/js/slide-D__jeCTu.js 1.92 kB
|
||||
dist/js/move-kOZGsaQl.js 1.96 kB
|
||||
dist/js/password-setting-BzxgKWpd.js 1.98 kB
|
||||
dist/js/archive-PnuNQRb2.js 1.99 kB
|
||||
dist/js/KeyCode-DNtAKsAc.js 2.00 kB
|
||||
dist/js/change-password-CVTTiJu_.js 2.06 kB
|
||||
dist/js/hasIn-BIluNPSA.js 2.06 kB
|
||||
dist/js/isMobile-DH4W6rzp.js 2.09 kB
|
||||
dist/js/pickAttrs-SF6-8m9R.js 2.18 kB
|
||||
dist/js/Portal-jWUJieln.js 2.26 kB
|
||||
dist/js/space-B06wu9Uj.js 2.30 kB
|
||||
dist/js/forget-password-rFqeb0Do.js 2.31 kB
|
||||
dist/js/zoom-C1lAvwDy.js 2.37 kB
|
||||
dist/js/Checkbox-CaX94bng.js 2.41 kB
|
||||
dist/js/time-picker-G9rC4smS.js 2.60 kB
|
||||
dist/js/dist-zStm9ma4.js 2.70 kB
|
||||
dist/js/responsiveObserve-CPvTZIYq.js 2.70 kB
|
||||
dist/js/job-config-DzbV-mmB.js 2.89 kB
|
||||
dist/js/use-preferences-2Ls4-wCJ.js 2.91 kB
|
||||
dist/js/auto-complete-UyB6Un0I.js 2.95 kB
|
||||
dist/js/Compact-Icyx2uFm.js 3.04 kB
|
||||
dist/js/model-fields-Xga1YJmB.js 3.15 kB
|
||||
dist/js/FormLabel-CiUM-Zyy.js 3.27 kB
|
||||
dist/js/authentication-DmobrOr_.js 3.37 kB
|
||||
dist/js/fallback-B3eN2qYq.js 3.37 kB
|
||||
dist/js/register-Blo6FBMi.js 3.40 kB
|
||||
dist/js/authentication-BYliOcm3.js 3.53 kB
|
||||
dist/js/divider-B8AbMF6d.js 3.58 kB
|
||||
dist/js/_getTag-2z2WZcIh.js 3.72 kB
|
||||
dist/js/wave-BBnUlIB_.js 3.82 kB
|
||||
dist/js/style-DQ50flCp.js 3.88 kB
|
||||
dist/js/Switch-DRsr_95y.js 3.96 kB
|
||||
dist/js/users-BEuwQv7Z.js 4.07 kB
|
||||
dist/js/profile-DVrkm3XP.js 4.07 kB
|
||||
dist/js/overview-B1FTe1Rt.js 4.14 kB
|
||||
dist/js/en_US-Cv9hrLhb.js 4.17 kB
|
||||
dist/js/nprogress-CcparBbP.js 4.18 kB
|
||||
dist/js/motion-BmOd6fTF.js 4.38 kB
|
||||
dist/js/ui-NNY_r1AM.js 4.39 kB
|
||||
dist/js/row-CWbUMMds.js 4.44 kB
|
||||
dist/js/ui-CCmUukCu.js 4.64 kB
|
||||
dist/js/BaseInput-D9ryi2LY.js 4.67 kB
|
||||
dist/js/tag-BFecLZmQ.js 4.83 kB
|
||||
dist/js/checkbox-DbdxvqS7.js 4.83 kB
|
||||
dist/js/vue.runtime.esm-bundler-DXMo22CJ.js 4.95 kB
|
||||
dist/js/exports-DMoGP0Jo.js 5.02 kB
|
||||
dist/jse/index-index-DcSn0tss.js 5.12 kB
|
||||
dist/js/roles-CDwxCB87.js 5.26 kB
|
||||
dist/js/alert-CkUknOsQ.js 5.34 kB
|
||||
dist/js/model-plan-C3OyTWOx.js 5.38 kB
|
||||
dist/js/Col-8hLsgOob.js 5.55 kB
|
||||
dist/js/VisuallyHiddenInput-CDz4_yZw.js 5.82 kB
|
||||
dist/js/core-CY2B_m7j.js 6.17 kB
|
||||
dist/js/storage-C7VfUrIU.js 6.30 kB
|
||||
dist/js/desktop-accounts-CmIo3sUI.js 6.34 kB
|
||||
dist/js/spin-3P-IVef6.js 6.52 kB
|
||||
dist/js/vc-overflow-DrtZeojQ.js 6.58 kB
|
||||
dist/js/icon-500-z_hKUj8N.js 7.10 kB
|
||||
dist/js/dayjs.min-DCUUuXM3.js 7.18 kB
|
||||
dist/js/rate-DdROH9ca.js 7.42 kB
|
||||
dist/js/popconfirm-BqMuKaMZ.js 7.43 kB
|
||||
dist/js/ResizeObserver.es-DbHj_W6-.js 7.62 kB
|
||||
dist/js/preferences-C8rVqNJ_.js 7.71 kB
|
||||
dist/js/preferences-Dy8TIlZp.js 7.73 kB
|
||||
dist/js/descriptions-BP4B3brJ.js 7.74 kB
|
||||
dist/js/conversations-BCu39QtV.js 7.89 kB
|
||||
dist/js/icon-offline-f1WNoXZl.js 8.11 kB
|
||||
dist/js/useMaxLevel-C03eqd6z.js 8.16 kB
|
||||
dist/js/about-De3lebFa.js 8.61 kB
|
||||
dist/js/switch-CtSw_Hgg.js 8.85 kB
|
||||
dist/js/dist-DUuDCbWu.js 9.09 kB
|
||||
dist/js/vue-types-CFReUAWV.js 9.32 kB
|
||||
dist/js/icon-403-lLbU1N7U.js 9.41 kB
|
||||
dist/js/model-catalog-CQksAdhH.js 9.55 kB
|
||||
dist/js/AntdIcon-BN7vh055.js 9.67 kB
|
||||
dist/js/modal-Ju-U4s3Q.js 9.82 kB
|
||||
dist/js/people-DVQx0_K5.js 9.83 kB
|
||||
dist/js/review-all-D2syOqfb.js 10.22 kB
|
||||
dist/js/avatar-Df6A0OqG.js 10.24 kB
|
||||
dist/js/radio-CpXH5nLt.js 10.84 kB
|
||||
dist/js/release-B5hsQIt3.js 11.77 kB
|
||||
dist/js/vc-virtual-list-DrQCcmQa.js 12.30 kB
|
||||
dist/js/button-B2y2NpJm.js 12.54 kB
|
||||
dist/js/style-Cw28xPuj.js 12.90 kB
|
||||
dist/js/icon-coming-soon-Di5CuiXP.js 12.91 kB
|
||||
dist/js/agents-BZhjoh24.js 13.09 kB
|
||||
dist/js/style-DuMcmENf.js 14.17 kB
|
||||
dist/js/desktop-config-D36icTC9.js 14.33 kB
|
||||
dist/js/mentions-BBcMTLcD.js 14.43 kB
|
||||
dist/js/module-CyhaP5hi.js 14.48 kB
|
||||
dist/js/batch-dialog-S_PJXJRX.js 14.57 kB
|
||||
dist/js/tooltip-DP9wufYH.js 14.61 kB
|
||||
dist/js/progress-Br8rQILc.js 15.21 kB
|
||||
dist/js/drawer-CUkdSsdG.js 15.46 kB
|
||||
dist/js/preferences-zaQWU8vR.js 15.72 kB
|
||||
dist/js/select-DyNDAEL2.js 17.30 kB
|
||||
dist/js/call-stats-XKI4bGxc.js 17.68 kB
|
||||
dist/js/card-BGR88GeQ.js 18.54 kB
|
||||
dist/js/dist-D5mNzO5q.js 20.16 kB
|
||||
dist/js/cascader-CJ-rRoA3.js 20.46 kB
|
||||
dist/js/input-number-B39v8Wj_.js 20.62 kB
|
||||
dist/js/tree-select-DuuuRFbI.js 20.68 kB
|
||||
dist/js/button-Cr_3AtOU.js 22.74 kB
|
||||
dist/js/image-I8Dw4v_6.js 23.31 kB
|
||||
dist/js/runtime-dom.esm-bundler-CirRHyjC.js 24.25 kB
|
||||
dist/js/icon-404-BI3hQ7ZR.js 24.36 kB
|
||||
dist/js/input-DgEff0DC.js 26.32 kB
|
||||
dist/js/center-CHgL7u3T.js 27.14 kB
|
||||
dist/js/cn-BpFrWzX2.js 27.30 kB
|
||||
dist/js/use-vben-form-Ci_vT-oC.js 28.39 kB
|
||||
dist/js/index.esm-DUQ5US9x.js 29.07 kB
|
||||
dist/js/job-wizard-BVYvaan2.js 29.23 kB
|
||||
dist/js/motion-d62SeGv9.js 34.66 kB
|
||||
dist/js/menu-QtUfh_QH.js 35.32 kB
|
||||
dist/js/upload-VFOuMjmy.js 36.93 kB
|
||||
dist/js/theme-toggle-DsxDItCJ.js 37.70 kB
|
||||
dist/js/style-CsqQHR1O.js 38.38 kB
|
||||
dist/js/config-provider-D1kcLCP5.js 39.10 kB
|
||||
dist/js/style-D8C_GS0s.js 39.14 kB
|
||||
dist/js/vue-router-WvyJJp1v.js 39.29 kB
|
||||
dist/js/vc-trigger-BzbjrH10.js 41.81 kB
|
||||
dist/js/console-BcQppt6y.js 41.93 kB
|
||||
dist/js/login-BRxKLa70.js 44.58 kB
|
||||
dist/js/sortable.complete.esm-DPqKnM38.js 45.70 kB
|
||||
dist/js/useConfigInject-z_xeO0pP.js 48.02 kB
|
||||
dist/js/tippy-DY7-gSO2.js 51.03 kB
|
||||
dist/js/src-DxaB-oAj.js 52.95 kB
|
||||
dist/js/form-CZK1ilUa.js 57.54 kB
|
||||
dist/js/icon-button-ShH4zO6U.js 73.90 kB
|
||||
dist/js/bootstrap-DLVvLJ7g.js 82.90 kB
|
||||
dist/js/runtime-core.esm-bundler-DkysjgTd.js 85.22 kB
|
||||
dist/js/generatePicker-DXnF1F4V.js 101.38 kB
|
||||
dist/js/auth-BlognHBz.js 119.83 kB
|
||||
dist/js/src-D78l4oCk.js 128.85 kB
|
||||
dist/js/table-D8C-izWj.js 137.05 kB
|
||||
dist/js/store-DWy_0h89.js 156.39 kB
|
||||
dist/js/config-Bw_4j2RP.js 244.86 kB
|
||||
dist/js/basic-DtL3okpt.js 366.39 kB
|
||||
|
||||
✓ built in 11.39s
|
||||
ZIP file created: C:\kefu\admin-web\apps\web-antd\dist.zip (1142929 total bytes)
|
||||
Folder has been zipped to: C:\kefu\admin-web\apps\web-antd\dist.zip
|
||||
@@ -1 +0,0 @@
|
||||
$ vue-tsc --noEmit --skipLibCheck
|
||||
@@ -1,8 +0,0 @@
|
||||
/usr/local/lib/python3.12/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
已重建 1 条向量索引
|
||||
已重建 0 条向量索引
|
||||
----------------------------------------------------------------------
|
||||
Ran 96 tests in 26.280s
|
||||
|
||||
OK
|
||||
@@ -1,243 +0,0 @@
|
||||
$ pnpm vite build --mode production
|
||||
vite v8.2.1 building client environment for production...
|
||||
[2K
|
||||
transforming...✓ 7454 modules transformed.
|
||||
rendering chunks...
|
||||
✨configuration file is build successfully!
|
||||
dist/_app-config-5.7.0-7362080d.js 0.20 kB
|
||||
dist/index.html 3.35 kB
|
||||
dist/css/login-Cj5PKODp.css 0.06 kB
|
||||
dist/css/auth-zsf-kax4.css 0.38 kB
|
||||
dist/css/config-CYorFwo-.css 0.56 kB
|
||||
dist/css/loading-DXYS4l2z.css 0.56 kB
|
||||
dist/css/vue-router-CJxWTMt5.css 0.69 kB
|
||||
dist/css/theme-toggle-CJLHZmGO.css 1.63 kB
|
||||
dist/css/tippy-DkTQMyWH.css 6.65 kB
|
||||
dist/css/basic-CE2ii0IK.css 23.49 kB
|
||||
dist/css/bootstrap-Dn-qZ8jd.css 153.51 kB
|
||||
dist/js/_plugin-vue_export-helper-BDNMzG2s.js 0.08 kB
|
||||
dist/js/devWarning-DlchpATv.js 0.10 kB
|
||||
dist/js/motionUtil-BeNb4tZl.js 0.11 kB
|
||||
dist/js/vben-C1vbzhcL.js 0.12 kB
|
||||
dist/js/omit-C0ksMpVM.js 0.14 kB
|
||||
dist/js/profile-B411QZNQ.js 0.15 kB
|
||||
dist/js/profile-tkuLhW9J.js 0.15 kB
|
||||
dist/js/useState-DlRKQDQX.js 0.16 kB
|
||||
dist/js/warning-BLl3S_cO.js 0.17 kB
|
||||
dist/js/useMemo-m5GuU0Kd.js 0.17 kB
|
||||
dist/js/useRefs-QDevZzkt.js 0.17 kB
|
||||
dist/js/useFlexGapSupport-D07fCJnk.js 0.18 kB
|
||||
dist/js/rotate-cw-CyWoHUpq.js 0.19 kB
|
||||
dist/js/Keyframes-K60KFfv3.js 0.20 kB
|
||||
dist/js/isVisible-B1N4qR6W.js 0.23 kB
|
||||
dist/js/coming-soon-C9te2Fo9.js 0.23 kB
|
||||
dist/js/initDefaultProps-D8Mki4gM.js 0.25 kB
|
||||
dist/js/useBreakpoint-4zwrQO2u.js 0.26 kB
|
||||
dist/js/page-DM9HIydN.js 0.27 kB
|
||||
dist/js/createContext-LBMERH-r.js 0.28 kB
|
||||
dist/js/page-YH8FPpYF.js 0.28 kB
|
||||
dist/js/src-DS89XIkw.js 0.28 kB
|
||||
dist/js/statusUtils-WKRwVnP6.js 0.29 kB
|
||||
dist/js/src-DkoRg56f.js 0.30 kB
|
||||
dist/js/forbidden-Bmiwnz_B.js 0.31 kB
|
||||
dist/js/not-found-CmXcaUT6.js 0.31 kB
|
||||
dist/js/internal-error-CMwA7W1E.js 0.31 kB
|
||||
dist/js/offline-Dx824lFG.js 0.31 kB
|
||||
dist/js/demos-Bb7WGJxd.js 0.32 kB
|
||||
dist/js/demos-BSnMPpZY.js 0.32 kB
|
||||
dist/js/download-DUHREPuF.js 0.42 kB
|
||||
dist/js/_arrayIncludesWith-D3sQWlhs.js 0.43 kB
|
||||
dist/js/isPlainObject-iVjSthyR.js 0.43 kB
|
||||
dist/js/raf-CR9Bw2Uc.js 0.45 kB
|
||||
dist/js/auth-title-DCLZf2Gr.js 0.48 kB
|
||||
dist/js/useMergedState-zH37e67U.js 0.49 kB
|
||||
dist/js/css-BflejRyY.js 0.50 kB
|
||||
dist/js/shallowequal-D7g0B-CQ.js 0.52 kB
|
||||
dist/js/extends-C_p2ba5S.js 0.52 kB
|
||||
dist/js/use-archive-load-BINKTMOh.js 0.52 kB
|
||||
dist/js/en-DA5aUWwj.js 0.58 kB
|
||||
dist/js/date-picker-C1ofm_9t.js 0.59 kB
|
||||
dist/js/render-content-3dfOk9Gq.js 0.59 kB
|
||||
dist/js/isObjectLike-DNah0Hql.js 0.66 kB
|
||||
dist/js/use-access-ObRBpYsT.js 0.69 kB
|
||||
dist/js/objectWithoutProperties-BjoYlK0I.js 0.69 kB
|
||||
dist/js/merge-C-fCyOMx.js 0.69 kB
|
||||
dist/js/defu-1oANYd5X.js 0.70 kB
|
||||
dist/js/rolldown-runtime-hePW80VL.js 0.71 kB
|
||||
dist/js/styleChecker-CeGG85sE.js 0.79 kB
|
||||
dist/js/useApi-CROJJdhE-oP73ypFI.js 0.83 kB
|
||||
dist/js/common-DWRZ7B_7.js 0.85 kB
|
||||
dist/js/common-BE0LVHtH.js 0.88 kB
|
||||
dist/js/Primitive-Bi_oIzTM.js 0.90 kB
|
||||
dist/js/compact-item-BbW5OmKl.js 0.94 kB
|
||||
dist/js/batch-xzXgOops.js 1.00 kB
|
||||
dist/js/LeftOutlined-HmT5OMoh.js 1.01 kB
|
||||
dist/js/RightOutlined-DwLwVX1C.js 1.01 kB
|
||||
dist/js/DownOutlined-Cq6F7QWr.js 1.01 kB
|
||||
dist/js/vnode-CRVBf7wj.js 1.01 kB
|
||||
dist/js/CheckOutlined-Dy5-Q7N5.js 1.01 kB
|
||||
dist/js/FormItemContext-CEmO5XmM.js 1.11 kB
|
||||
dist/js/CheckCircleFilled-CvJ3C2gR.js 1.11 kB
|
||||
dist/js/LoadingOutlined-tpSKTswf.js 1.15 kB
|
||||
dist/js/preload-helper-DaercurD.js 1.22 kB
|
||||
dist/js/objectSpread2-BmonrgTA.js 1.29 kB
|
||||
dist/js/_baseIteratee-NxSP5AT6.js 1.29 kB
|
||||
dist/js/EyeOutlined-w8ODygj3.js 1.30 kB
|
||||
dist/js/ActionButton-DlhIPLDf.js 1.33 kB
|
||||
dist/js/SearchOutlined-CndaZ08h.js 1.34 kB
|
||||
dist/js/loading-Cw3fZBrE.js 1.35 kB
|
||||
dist/js/knowledge-roQbw_jw.js 1.40 kB
|
||||
dist/js/collapseMotion-BfalGvoQ.js 1.47 kB
|
||||
dist/js/CloseOutlined-BdX5pn5u.js 1.48 kB
|
||||
dist/js/colors-C2RrYxlT.js 1.48 kB
|
||||
dist/js/zh-cn-DTVg5rYV.js 1.52 kB
|
||||
dist/js/CloseCircleFilled-C9x0ZM0q.js 1.56 kB
|
||||
dist/js/debounce-DNW4oWi1.js 1.58 kB
|
||||
dist/js/archive-account-selector-CnQ_KU9I.js 1.63 kB
|
||||
dist/js/notification-setting-7bFohVCQ.js 1.69 kB
|
||||
dist/js/page-CuTJnSJp.js 1.70 kB
|
||||
dist/js/audit-CFwX846O.js 1.75 kB
|
||||
dist/js/base-setting-CG3mjOo-.js 1.82 kB
|
||||
dist/js/security-setting-C-Wxwv7E.js 1.90 kB
|
||||
dist/js/slide-D__jeCTu.js 1.92 kB
|
||||
dist/js/move-kOZGsaQl.js 1.96 kB
|
||||
dist/js/password-setting-BzxgKWpd.js 1.98 kB
|
||||
dist/js/archive-CtN8mksn.js 1.99 kB
|
||||
dist/js/KeyCode-DNtAKsAc.js 2.00 kB
|
||||
dist/js/change-password-u5_YQADa.js 2.06 kB
|
||||
dist/js/hasIn-BIluNPSA.js 2.06 kB
|
||||
dist/js/isMobile-DH4W6rzp.js 2.09 kB
|
||||
dist/js/pickAttrs-SF6-8m9R.js 2.18 kB
|
||||
dist/js/Portal-jWUJieln.js 2.26 kB
|
||||
dist/js/space-B06wu9Uj.js 2.30 kB
|
||||
dist/js/forget-password-rFqeb0Do.js 2.31 kB
|
||||
dist/js/zoom-C1lAvwDy.js 2.37 kB
|
||||
dist/js/Checkbox-CaX94bng.js 2.41 kB
|
||||
dist/js/time-picker-G9rC4smS.js 2.60 kB
|
||||
dist/js/dist-zStm9ma4.js 2.70 kB
|
||||
dist/js/responsiveObserve-CPvTZIYq.js 2.70 kB
|
||||
dist/js/job-config-pSe-zaQB.js 2.89 kB
|
||||
dist/js/use-preferences-2Ls4-wCJ.js 2.91 kB
|
||||
dist/js/auto-complete-UyB6Un0I.js 2.95 kB
|
||||
dist/js/Compact-Icyx2uFm.js 3.04 kB
|
||||
dist/js/model-fields-BCrJLCzI.js 3.15 kB
|
||||
dist/js/FormLabel-CiUM-Zyy.js 3.27 kB
|
||||
dist/js/authentication-DmobrOr_.js 3.37 kB
|
||||
dist/js/fallback-B3eN2qYq.js 3.37 kB
|
||||
dist/js/register-Blo6FBMi.js 3.40 kB
|
||||
dist/js/authentication-BYliOcm3.js 3.53 kB
|
||||
dist/js/divider-B8AbMF6d.js 3.58 kB
|
||||
dist/js/_getTag-2z2WZcIh.js 3.72 kB
|
||||
dist/js/wave-BBnUlIB_.js 3.82 kB
|
||||
dist/js/style-DQ50flCp.js 3.88 kB
|
||||
dist/js/Switch-DRsr_95y.js 3.96 kB
|
||||
dist/js/users-BP-5rQbz.js 4.07 kB
|
||||
dist/js/profile-NNtwd5IV.js 4.07 kB
|
||||
dist/js/overview-DZftG1qL.js 4.14 kB
|
||||
dist/js/en_US-Cv9hrLhb.js 4.17 kB
|
||||
dist/js/nprogress-CcparBbP.js 4.18 kB
|
||||
dist/js/motion-BmOd6fTF.js 4.38 kB
|
||||
dist/js/ui-NNY_r1AM.js 4.39 kB
|
||||
dist/js/row-DtpYqXpD.js 4.44 kB
|
||||
dist/js/ui-CCmUukCu.js 4.64 kB
|
||||
dist/js/BaseInput-D9ryi2LY.js 4.67 kB
|
||||
dist/js/tag-BFecLZmQ.js 4.83 kB
|
||||
dist/js/checkbox-DbdxvqS7.js 4.83 kB
|
||||
dist/js/vue.runtime.esm-bundler-DXMo22CJ.js 4.95 kB
|
||||
dist/js/exports-D9vFgtus.js 5.02 kB
|
||||
dist/jse/index-index-bPpBQ29w.js 5.12 kB
|
||||
dist/js/roles-CUL9UuFy.js 5.26 kB
|
||||
dist/js/alert-CkUknOsQ.js 5.34 kB
|
||||
dist/js/model-plan-Drq3agYm.js 5.38 kB
|
||||
dist/js/Col-8hLsgOob.js 5.55 kB
|
||||
dist/js/VisuallyHiddenInput-CDz4_yZw.js 5.82 kB
|
||||
dist/js/core-CY2B_m7j.js 6.17 kB
|
||||
dist/js/storage-BgBQ6eCL.js 6.30 kB
|
||||
dist/js/desktop-accounts-BMlFY6eN.js 6.34 kB
|
||||
dist/js/spin-3P-IVef6.js 6.52 kB
|
||||
dist/js/vc-overflow-DrtZeojQ.js 6.58 kB
|
||||
dist/js/icon-500-z_hKUj8N.js 7.10 kB
|
||||
dist/js/dayjs.min-DCUUuXM3.js 7.18 kB
|
||||
dist/js/rate-DdROH9ca.js 7.42 kB
|
||||
dist/js/popconfirm-BqMuKaMZ.js 7.43 kB
|
||||
dist/js/ResizeObserver.es-DbHj_W6-.js 7.62 kB
|
||||
dist/js/preferences-C8rVqNJ_.js 7.71 kB
|
||||
dist/js/preferences-Dy8TIlZp.js 7.73 kB
|
||||
dist/js/descriptions-BP4B3brJ.js 7.74 kB
|
||||
dist/js/conversations-B3kHiByx.js 7.89 kB
|
||||
dist/js/icon-offline-f1WNoXZl.js 8.11 kB
|
||||
dist/js/useMaxLevel-C03eqd6z.js 8.16 kB
|
||||
dist/js/about-BwTyhIv_.js 8.61 kB
|
||||
dist/js/switch-CtSw_Hgg.js 8.85 kB
|
||||
dist/js/dist-DUuDCbWu.js 9.09 kB
|
||||
dist/js/vue-types-CFReUAWV.js 9.32 kB
|
||||
dist/js/icon-403-lLbU1N7U.js 9.41 kB
|
||||
dist/js/model-catalog-HzgLIKeD.js 9.55 kB
|
||||
dist/js/AntdIcon-BN7vh055.js 9.67 kB
|
||||
dist/js/modal-Ju-U4s3Q.js 9.82 kB
|
||||
dist/js/people-DJI1Lbvv.js 9.83 kB
|
||||
dist/js/review-all-DOQAMi8J.js 10.22 kB
|
||||
dist/js/avatar-Df6A0OqG.js 10.24 kB
|
||||
dist/js/radio-CpXH5nLt.js 10.84 kB
|
||||
dist/js/release-LqQppPlc.js 11.77 kB
|
||||
dist/js/vc-virtual-list-DrQCcmQa.js 12.30 kB
|
||||
dist/js/button-B2y2NpJm.js 12.54 kB
|
||||
dist/js/style-Cw28xPuj.js 12.90 kB
|
||||
dist/js/icon-coming-soon-Di5CuiXP.js 12.91 kB
|
||||
dist/js/agents-DOkZv4_n.js 13.09 kB
|
||||
dist/js/style-DuMcmENf.js 14.17 kB
|
||||
dist/js/desktop-config-xkW3HAeC.js 14.33 kB
|
||||
dist/js/mentions-BBcMTLcD.js 14.43 kB
|
||||
dist/js/module-CyhaP5hi.js 14.48 kB
|
||||
dist/js/batch-dialog-mXmjBwWX.js 14.57 kB
|
||||
dist/js/tooltip-DP9wufYH.js 14.61 kB
|
||||
dist/js/progress-Br8rQILc.js 15.21 kB
|
||||
dist/js/drawer-CUkdSsdG.js 15.46 kB
|
||||
dist/js/preferences-zaQWU8vR.js 15.72 kB
|
||||
dist/js/select-DyNDAEL2.js 17.30 kB
|
||||
dist/js/call-stats-Bc096pQl.js 17.68 kB
|
||||
dist/js/card-ZuLu6CvW.js 18.54 kB
|
||||
dist/js/dist-D5mNzO5q.js 20.16 kB
|
||||
dist/js/cascader-CJ-rRoA3.js 20.46 kB
|
||||
dist/js/input-number-B39v8Wj_.js 20.62 kB
|
||||
dist/js/tree-select-DuuuRFbI.js 20.68 kB
|
||||
dist/js/button-Cr_3AtOU.js 22.74 kB
|
||||
dist/js/image-I8Dw4v_6.js 23.31 kB
|
||||
dist/js/runtime-dom.esm-bundler-CirRHyjC.js 24.25 kB
|
||||
dist/js/icon-404-BI3hQ7ZR.js 24.36 kB
|
||||
dist/js/input-DgEff0DC.js 26.32 kB
|
||||
dist/js/cn-BpFrWzX2.js 27.30 kB
|
||||
dist/js/center-BLfUvenl.js 28.08 kB
|
||||
dist/js/use-vben-form-Ci_vT-oC.js 28.39 kB
|
||||
dist/js/index.esm-DUQ5US9x.js 29.07 kB
|
||||
dist/js/job-wizard-Db2QVhyM.js 29.23 kB
|
||||
dist/js/motion-d62SeGv9.js 34.66 kB
|
||||
dist/js/menu-QtUfh_QH.js 35.32 kB
|
||||
dist/js/upload-VFOuMjmy.js 36.93 kB
|
||||
dist/js/theme-toggle-DsxDItCJ.js 37.70 kB
|
||||
dist/js/style-CsqQHR1O.js 38.38 kB
|
||||
dist/js/config-provider-D1kcLCP5.js 39.10 kB
|
||||
dist/js/style-D8C_GS0s.js 39.14 kB
|
||||
dist/js/vue-router-WvyJJp1v.js 39.29 kB
|
||||
dist/js/vc-trigger-BzbjrH10.js 41.81 kB
|
||||
dist/js/console-CQVAqHCG.js 41.93 kB
|
||||
dist/js/login-Qq0I6FOe.js 44.58 kB
|
||||
dist/js/sortable.complete.esm-DPqKnM38.js 45.70 kB
|
||||
dist/js/useConfigInject-z_xeO0pP.js 48.02 kB
|
||||
dist/js/tippy-DY7-gSO2.js 51.03 kB
|
||||
dist/js/src-DxaB-oAj.js 52.95 kB
|
||||
dist/js/form-CZK1ilUa.js 57.54 kB
|
||||
dist/js/icon-button-ShH4zO6U.js 73.90 kB
|
||||
dist/js/bootstrap-CTi-rZ4b.js 82.87 kB
|
||||
dist/js/runtime-core.esm-bundler-DkysjgTd.js 85.22 kB
|
||||
dist/js/generatePicker-DXnF1F4V.js 101.38 kB
|
||||
dist/js/auth-BlognHBz.js 119.83 kB
|
||||
dist/js/src-D78l4oCk.js 128.85 kB
|
||||
dist/js/table-EWhwMmEC.js 137.05 kB
|
||||
dist/js/store-B2VrBUyT.js 157.28 kB
|
||||
dist/js/config-Bw_4j2RP.js 244.86 kB
|
||||
dist/js/basic-BOTTV4P4.js 366.39 kB
|
||||
|
||||
✓ built in 15.62s
|
||||
ZIP file created: C:\kefu\admin-web\apps\web-antd\dist.zip (1143712 total bytes)
|
||||
Folder has been zipped to: C:\kefu\admin-web\apps\web-antd\dist.zip
|
||||
@@ -1 +0,0 @@
|
||||
$ vue-tsc --noEmit --skipLibCheck
|
||||
@@ -1,253 +0,0 @@
|
||||
Build Python: C:\wechat_rpa\.build-venv\Scripts\python.exe
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_final.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_media.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_voice2text.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_crypto.py -> archive_exporter
|
||||
217 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
217 INFO: Python: 3.12.14
|
||||
263 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
263 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
267 INFO: Removing temporary files and cleaning cache in C:\kefu\deploy\listener-continuity-20260917\build-self-check-profile\Local\pyinstaller
|
||||
2369 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
3014 INFO: Appending 'binaries' from .spec
|
||||
3014 INFO: Appending 'datas' from .spec
|
||||
3016 INFO: checking Analysis
|
||||
3016 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
3016 INFO: Looking for Python shared library...
|
||||
3016 INFO: Using Python shared library: C:\Users\isard\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python312.dll
|
||||
3016 INFO: Running Analysis Analysis-00.toc
|
||||
3016 INFO: Target bytecode optimization level: 1
|
||||
3016 INFO: Initializing module dependency graph...
|
||||
3018 INFO: Initializing module graph hook caches...
|
||||
3041 INFO: Analyzing modules for base_library.zip ...
|
||||
5117 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
5753 INFO: Processing standard module hook 'hook-math.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
7416 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
8682 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
9222 INFO: Caching module dependency graph...
|
||||
9283 INFO: Analyzing C:\wechat_rpa\app_main.py
|
||||
9446 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
9666 INFO: Processing standard module hook 'hook-xml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10027 INFO: Processing standard module hook 'hook-_ctypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10136 INFO: Processing standard module hook 'hook-sqlite3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10635 INFO: Processing standard module hook 'hook-Crypto.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
11714 INFO: Processing standard module hook 'hook-pycparser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
11938 INFO: Processing standard module hook 'hook-setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
11940 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
12888 INFO: Processing standard module hook 'hook-platform.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
12892 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
12964 INFO: Processing standard module hook 'hook-sysconfig.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
12977 INFO: Processing pre-safe-import-module hook 'hook-jaraco.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
12978 INFO: Setuptools: 'jaraco' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.jaraco'!
|
||||
12994 INFO: Processing pre-safe-import-module hook 'hook-more_itertools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
12995 INFO: Setuptools: 'more_itertools' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.more_itertools'!
|
||||
13194 INFO: Processing standard module hook 'hook-_osx_support.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13200 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
13987 INFO: Processing pre-safe-import-module hook 'hook-packaging.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14337 INFO: Processing standard module hook 'hook-setuptools._vendor.jaraco.text.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
14340 INFO: Processing pre-safe-import-module hook 'hook-importlib_resources.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14615 INFO: Processing pre-safe-import-module hook 'hook-backports.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14616 INFO: Setuptools: 'backports' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.backports'!
|
||||
15485 INFO: Processing pre-safe-import-module hook 'hook-tomli.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
15486 INFO: Setuptools: 'tomli' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.tomli'!
|
||||
16293 INFO: Processing pre-safe-import-module hook 'hook-wheel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
16294 INFO: Setuptools: 'wheel' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.wheel'!
|
||||
17009 INFO: Processing standard module hook 'hook-webbrowser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
17749 INFO: Processing standard module hook 'hook-urllib3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18473 INFO: Processing standard module hook 'hook-certifi.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18526 INFO: Processing standard module hook 'hook-charset_normalizer.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18714 INFO: Processing standard module hook 'hook-cryptography.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
20516 INFO: hook-cryptography: cryptography does not seem to be using dynamically linked OpenSSL.
|
||||
22222 INFO: Processing standard module hook 'hook-PySide6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
22532 INFO: Processing standard module hook 'hook-shiboken6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
22739 INFO: Processing standard module hook 'hook-PySide6.QtNetwork.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
30492 INFO: Processing standard module hook 'hook-PySide6.QtCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
36997 INFO: Processing standard module hook 'hook-PySide6.QtGui.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
68009 INFO: Processing standard module hook 'hook-PySide6.QtWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
73721 INFO: Processing standard module hook 'hook-PySide6.QtWebChannel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
76028 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
81952 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
84092 INFO: Processing standard module hook 'hook-PySide6.QtPrintSupport.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
87531 INFO: Processing pre-find-module-path hook 'hook-tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
87534 INFO: TclTkInfo: initializing cached Tcl/Tk info...
|
||||
88975 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
89016 INFO: Processing standard module hook 'hook-PIL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
89168 INFO: Processing standard module hook 'hook-PIL.Image.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
89733 INFO: Processing standard module hook 'hook-numpy.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
91902 INFO: Processing standard module hook 'hook-difflib.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
93452 INFO: Processing standard module hook 'hook-xml.etree.cElementTree.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
94134 INFO: Processing standard module hook 'hook-PIL.ImageFilter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
94760 INFO: Processing standard module hook 'hook-cv2.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
95810 INFO: Processing standard module hook 'hook-onnxruntime.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
95923 INFO: Processing pre-safe-import-module hook 'hook-tensorflow.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\pre_safe_import_module'
|
||||
95991 INFO: Processing standard module hook 'hook-shapely.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
96443 INFO: Processing standard module hook 'hook-pydantic.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
97446 INFO: Processing standard module hook 'hook-rich.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
98674 INFO: Processing standard module hook 'hook-pygments.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
102039 INFO: Processing standard module hook 'hook-zoneinfo.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
103781 INFO: Processing standard module hook 'hook-anyio.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
105339 INFO: Processing standard module hook 'hook-opentelemetry.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
105948 INFO: Processing standard module hook 'hook-uvicorn.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
108299 INFO: Processing standard module hook 'hook-websockets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
111139 INFO: Processing standard module hook 'hook-pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
111458 INFO: Processing standard module hook 'hook-jsonschema.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
111697 INFO: Processing standard module hook 'hook-jsonschema_specifications.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
112917 INFO: Analyzing hidden import 'mcp.cli'
|
||||
113508 INFO: Analyzing hidden import 'mcp.client.__main__'
|
||||
113512 INFO: Analyzing hidden import 'mcp.client.auth'
|
||||
113570 INFO: Analyzing hidden import 'mcp.client.auth.extensions'
|
||||
113571 INFO: Analyzing hidden import 'mcp.client.auth.extensions.client_credentials'
|
||||
113690 INFO: Analyzing hidden import 'mcp.client.auth.extensions.identity_assertion'
|
||||
113700 INFO: Analyzing hidden import 'mcp.server.__main__'
|
||||
113703 INFO: Analyzing hidden import 'mcp.server.apps'
|
||||
113712 INFO: Analyzing hidden import 'mcp.server.fastmcp'
|
||||
113713 INFO: Analyzing hidden import 'mcp.shared.metadata_utils'
|
||||
113715 INFO: Processing module hooks (post-graph stage)...
|
||||
113984 WARNING: Hidden import "pycparser.lextab" not found!
|
||||
113985 WARNING: Hidden import "pycparser.yacctab" not found!
|
||||
114683 WARNING: Hidden import "tzdata" not found!
|
||||
115134 INFO: Processing standard module hook 'hook-PIL.SpiderImagePlugin.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
118530 INFO: Processing standard module hook 'hook-PySide6.QtQuick.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
122620 INFO: Processing standard module hook 'hook-PySide6.QtOpenGL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
127881 INFO: Processing standard module hook 'hook-PySide6.QtQml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
170157 INFO: Processing standard module hook 'hook-PySide6.QtPositioning.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
172551 INFO: Processing standard module hook 'hook-PySide6.QtQuickWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
173961 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
174034 INFO: Performing binary vs. data reclassification (3714 entries)
|
||||
174777 INFO: Looking for ctypes DLLs
|
||||
175387 INFO: Analyzing run-time hooks ...
|
||||
175400 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175403 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175406 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175409 INFO: Including run-time hook 'pyi_rth_setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175478 INFO: Including run-time hook 'pyi_rth_cryptography_openssl.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
175480 INFO: Including run-time hook 'pyi_rth_pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
175484 INFO: Including run-time hook 'pyi_rth_pyside6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175491 INFO: Processing pre-find-module-path hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
175498 INFO: Processing standard module hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
175507 INFO: Including run-time hook 'pyi_rth__tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
175720 INFO: Creating base_library.zip...
|
||||
176052 INFO: Looking for dynamic libraries
|
||||
179758 INFO: Extra DLL search directories (AddDllDirectory): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shiboken6', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\numpy.libs', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shapely.libs']
|
||||
179759 INFO: Extra DLL search directories (PATH): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PySide6']
|
||||
186455 INFO: Warnings written to C:\wechat_rpa\build\wechat_rpa\warn-wechat_rpa.txt
|
||||
186703 INFO: Graph cross-reference written to C:\wechat_rpa\build\wechat_rpa\xref-wechat_rpa.html
|
||||
186945 INFO: checking PYZ
|
||||
186945 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
186945 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
197881 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz completed successfully.
|
||||
197936 INFO: checking PKG
|
||||
197936 INFO: Building PKG because PKG-00.toc is non existent
|
||||
197937 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.18.pkg
|
||||
197998 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.18.pkg completed successfully.
|
||||
198000 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\runw.exe
|
||||
198000 INFO: checking EXE
|
||||
198000 INFO: Building EXE because EXE-00.toc is non existent
|
||||
198000 INFO: Building EXE from EXE-00.toc
|
||||
198000 INFO: Copying bootloader EXE to C:\wechat_rpa\build\wechat_rpa\ZhenAI-WeCom-Assistant-v1.4.18.exe
|
||||
198062 INFO: Copying icon to EXE
|
||||
198110 INFO: Copying version information to EXE
|
||||
198156 INFO: Copying 0 resources to EXE
|
||||
198157 INFO: Embedding manifest in EXE
|
||||
198203 INFO: Appending PKG archive to EXE
|
||||
198323 INFO: Fixing EXE headers
|
||||
198729 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
198785 INFO: checking COLLECT
|
||||
198785 INFO: Building COLLECT because COLLECT-00.toc is non existent
|
||||
198786 INFO: Building COLLECT COLLECT-00.toc
|
||||
204253 INFO: Building COLLECT COLLECT-00.toc completed successfully.
|
||||
204372 INFO: Build complete! The results are available in: C:\wechat_rpa\dist
|
||||
Embedded browser and VC runtime files verified
|
||||
197 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
198 INFO: Python: 3.12.14
|
||||
285 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
285 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
287 INFO: wrote C:\wechat_rpa\build\updater-helper\ZhenAIUpdater.spec
|
||||
291 INFO: Removing temporary files and cleaning cache in C:\kefu\deploy\listener-continuity-20260917\build-self-check-profile\Local\pyinstaller
|
||||
309 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
898 INFO: checking Analysis
|
||||
898 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
898 INFO: Looking for Python shared library...
|
||||
898 INFO: Using Python shared library: C:\Users\isard\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python312.dll
|
||||
899 INFO: Running Analysis Analysis-00.toc
|
||||
899 INFO: Target bytecode optimization level: 0
|
||||
899 INFO: Initializing module dependency graph...
|
||||
900 INFO: Initializing module graph hook caches...
|
||||
924 INFO: Analyzing modules for base_library.zip ...
|
||||
2893 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
3494 INFO: Processing standard module hook 'hook-math.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
4856 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
6165 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
6670 INFO: Caching module dependency graph...
|
||||
6726 INFO: Analyzing C:\wechat_rpa\updater_main.py
|
||||
6761 INFO: Processing standard module hook 'hook-_ctypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
6805 INFO: Processing module hooks (post-graph stage)...
|
||||
6813 INFO: Performing binary vs. data reclassification (1 entries)
|
||||
6815 INFO: Looking for ctypes DLLs
|
||||
6823 INFO: Analyzing run-time hooks ...
|
||||
6824 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
6830 INFO: Creating base_library.zip...
|
||||
6860 INFO: Looking for dynamic libraries
|
||||
7124 INFO: Extra DLL search directories (AddDllDirectory): []
|
||||
7124 INFO: Extra DLL search directories (PATH): []
|
||||
7482 INFO: Warnings written to C:\wechat_rpa\build\updater-helper\ZhenAIUpdater\warn-ZhenAIUpdater.txt
|
||||
7504 INFO: Graph cross-reference written to C:\wechat_rpa\build\updater-helper\ZhenAIUpdater\xref-ZhenAIUpdater.html
|
||||
7531 INFO: checking PYZ
|
||||
7531 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
7531 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\updater-helper\ZhenAIUpdater\PYZ-00.pyz
|
||||
7772 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\updater-helper\ZhenAIUpdater\PYZ-00.pyz completed successfully.
|
||||
7779 INFO: checking PKG
|
||||
7780 INFO: Building PKG because PKG-00.toc is non existent
|
||||
7780 INFO: Building PKG (CArchive) ZhenAIUpdater.pkg
|
||||
12614 INFO: Building PKG (CArchive) ZhenAIUpdater.pkg completed successfully.
|
||||
12617 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\run.exe
|
||||
12617 INFO: checking EXE
|
||||
12618 INFO: Building EXE because EXE-00.toc is non existent
|
||||
12618 INFO: Building EXE from EXE-00.toc
|
||||
12619 INFO: Copying bootloader EXE to C:\wechat_rpa\dist\updater-helper\ZhenAIUpdater.exe
|
||||
12676 INFO: Copying icon to EXE
|
||||
12728 INFO: Copying 0 resources to EXE
|
||||
12728 INFO: Embedding manifest in EXE
|
||||
12774 INFO: Appending PKG archive to EXE
|
||||
12856 INFO: Fixing EXE headers
|
||||
13168 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
13172 INFO: Build complete! The results are available in: C:\wechat_rpa\dist\updater-helper
|
||||
Code signing skipped (no certificate configured): ZhenAIUpdater.exe
|
||||
Independent updater built and bundled
|
||||
Code signing skipped (no certificate configured): ZhenAI-WeCom-Assistant-v1.4.18.exe
|
||||
Packaged Qt WebEngine self-check passed
|
||||
Packaged real HTTPS and certificate verification checks passed (clean PATH)
|
||||
Packaged automatic decryption and incremental cloud upload checks passed (synthetic data, mocked transport)
|
||||
Packaged Messages navigation and OCR checks passed (synthetic UI, mocked input)
|
||||
Packaged cross-machine capture, DPI and unread click checks passed (synthetic pixels, mocked input)
|
||||
Packaged self-reply feedback and send guards passed (synthetic archive, mocked input)
|
||||
Packaged background database detection and database-first reply checks passed (synthetic data, mocked input)
|
||||
App folder: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.18
|
||||
EXE: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.18\ZhenAI-WeCom-Assistant-v1.4.18.exe
|
||||
SHA256: 1265EF124E5F14201D2B9FA03C518824954422AF3A57D1F04DE4E1F178E6E7FA
|
||||
@@ -1,42 +0,0 @@
|
||||
test_programming_error_is_visible_and_does_not_terminate_visual_listener (test_listener_continuity.ListenerContinuityTests.test_programming_error_is_visible_and_does_not_terminate_visual_listener) ... ok
|
||||
test_recovery_backoff_is_bounded_and_repeated_errors_do_not_flood_logs (test_listener_continuity.ListenerContinuityTests.test_recovery_backoff_is_bounded_and_repeated_errors_do_not_flood_logs) ... ok
|
||||
test_user_stop_interrupts_connection_backoff_without_polling (test_listener_continuity.ListenerContinuityTests.test_user_stop_interrupts_connection_backoff_without_polling) ... ok
|
||||
test_verification_capture_failure_keeps_guard_and_no_further_polls (test_listener_continuity.ListenerContinuityTests.test_verification_capture_failure_keeps_guard_and_no_further_polls) ... ok
|
||||
test_verification_requires_consecutive_clean_captures (test_listener_continuity.ListenerContinuityTests.test_verification_requires_consecutive_clean_captures) ... ok
|
||||
test_verification_resumes_only_after_two_clean_workspace_captures (test_listener_continuity.ListenerContinuityTests.test_verification_resumes_only_after_two_clean_workspace_captures) ... ok
|
||||
test_visual_initial_connection_waits_then_recovers (test_listener_continuity.ListenerContinuityTests.test_visual_initial_connection_waits_then_recovers) ... ok
|
||||
test_visual_temporary_poll_failure_recovers_same_bot_and_preserves_protected_state (test_listener_continuity.ListenerContinuityTests.test_visual_temporary_poll_failure_recovers_same_bot_and_preserves_protected_state) ... ok
|
||||
test_attention_does_not_stop_listener_or_clear_review_and_delivery_protection (test_listener_continuity.ProtocolListenerContinuityTests.test_attention_does_not_stop_listener_or_clear_review_and_delivery_protection) ... ok
|
||||
test_protocol_database_errors_retry_same_account_bot_without_reconstruction (test_listener_continuity.ProtocolListenerContinuityTests.test_protocol_database_errors_retry_same_account_bot_without_reconstruction) ... ok
|
||||
test_protocol_startup_unavailable_waits_without_polling_then_recovers (test_listener_continuity.ProtocolListenerContinuityTests.test_protocol_startup_unavailable_waits_without_polling_then_recovers) ... ok
|
||||
test_stop_during_protocol_backoff_closes_resources_and_never_repolls (test_listener_continuity.ProtocolListenerContinuityTests.test_stop_during_protocol_backoff_closes_resources_and_never_repolls) ... ok
|
||||
test_stop_during_unsupported_build_wait_never_constructs_bot (test_listener_continuity.ProtocolListenerContinuityTests.test_stop_during_unsupported_build_wait_never_constructs_bot) ... ok
|
||||
test_unsupported_build_waits_and_never_constructs_sender_until_preflight_passes (test_listener_continuity.ProtocolListenerContinuityTests.test_unsupported_build_waits_and_never_constructs_sender_until_preflight_passes) ... ok
|
||||
test_capsule_preserves_verification_progress (test_listener_ui_continuity.ListenerUIContinuityTests.test_capsule_preserves_verification_progress) ... ok
|
||||
test_explicit_stop_still_finishes_worker (test_listener_ui_continuity.ListenerUIContinuityTests.test_explicit_stop_still_finishes_worker) ... ok
|
||||
test_protocol_task_attention_does_not_disconnect_healthy_listener (test_listener_ui_continuity.ListenerUIContinuityTests.test_protocol_task_attention_does_not_disconnect_healthy_listener) ... ok
|
||||
test_recoverable_wait_does_not_mark_queue_as_stopped (test_listener_ui_continuity.ListenerUIContinuityTests.test_recoverable_wait_does_not_mark_queue_as_stopped) ... ok
|
||||
test_sidebar_waiting_keeps_stop_button_active (test_listener_ui_continuity.ListenerUIContinuityTests.test_sidebar_waiting_keeps_stop_button_active) ... ok
|
||||
test_waiting_states_keep_running_and_stop_control_available (test_listener_ui_continuity.ListenerUIContinuityTests.test_waiting_states_keep_running_and_stop_control_available) ... ok
|
||||
test_web_labels_distinguish_waiting_from_stopped (test_listener_ui_continuity.ListenerUIContinuityTests.test_web_labels_distinguish_waiting_from_stopped) ... ok
|
||||
test_database_poll_failure_recovers_without_recreating_pending_tasks (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_database_poll_failure_recovers_without_recreating_pending_tasks) ... ok
|
||||
test_receipt_unknown_and_review_do_not_stop_other_conversations (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_receipt_unknown_and_review_do_not_stop_other_conversations) ... ok
|
||||
test_database_wide_failure_propagates_without_healthy_claim_or_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_database_wide_failure_propagates_without_healthy_claim_or_send) ... ok
|
||||
test_explicit_pre_send_unavailable_stays_error_and_peers_continue (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_explicit_pre_send_unavailable_stays_error_and_peers_continue) ... ok
|
||||
test_foreign_account_task_cannot_send_while_current_account_continues (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_foreign_account_task_cannot_send_while_current_account_continues) ... ok
|
||||
test_generation_error_does_not_stop_another_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_generation_error_does_not_stop_another_conversation) ... ok
|
||||
test_malformed_message_row_does_not_drop_valid_rows (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_message_row_does_not_drop_valid_rows) ... ok
|
||||
test_malformed_task_timing_does_not_block_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_task_timing_does_not_block_peers) ... ok
|
||||
test_media_manual_handling_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_media_manual_handling_only_blocks_its_own_conversation) ... ok
|
||||
test_new_messages_and_contact_notices_cannot_replace_unknown_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_new_messages_and_contact_notices_cannot_replace_unknown_send) ... ok
|
||||
test_pending_review_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_pending_review_only_blocks_its_own_conversation) ... ok
|
||||
test_restart_keeps_unknown_and_failed_tasks_isolated (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_restart_keeps_unknown_and_failed_tasks_isolated) ... ok
|
||||
test_sending_persistence_error_preserves_no_replay_and_peer_processing (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_sending_persistence_error_preserves_no_replay_and_peer_processing) ... ok
|
||||
test_task_context_read_error_is_recorded_without_stopping_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_task_context_read_error_is_recorded_without_stopping_peers) ... ok
|
||||
test_unexpected_sender_exception_is_unknown_not_automatic_retry (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unexpected_sender_exception_is_unknown_not_automatic_retry) ... ok
|
||||
test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 37 tests in 2.360s
|
||||
|
||||
OK
|
||||
@@ -1,30 +0,0 @@
|
||||
MakeNSIS v3.12 - Copyright 1999-2026 Contributors
|
||||
See the file COPYING for license details.
|
||||
Credits can be found in the Users Manual.
|
||||
|
||||
Command line defined: "APP_VERSION=1.4.18"
|
||||
Command line defined: "APP_FILE_VERSION=1.4.18.0"
|
||||
Command line defined: "SOURCE_DIR=C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.18"
|
||||
Processing config: C:\wechat_rpa\.installer-tools\NSIS\nsisconf.nsh
|
||||
Processing script file: "C:\wechat_rpa\installer.nsi" (UTF8)
|
||||
|
||||
Processed 1 file, writing output (x86-unicode):
|
||||
|
||||
Output: "C:\wechat_rpa\dist\installer\��AI�ͷ�-��װ��-v1.4.18.exe"
|
||||
Install: 4 pages (256 bytes), 1 section (2072 bytes), 4725 instructions (132300 bytes), 3342 strings (141484 bytes), 1 language table (302 bytes).
|
||||
Uninstall: 3 pages (256 bytes), 1 section (2072 bytes), 285 instructions (7980 bytes), 167 strings (3562 bytes), 1 language table (282 bytes).
|
||||
Datablock optimizer saved 1775 KiB (~0.2%).
|
||||
|
||||
Using zlib (compress whole) compression.
|
||||
|
||||
EXE header size: 118784 / 40960 bytes
|
||||
Install code: (276878 bytes)
|
||||
Install data: (868673960 bytes)
|
||||
Uninstall code+data: (141472 bytes)
|
||||
Compressed data: 352033569 / 869092310 bytes
|
||||
CRC (0x17774187): 4 / 4 bytes
|
||||
|
||||
Total size: 352152357 / 869133274 bytes (40.5%)
|
||||
Code signing skipped (no certificate configured): 甄AI客服-安装包-v1.4.18.exe
|
||||
Installer: C:\wechat_rpa\dist\installer\甄AI客服-安装包-v1.4.18.exe
|
||||
SHA256: BA0C5847A2C8AEDC2D3FF9A0FC06EE35DE1E3B6704D52B8BB3EF0F64D4DC2F48
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
7-Zip 26.03 (x64) : Copyright (c) 1999-2026 Igor Pavlov : 2026-09-03
|
||||
|
||||
Scanning the drive for archives:
|
||||
1 file, 352152357 bytes (336 MiB)
|
||||
|
||||
Testing archive: C:\wechat_rpa\dist\installer\��AI�ͷ�-��װ��-v1.4.18.exe
|
||||
--
|
||||
Path = C:\wechat_rpa\dist\installer\��AI�ͷ�-��װ��-v1.4.18.exe
|
||||
Type = Nsis
|
||||
Physical Size = 352152357
|
||||
Method = Deflate
|
||||
Solid = +
|
||||
Headers Size = 276850
|
||||
Embedded Stub Size = 118784
|
||||
SubType = NSIS-3 Unicode
|
||||
|
||||
Everything is Ok
|
||||
|
||||
Files: 4013
|
||||
Size: 870449651
|
||||
Compressed: 352152357
|
||||
@@ -1,7 +0,0 @@
|
||||
test_database_poll_failure_recovers_without_recreating_pending_tasks (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_database_poll_failure_recovers_without_recreating_pending_tasks) ... ok
|
||||
test_receipt_unknown_and_review_do_not_stop_other_conversations (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_receipt_unknown_and_review_do_not_stop_other_conversations) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 2 tests in 1.232s
|
||||
|
||||
OK
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,315 +0,0 @@
|
||||
test_programming_error_is_visible_and_does_not_terminate_visual_listener (test_listener_continuity.ListenerContinuityTests.test_programming_error_is_visible_and_does_not_terminate_visual_listener) ... ok
|
||||
test_recovery_backoff_is_bounded_and_repeated_errors_do_not_flood_logs (test_listener_continuity.ListenerContinuityTests.test_recovery_backoff_is_bounded_and_repeated_errors_do_not_flood_logs) ... ok
|
||||
test_user_stop_interrupts_connection_backoff_without_polling (test_listener_continuity.ListenerContinuityTests.test_user_stop_interrupts_connection_backoff_without_polling) ... ok
|
||||
test_verification_capture_failure_keeps_guard_and_no_further_polls (test_listener_continuity.ListenerContinuityTests.test_verification_capture_failure_keeps_guard_and_no_further_polls) ... ok
|
||||
test_verification_requires_consecutive_clean_captures (test_listener_continuity.ListenerContinuityTests.test_verification_requires_consecutive_clean_captures) ... ok
|
||||
test_verification_resumes_only_after_two_clean_workspace_captures (test_listener_continuity.ListenerContinuityTests.test_verification_resumes_only_after_two_clean_workspace_captures) ... ok
|
||||
test_visual_initial_connection_waits_then_recovers (test_listener_continuity.ListenerContinuityTests.test_visual_initial_connection_waits_then_recovers) ... ok
|
||||
test_visual_temporary_poll_failure_recovers_same_bot_and_preserves_protected_state (test_listener_continuity.ListenerContinuityTests.test_visual_temporary_poll_failure_recovers_same_bot_and_preserves_protected_state) ... ok
|
||||
test_attention_does_not_stop_listener_or_clear_review_and_delivery_protection (test_listener_continuity.ProtocolListenerContinuityTests.test_attention_does_not_stop_listener_or_clear_review_and_delivery_protection) ... ok
|
||||
test_protocol_database_errors_retry_same_account_bot_without_reconstruction (test_listener_continuity.ProtocolListenerContinuityTests.test_protocol_database_errors_retry_same_account_bot_without_reconstruction) ... ok
|
||||
test_protocol_startup_unavailable_waits_without_polling_then_recovers (test_listener_continuity.ProtocolListenerContinuityTests.test_protocol_startup_unavailable_waits_without_polling_then_recovers) ... ok
|
||||
test_stop_during_protocol_backoff_closes_resources_and_never_repolls (test_listener_continuity.ProtocolListenerContinuityTests.test_stop_during_protocol_backoff_closes_resources_and_never_repolls) ... ok
|
||||
test_stop_during_unsupported_build_wait_never_constructs_bot (test_listener_continuity.ProtocolListenerContinuityTests.test_stop_during_unsupported_build_wait_never_constructs_bot) ... ok
|
||||
test_unsupported_build_waits_and_never_constructs_sender_until_preflight_passes (test_listener_continuity.ProtocolListenerContinuityTests.test_unsupported_build_waits_and_never_constructs_sender_until_preflight_passes) ... ok
|
||||
test_capsule_preserves_verification_progress (test_listener_ui_continuity.ListenerUIContinuityTests.test_capsule_preserves_verification_progress) ... ok
|
||||
test_explicit_stop_still_finishes_worker (test_listener_ui_continuity.ListenerUIContinuityTests.test_explicit_stop_still_finishes_worker) ... ok
|
||||
test_protocol_task_attention_does_not_disconnect_healthy_listener (test_listener_ui_continuity.ListenerUIContinuityTests.test_protocol_task_attention_does_not_disconnect_healthy_listener) ... ok
|
||||
test_recoverable_wait_does_not_mark_queue_as_stopped (test_listener_ui_continuity.ListenerUIContinuityTests.test_recoverable_wait_does_not_mark_queue_as_stopped) ... ok
|
||||
test_sidebar_waiting_keeps_stop_button_active (test_listener_ui_continuity.ListenerUIContinuityTests.test_sidebar_waiting_keeps_stop_button_active) ... ok
|
||||
test_waiting_states_keep_running_and_stop_control_available (test_listener_ui_continuity.ListenerUIContinuityTests.test_waiting_states_keep_running_and_stop_control_available) ... ok
|
||||
test_web_labels_distinguish_waiting_from_stopped (test_listener_ui_continuity.ListenerUIContinuityTests.test_web_labels_distinguish_waiting_from_stopped) ... ok
|
||||
test_database_poll_failure_recovers_without_recreating_pending_tasks (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_database_poll_failure_recovers_without_recreating_pending_tasks) ... ok
|
||||
test_receipt_unknown_and_review_do_not_stop_other_conversations (test_listener_continuity_integration.ListenerContinuityIntegrationTests.test_receipt_unknown_and_review_do_not_stop_other_conversations) ... ok
|
||||
test_database_wide_failure_propagates_without_healthy_claim_or_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_database_wide_failure_propagates_without_healthy_claim_or_send) ... ok
|
||||
test_explicit_pre_send_unavailable_stays_error_and_peers_continue (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_explicit_pre_send_unavailable_stays_error_and_peers_continue) ... ok
|
||||
test_foreign_account_task_cannot_send_while_current_account_continues (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_foreign_account_task_cannot_send_while_current_account_continues) ... ok
|
||||
test_generation_error_does_not_stop_another_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_generation_error_does_not_stop_another_conversation) ... ok
|
||||
test_malformed_message_row_does_not_drop_valid_rows (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_message_row_does_not_drop_valid_rows) ... ok
|
||||
test_malformed_task_timing_does_not_block_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_malformed_task_timing_does_not_block_peers) ... ok
|
||||
test_media_manual_handling_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_media_manual_handling_only_blocks_its_own_conversation) ... ok
|
||||
test_new_messages_and_contact_notices_cannot_replace_unknown_send (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_new_messages_and_contact_notices_cannot_replace_unknown_send) ... ok
|
||||
test_pending_review_only_blocks_its_own_conversation (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_pending_review_only_blocks_its_own_conversation) ... ok
|
||||
test_restart_keeps_unknown_and_failed_tasks_isolated (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_restart_keeps_unknown_and_failed_tasks_isolated) ... ok
|
||||
test_sending_persistence_error_preserves_no_replay_and_peer_processing (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_sending_persistence_error_preserves_no_replay_and_peer_processing) ... ok
|
||||
test_task_context_read_error_is_recorded_without_stopping_peers (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_task_context_read_error_is_recorded_without_stopping_peers) ... ok
|
||||
test_unexpected_sender_exception_is_unknown_not_automatic_retry (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unexpected_sender_exception_is_unknown_not_automatic_retry) ... ok
|
||||
test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks (test_protocol_listener_continuity.ProtocolListenerContinuityTests.test_unknown_receipt_does_not_stop_same_poll_or_future_peer_tasks) ... ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_isolated_with_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_isolated_with_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_cancelled_context_history_only_keeps_unanswered (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_cancelled_context_history_only_keeps_unanswered) ... ok
|
||||
test_context_enabled_retains_both_roles_and_unanswered_batch (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_context_enabled_retains_both_roles_and_unanswered_batch) ... ok
|
||||
test_exactly_100_unanswered_messages_preserve_every_part (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_exactly_100_unanswered_messages_preserve_every_part) ... ok
|
||||
test_existing_approved_draft_with_media_is_not_sent (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_existing_approved_draft_with_media_is_not_sent) ... ok
|
||||
test_image_then_related_text_stays_manual (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_image_then_related_text_stays_manual) ... ok
|
||||
test_old_media_before_own_reply_does_not_block_new_text (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_old_media_before_own_reply_does_not_block_new_text) ... ok
|
||||
test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_overflowing_unanswered_batch_cannot_answer_from_truncated_tail) ... ok
|
||||
test_own_reply_within_long_history_makes_current_batch_complete (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_own_reply_within_long_history_makes_current_batch_complete) ... ok
|
||||
test_restart_preserves_uncertain_conversation_and_processes_others (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_restart_preserves_uncertain_conversation_and_processes_others) ... ok
|
||||
test_unanswered_batch_not_lost_with_short_context_limit (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_unanswered_batch_not_lost_with_short_context_limit) ... ok
|
||||
test_uncertain_receipt_for_other_account_does_not_pause_current (test_protocol_audit_boundaries.ProtocolAuditBoundaries.test_uncertain_receipt_for_other_account_does_not_pause_current) ... ok
|
||||
test_foreign_account_task_cannot_be_approved_deleted_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_foreign_account_task_cannot_be_approved_deleted_or_retried) ... ok
|
||||
test_high_risk_reason_available_in_automatic_mode (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_high_risk_reason_available_in_automatic_mode) ... ok
|
||||
test_media_batch_is_visible_manual_work_without_approvable_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_media_batch_is_visible_manual_work_without_approvable_draft) ... ok
|
||||
test_next_valid_batch_discards_old_manual_requirement (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_next_valid_batch_discards_old_manual_requirement) ... ok
|
||||
test_old_saved_review_and_manual_tasks_restore_metadata_only (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_old_saved_review_and_manual_tasks_restore_metadata_only) ... ok
|
||||
test_overlong_batch_cannot_be_approved_as_a_draft (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_overlong_batch_cannot_be_approved_as_a_draft) ... ok
|
||||
test_retry_clears_old_metadata_then_rechecks_media_without_sending (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_retry_clears_old_metadata_then_rechecks_media_without_sending) ... ok
|
||||
test_review_draft_reason_persists_then_explicit_approval_sends_once (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_review_draft_reason_persists_then_explicit_approval_sends_once) ... ok
|
||||
test_unknown_receipt_cannot_be_approved_or_retried (test_protocol_review_visibility.ProtocolReviewVisibilityTests.test_unknown_receipt_cannot_be_approved_or_retried) ... ok
|
||||
test_a_clock_rollback_never_deletes_a_fresh_log (test_runtime_settings.LogRetentionTest.test_a_clock_rollback_never_deletes_a_fresh_log) ... ok
|
||||
test_a_shorter_window_deletes_more (test_runtime_settings.LogRetentionTest.test_a_shorter_window_deletes_more) ... ok
|
||||
test_logs_older_than_the_retention_window_are_deleted (test_runtime_settings.LogRetentionTest.test_logs_older_than_the_retention_window_are_deleted) ... ok
|
||||
test_out_of_range_values_fall_back_to_the_documented_defaults (test_runtime_settings.LogRetentionTest.test_out_of_range_values_fall_back_to_the_documented_defaults) ... ok
|
||||
test_the_file_count_cap_still_applies (test_runtime_settings.LogRetentionTest.test_the_file_count_cap_still_applies) ... ok
|
||||
test_unreadable_directory_never_breaks_startup (test_runtime_settings.LogRetentionTest.test_unreadable_directory_never_breaks_startup) ... ok
|
||||
test_atomic_operation_progress_includes_phase_step_detail_and_customer (test_runtime_settings.RuntimeSettingsTest.test_atomic_operation_progress_includes_phase_step_detail_and_customer) ... ok
|
||||
test_bot_uses_instance_batch_window_when_call_has_no_override (test_runtime_settings.RuntimeSettingsTest.test_bot_uses_instance_batch_window_when_call_has_no_override) ... ok
|
||||
test_classic_capsule_renders_each_progress_message_as_a_numbered_step (test_runtime_settings.RuntimeSettingsTest.test_classic_capsule_renders_each_progress_message_as_a_numbered_step) ... ok
|
||||
test_classic_queue_consumes_the_runtime_progress_channel (test_runtime_settings.RuntimeSettingsTest.test_classic_queue_consumes_the_runtime_progress_channel) ... ok
|
||||
test_classic_settings_save_persists_and_updates_live_thread (test_runtime_settings.RuntimeSettingsTest.test_classic_settings_save_persists_and_updates_live_thread) ... ok
|
||||
test_customer_chat_body_is_not_mirrored_into_floating_capsule (test_runtime_settings.RuntimeSettingsTest.test_customer_chat_body_is_not_mirrored_into_floating_capsule) ... ok
|
||||
test_invalid_saved_batch_window_falls_back_to_twenty_seconds (test_runtime_settings.RuntimeSettingsTest.test_invalid_saved_batch_window_falls_back_to_twenty_seconds) ... ok
|
||||
test_invalid_saved_send_delay_falls_back_to_one_second (test_runtime_settings.RuntimeSettingsTest.test_invalid_saved_send_delay_falls_back_to_one_second) ... ok
|
||||
test_invalid_send_mode_falls_back_to_automatic (test_runtime_settings.RuntimeSettingsTest.test_invalid_send_mode_falls_back_to_automatic) ... ok
|
||||
test_legacy_settings_without_batch_window_keep_twenty_second_default (test_runtime_settings.RuntimeSettingsTest.test_legacy_settings_without_batch_window_keep_twenty_second_default) ... ok
|
||||
test_manual_queue_delete_removes_only_selected_full_key_atomically (test_runtime_settings.RuntimeSettingsTest.test_manual_queue_delete_removes_only_selected_full_key_atomically) ... ok
|
||||
test_manual_retry_only_requeues_retry_wait_tasks (test_runtime_settings.RuntimeSettingsTest.test_manual_retry_only_requeues_retry_wait_tasks) ... ok
|
||||
test_message_copy_retries_when_wecom_writes_clipboard_late (test_runtime_settings.RuntimeSettingsTest.test_message_copy_retries_when_wecom_writes_clipboard_late) ... ok
|
||||
test_retry_request_queues_until_bot_startup_finishes (test_runtime_settings.RuntimeSettingsTest.test_retry_request_queues_until_bot_startup_finishes) ... ok
|
||||
test_review_pending_state_survives_restart (test_runtime_settings.RuntimeSettingsTest.test_review_pending_state_survives_restart) ... [待回复恢复] 已从磁盘恢复 1 个未完成任务。
|
||||
ok
|
||||
test_runtime_thread_syncs_updated_batch_window_before_next_poll (test_runtime_settings.RuntimeSettingsTest.test_runtime_thread_syncs_updated_batch_window_before_next_poll) ... [引擎B] 数据直读检测已启动
|
||||
[+] 窗口激活模式已开启:企业微信未显示时会自动还原到前台
|
||||
[i] 数据库新消息与未读标记共同触发回复任务,窗口异常时保留任务并重试
|
||||
[+] 人机共存已开启:鼠标静止 5 秒后才自动操作
|
||||
[+] 连续消息合并等待:7 秒
|
||||
[+] 发送前等待:1.5 秒
|
||||
[+] 发送模式:人工审核草稿(AI 只把回复填进输入框,不会自动按回车;需要自动发送请在设置里切到“自动发送”)
|
||||
[引擎B] DB 直读失败: 数据库正在初始化或刷新,暂用备用读取,备用检测继续运行
|
||||
ok
|
||||
test_send_delay_wait_is_independent_and_interruptible (test_runtime_settings.RuntimeSettingsTest.test_send_delay_wait_is_independent_and_interruptible) ... ok
|
||||
test_tagged_low_level_logs_are_mirrored_to_capsule_progress (test_runtime_settings.RuntimeSettingsTest.test_tagged_low_level_logs_are_mirrored_to_capsule_progress) ... ok
|
||||
test_async_protocol_check_retains_explicit_approval_request (test_desktop_review_visibility.DesktopReviewTest.test_async_protocol_check_retains_explicit_approval_request) ... ok
|
||||
test_explicit_approval_reaches_thread_with_exact_key_and_refreshes (test_desktop_review_visibility.DesktopReviewTest.test_explicit_approval_reaches_thread_with_exact_key_and_refreshes) ... ok
|
||||
test_human_filter_includes_unknown_receipt_and_no_empty_send (test_desktop_review_visibility.DesktopReviewTest.test_human_filter_includes_unknown_receipt_and_no_empty_send) ... ok
|
||||
test_legacy_receipt_states_are_visible_but_not_sendable (test_desktop_review_visibility.DesktopReviewTest.test_legacy_receipt_states_are_visible_but_not_sendable) ... ok
|
||||
test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser (test_desktop_review_visibility.DesktopReviewTest.test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser) ... ok
|
||||
test_review_counts_remain_visible_under_an_unrelated_filter (test_desktop_review_visibility.DesktopReviewTest.test_review_counts_remain_visible_under_an_unrelated_filter) ... ok
|
||||
test_review_filter_surfaces_protocol_draft_and_reason (test_desktop_review_visibility.DesktopReviewTest.test_review_filter_surfaces_protocol_draft_and_reason) ... ok
|
||||
test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff (test_desktop_review_visibility.DesktopReviewTest.test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff) ... ok
|
||||
test_stopped_handoff_uses_offline_resolution_and_preserves_seen (test_desktop_review_visibility.DesktopReviewTest.test_stopped_handoff_uses_offline_resolution_and_preserves_seen) ... ok
|
||||
test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve (test_desktop_review_visibility.DesktopReviewTest.test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve) ... ok
|
||||
test_generation_failure_is_retryable_but_not_sendable (test_desktop_review_visibility.ReviewStateTest.test_generation_failure_is_retryable_but_not_sendable) ... ok
|
||||
test_media_without_draft_cannot_be_approved (test_desktop_review_visibility.ReviewStateTest.test_media_without_draft_cannot_be_approved) ... ok
|
||||
test_protocol_and_visual_reviews_have_the_same_action_contract (test_desktop_review_visibility.ReviewStateTest.test_protocol_and_visual_reviews_have_the_same_action_contract) ... ok
|
||||
test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag (test_desktop_review_visibility.ReviewStateTest.test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag) ... ok
|
||||
test_a_blank_name_leaves_the_current_one_alone (test_qt_console_bridge.ConsoleBridgeTest.test_a_blank_name_leaves_the_current_one_alone)
|
||||
空名字是"没填",不是"改成空"——改成空会让提示词里出现一个没有名字的客服。 ... ok
|
||||
test_a_failed_connection_says_why_in_the_log (test_qt_console_bridge.ConsoleBridgeTest.test_a_failed_connection_says_why_in_the_log)
|
||||
失败必须留下原因。只说"连接失败"的话,人不知道是地址错了还是后台没起。 ... ok
|
||||
test_an_over_long_agent_name_is_truncated (test_qt_console_bridge.ConsoleBridgeTest.test_an_over_long_agent_name_is_truncated)
|
||||
昵称会拼进系统提示词,不能让它无限长。 ... ok
|
||||
test_approve_task_reaches_the_host_with_the_exact_key (test_qt_console_bridge.ConsoleBridgeTest.test_approve_task_reaches_the_host_with_the_exact_key)
|
||||
「通过并发送」必须真的连到后端。 ... ok
|
||||
test_approving_a_task_that_left_the_queue_sends_nothing (test_qt_console_bridge.ConsoleBridgeTest.test_approving_a_task_that_left_the_queue_sends_nothing)
|
||||
任务已经不在队列里就别再放行——否则可能把草稿发到别的会话去。 ... ok
|
||||
test_archive_date_button_uses_real_business_filter (test_qt_console_bridge.ConsoleBridgeTest.test_archive_date_button_uses_real_business_filter) ... ok
|
||||
test_archive_selection_only_commits_an_existing_visible_key (test_qt_console_bridge.ConsoleBridgeTest.test_archive_selection_only_commits_an_existing_visible_key) ... ok
|
||||
test_auto_send_header_selects_auto_mode_before_starting (test_qt_console_bridge.ConsoleBridgeTest.test_auto_send_header_selects_auto_mode_before_starting) ... ok
|
||||
test_canvas_uses_available_logical_space_without_design_minimum (test_qt_console_bridge.ConsoleBridgeTest.test_canvas_uses_available_logical_space_without_design_minimum) ... ok
|
||||
test_connect_backend_forwards_the_url_to_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_connect_backend_forwards_the_url_to_the_host)
|
||||
控制台上填的后台地址要真的到得了后端。 ... ok
|
||||
test_console_html_and_javascript_assets_are_packaged_together (test_qt_console_bridge.ConsoleBridgeTest.test_console_html_and_javascript_assets_are_packaged_together) ... ok
|
||||
test_console_push_timer_coalesces_against_earliest_deadline (test_qt_console_bridge.ConsoleBridgeTest.test_console_push_timer_coalesces_against_earliest_deadline) ... ok
|
||||
test_editable_fields_look_editable (test_qt_console_bridge.ConsoleBridgeTest.test_editable_fields_look_editable)
|
||||
能改的地方要看得出来能改。 ... ok
|
||||
test_every_html_navigation_schedules_authoritative_state (test_qt_console_bridge.ConsoleBridgeTest.test_every_html_navigation_schedules_authoritative_state) ... ok
|
||||
test_every_save_button_gives_the_user_feedback (test_qt_console_bridge.ConsoleBridgeTest.test_every_save_button_gives_the_user_feedback)
|
||||
点了保存必须看得见反馈。 ... ok
|
||||
test_handoff_only_reports_tasks_the_backend_accepted (test_qt_console_bridge.ConsoleBridgeTest.test_handoff_only_reports_tasks_the_backend_accepted) ... ok
|
||||
test_long_pages_scroll_without_shrinking_text (test_qt_console_bridge.ConsoleBridgeTest.test_long_pages_scroll_without_shrinking_text) ... ok
|
||||
test_no_layout_container_keeps_a_hard_coded_height (test_qt_console_bridge.ConsoleBridgeTest.test_no_layout_container_keeps_a_hard_coded_height)
|
||||
去掉滚动条之后,"装不下"不再表现为滚动条,而是内容画到别的面板身上。 ... ok
|
||||
test_number_fields_tell_you_the_allowed_range (test_qt_console_bridge.ConsoleBridgeTest.test_number_fields_tell_you_the_allowed_range) ... ok
|
||||
test_page_grids_use_proportional_columns (test_qt_console_bridge.ConsoleBridgeTest.test_page_grids_use_proportional_columns)
|
||||
各栏必须按比例分配宽度。写死像素的话,舞台变宽它们也不会跟着变宽, ... ok
|
||||
test_queue_actions_select_exact_key_before_forwarding (test_qt_console_bridge.ConsoleBridgeTest.test_queue_actions_select_exact_key_before_forwarding) ... ok
|
||||
test_ready_state_delivery_updates_cache_only_after_emit (test_qt_console_bridge.ConsoleBridgeTest.test_ready_state_delivery_updates_cache_only_after_emit) ... ok
|
||||
test_request_state_forces_webchannel_handshake_payload (test_qt_console_bridge.ConsoleBridgeTest.test_request_state_forces_webchannel_handshake_payload) ... ok
|
||||
test_responsive_styles_are_bundled_after_reference_styles (test_qt_console_bridge.ConsoleBridgeTest.test_responsive_styles_are_bundled_after_reference_styles) ... ok
|
||||
test_same_view_state_push_preserves_sidebar_and_main_dom_identity (test_qt_console_bridge.ConsoleBridgeTest.test_same_view_state_push_preserves_sidebar_and_main_dom_identity) ... ok
|
||||
test_save_ai_only_applies_the_agent_name (test_qt_console_bridge.ConsoleBridgeTest.test_save_ai_only_applies_the_agent_name)
|
||||
AI 设置页现在只有客服昵称是真正的本机设置。 ... ok
|
||||
test_set_view_waits_for_loaded_document_and_replays_once (test_qt_console_bridge.ConsoleBridgeTest.test_set_view_waits_for_loaded_document_and_replays_once) ... ok
|
||||
test_sidebar_orb_is_wired_to_the_listen_toggle (test_qt_console_bridge.ConsoleBridgeTest.test_sidebar_orb_is_wired_to_the_listen_toggle)
|
||||
侧栏那颗球是用户最常点的开关,HTML 上必须真的绑着动作。 ... ok
|
||||
test_stale_queue_key_never_mutates_previous_selection (test_qt_console_bridge.ConsoleBridgeTest.test_stale_queue_key_never_mutates_previous_selection) ... ok
|
||||
test_state_is_not_cached_before_webchannel_handshake (test_qt_console_bridge.ConsoleBridgeTest.test_state_is_not_cached_before_webchannel_handshake) ... ok
|
||||
test_the_console_script_handles_that_action (test_qt_console_bridge.ConsoleBridgeTest.test_the_console_script_handles_that_action) ... ok
|
||||
test_the_feedback_helper_covers_pending_result_and_failure (test_qt_console_bridge.ConsoleBridgeTest.test_the_feedback_helper_covers_pending_result_and_failure)
|
||||
反馈要三段齐全:立刻响应、真实结果、失败也要说清。 ... ok
|
||||
test_the_save_slots_report_their_result_back (test_qt_console_bridge.ConsoleBridgeTest.test_the_save_slots_report_their_result_back)
|
||||
Qt 侧的保存槽必须把结果回传,否则网页那边永远只能瞎猜。 ... ok
|
||||
test_the_scale_never_depends_on_page_height_or_device_pixel_ratio (test_qt_console_bridge.ConsoleBridgeTest.test_the_scale_never_depends_on_page_height_or_device_pixel_ratio) ... ok
|
||||
test_the_side_rail_height_does_not_follow_page_content (test_qt_console_bridge.ConsoleBridgeTest.test_the_side_rail_height_does_not_follow_page_content)
|
||||
侧栏在每一页必须一样高。 ... ok
|
||||
test_toggle_listen_starts_and_stops_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_toggle_listen_starts_and_stops_the_host) ... ok
|
||||
test_all_receipt_variants_require_explicit_confirmation_at_mutation_time (test_handoff_safety.OfflineHandoffSafetyTests.test_all_receipt_variants_require_explicit_confirmation_at_mutation_time) ... ok
|
||||
test_sending_stage_cannot_be_removed_even_after_confirmation (test_handoff_safety.OfflineHandoffSafetyTests.test_sending_stage_cannot_be_removed_even_after_confirmation) ... ok
|
||||
test_startup_confirmation_is_per_task_not_batch_wide (test_handoff_safety.OfflineHandoffSafetyTests.test_startup_confirmation_is_per_task_not_batch_wide) ... ok
|
||||
test_stage_only_receipt_blocks_approval_retry_cancel_and_incoming_replacement (test_handoff_safety.ProtocolHandoffSafetyTests.test_stage_only_receipt_blocks_approval_retry_cancel_and_incoming_replacement) ... ok
|
||||
test_stage_only_sending_is_protected_then_restores_as_unknown_receipt (test_handoff_safety.ProtocolHandoffSafetyTests.test_stage_only_sending_is_protected_then_restores_as_unknown_receipt) ... ok
|
||||
test_stale_ui_snapshot_cannot_handoff_newly_uncertain_response (test_handoff_safety.ProtocolHandoffSafetyTests.test_stale_ui_snapshot_cannot_handoff_newly_uncertain_response) ... ok
|
||||
test_legacy_visual_queue_upgrades_to_envelope_and_retains_full_evidence (test_handoff_evidence.OfflineEvidenceTests.test_legacy_visual_queue_upgrades_to_envelope_and_retains_full_evidence) ... ok
|
||||
test_write_failure_preserves_original_queue_and_evidence (test_handoff_evidence.OfflineEvidenceTests.test_write_failure_preserves_original_queue_and_evidence) ... ok
|
||||
test_failed_persist_rolls_back_memory_and_keeps_pause (test_handoff_evidence.ProtocolEvidenceTests.test_failed_persist_rolls_back_memory_and_keeps_pause) ... ok
|
||||
test_takeover_record_survives_restart_and_poll_without_becoming_pending (test_handoff_evidence.ProtocolEvidenceTests.test_takeover_record_survives_restart_and_poll_without_becoming_pending) ... ok
|
||||
test_active_send_and_other_account_stay_protected (test_review_handoff.ProtocolHandoffTests.test_active_send_and_other_account_stay_protected) ... ok
|
||||
test_explicit_takeover_releases_pause_without_send_or_receipt_change (test_review_handoff.ProtocolHandoffTests.test_explicit_takeover_releases_pause_without_send_or_receipt_change) ... ok
|
||||
test_failed_send_can_be_taken_over_without_retry (test_review_handoff.ProtocolHandoffTests.test_failed_send_can_be_taken_over_without_retry) ... ok
|
||||
test_other_uncertain_tasks_keep_pause (test_review_handoff.ProtocolHandoffTests.test_other_uncertain_tasks_keep_pause) ... ok
|
||||
test_handoff_during_startup_keeps_takeover_semantics (test_review_handoff.RuntimeHandoffTests.test_handoff_during_startup_keeps_takeover_semantics) ... ok
|
||||
test_live_protocol_takeover_uses_distinct_engine_action (test_review_handoff.RuntimeHandoffTests.test_live_protocol_takeover_uses_distinct_engine_action) ... ok
|
||||
test_offline_takeover_preserves_dedup_and_does_not_claim_delivery (test_review_handoff.RuntimeHandoffTests.test_offline_takeover_preserves_dedup_and_does_not_claim_delivery) ... ok
|
||||
test_visual_engine_falls_back_to_guarded_cancellation (test_review_handoff.RuntimeHandoffTests.test_visual_engine_falls_back_to_guarded_cancellation) ... ok
|
||||
test_existing_system_notice_is_checked_before_generation (test_contact_reply_guard.ProtocolContactTests.test_existing_system_notice_is_checked_before_generation) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议跳过] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复
|
||||
ok
|
||||
test_failed_notice_lookup_keeps_unknown_send_protected (test_contact_reply_guard.ProtocolContactTests.test_failed_notice_lookup_keeps_unknown_send_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 本会话发送结果待人工核对,其他会话继续监听;callback timeout
|
||||
ok
|
||||
test_notice_arriving_during_generation_cancels_draft (test_contact_reply_guard.ProtocolContactTests.test_notice_arriving_during_generation_cancels_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议跳过] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复
|
||||
ok
|
||||
test_notice_blocks_one_chat_and_another_chat_still_sends (test_contact_reply_guard.ProtocolContactTests.test_notice_blocks_one_chat_and_another_chat_still_sends) ... [协议跳过] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_other_send_failure_remains_protected (test_contact_reply_guard.ProtocolContactTests.test_other_send_failure_remains_protected) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 客户端拒绝发送,需人工核对;network unavailable
|
||||
ok
|
||||
test_rejection_during_send_is_not_retried_after_restart (test_contact_reply_guard.ProtocolContactTests.test_rejection_during_send_is_not_retried_after_restart) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议跳过] 同名客户 · 该用户不是你的联系人
|
||||
ok
|
||||
test_restore_notice_allows_later_message (test_contact_reply_guard.ProtocolContactTests.test_restore_notice_allows_later_message) ... [协议跳过] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_unknown_receipt_with_contact_notice_isolated_without_resending (test_contact_reply_guard.ProtocolContactTests.test_unknown_receipt_with_contact_notice_isolated_without_resending) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议跳过] 同名客户 · 对方开启联系人验证,当前不是联系人,已跳过自动回复
|
||||
ok
|
||||
test_user_quoting_notice_does_not_disable_chat (test_contact_reply_guard.ProtocolContactTests.test_user_quoting_notice_does_not_disable_chat) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 193 tests in 8.264s
|
||||
|
||||
OK
|
||||
@@ -1,18 +0,0 @@
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
test_busy_refresh_does_not_start_a_second_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_busy_refresh_does_not_start_a_second_scan) ... ok
|
||||
test_first_load_automates_and_tab_return_does_not_retry_failure (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_first_load_automates_and_tab_return_does_not_retry_failure) ... ok
|
||||
test_manual_acquire_does_not_trigger_a_second_automatic_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_manual_acquire_does_not_trigger_a_second_automatic_scan) ... ok
|
||||
test_worker_error_exposes_manual_fallback (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_worker_error_exposes_manual_fallback) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 13 tests in 0.620s
|
||||
|
||||
OK
|
||||
@@ -1,18 +0,0 @@
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
test_busy_refresh_does_not_start_a_second_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_busy_refresh_does_not_start_a_second_scan) ... ok
|
||||
test_first_load_automates_and_tab_return_does_not_retry_failure (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_first_load_automates_and_tab_return_does_not_retry_failure) ... ok
|
||||
test_manual_acquire_does_not_trigger_a_second_automatic_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_manual_acquire_does_not_trigger_a_second_automatic_scan) ... ok
|
||||
test_worker_error_exposes_manual_fallback (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_worker_error_exposes_manual_fallback) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 13 tests in 0.677s
|
||||
|
||||
OK
|
||||
@@ -1,267 +0,0 @@
|
||||
test_actual_send_mode_never_uses_probe_hash_cache (test_protocol_probe_performance.BuildHashReuseTests.test_actual_send_mode_never_uses_probe_hash_cache) ... ok
|
||||
test_changed_binary_is_not_reused_with_same_process (test_protocol_probe_performance.BuildHashReuseTests.test_changed_binary_is_not_reused_with_same_process) ... ok
|
||||
test_file_change_during_hash_fails_closed (test_protocol_probe_performance.BuildHashReuseTests.test_file_change_during_hash_fails_closed) ... ok
|
||||
test_native_client_still_validates_live_identity_each_time (test_protocol_probe_performance.BuildHashReuseTests.test_native_client_still_validates_live_identity_each_time) ... ok
|
||||
test_new_pid_and_reused_pid_with_new_creation_time_rehash (test_protocol_probe_performance.BuildHashReuseTests.test_new_pid_and_reused_pid_with_new_creation_time_rehash) ... ok
|
||||
test_one_probe_reads_same_process_build_once_but_next_probe_rechecks (test_protocol_probe_performance.BuildHashReuseTests.test_one_probe_reads_same_process_build_once_but_next_probe_rechecks) ... ok
|
||||
test_unavailable_process_start_time_does_not_enable_cache (test_protocol_probe_performance.BuildHashReuseTests.test_unavailable_process_start_time_does_not_enable_cache) ... ok
|
||||
test_change_after_database_check_is_never_hidden_by_static_reuse (test_protocol_probe_performance.ProbeFreshnessTests.test_change_after_database_check_is_never_hidden_by_static_reuse) ... ok
|
||||
test_repeated_probes_revalidate_account_and_database (test_protocol_probe_performance.ProbeFreshnessTests.test_repeated_probes_revalidate_account_and_database) ... ok
|
||||
test_actual_reply_startup_loads_current_account_metadata (test_protocol_probe_performance.ScopedDatabaseTests.test_actual_reply_startup_loads_current_account_metadata) ... ok
|
||||
test_default_database_keeps_all_account_and_metadata_behavior (test_protocol_probe_performance.ScopedDatabaseTests.test_default_database_keeps_all_account_and_metadata_behavior) ... ok
|
||||
test_other_account_cache_cannot_prove_current_account_ready (test_protocol_probe_performance.ScopedDatabaseTests.test_other_account_cache_cannot_prove_current_account_ready) ... ok
|
||||
test_probe_prepares_only_current_message_database_without_metadata (test_protocol_probe_performance.ScopedDatabaseTests.test_probe_prepares_only_current_message_database_without_metadata) ... ok
|
||||
test_schema_check_is_preserved_in_lightweight_probe (test_protocol_probe_performance.ScopedDatabaseTests.test_schema_check_is_preserved_in_lightweight_probe) ... ok
|
||||
test_unsafe_account_or_database_name_is_rejected (test_protocol_probe_performance.ScopedDatabaseTests.test_unsafe_account_or_database_name_is_rejected) ... ok
|
||||
test_only_success_resumes_pending_start (test_protocol_cross_machine.GuiTests.test_only_success_resumes_pending_start) ... ok
|
||||
test_saved_protocol_gets_auto_probe_and_recent_report_is_reused (test_protocol_cross_machine.GuiTests.test_saved_protocol_gets_auto_probe_and_recent_report_is_reused) ... ok
|
||||
test_start_waits_without_constructing_sender (test_protocol_cross_machine.GuiTests.test_start_waits_without_constructing_sender) ... ok
|
||||
test_stop_cancels_delayed_start (test_protocol_cross_machine.GuiTests.test_stop_cancels_delayed_start) ... ok
|
||||
test_account_change_and_exit_during_initialization_are_blocked (test_protocol_cross_machine.ProbeTests.test_account_change_and_exit_during_initialization_are_blocked) ... ok
|
||||
test_custom_install_path_needs_no_sdk (test_protocol_cross_machine.ProbeTests.test_custom_install_path_needs_no_sdk) ... ok
|
||||
test_database_failure_cannot_report_ready (test_protocol_cross_machine.ProbeTests.test_database_failure_cannot_report_ready) ... ok
|
||||
test_missing_database_flag_never_enables_sender (test_protocol_cross_machine.ProbeTests.test_missing_database_flag_never_enables_sender) ... ok
|
||||
test_not_running_still_reports_custom_install (test_protocol_cross_machine.ProbeTests.test_not_running_still_reports_custom_install) ... ok
|
||||
test_real_failure_is_visible_instead_of_sdk_message (test_protocol_cross_machine.ProbeTests.test_real_failure_is_visible_instead_of_sdk_message) ... ok
|
||||
test_unsupported_version_or_architecture_does_not_access_sender (test_protocol_cross_machine.ProbeTests.test_unsupported_version_or_architecture_does_not_access_sender) ... ok
|
||||
test_current_account_ignores_stale_saved_directory (test_protocol_cross_machine.StorageTests.test_current_account_ignores_stale_saved_directory) ... ok
|
||||
test_encrypted_first_install_initializes_only_current_machine_keys (test_protocol_cross_machine.StorageTests.test_encrypted_first_install_initializes_only_current_machine_keys) ... ok
|
||||
test_fresh_account_with_plain_db_needs_no_key_worker (test_protocol_cross_machine.StorageTests.test_fresh_account_with_plain_db_needs_no_key_worker) ... ok
|
||||
test_historical_account_and_empty_sqlite_cannot_prove_readiness (test_protocol_cross_machine.StorageTests.test_historical_account_and_empty_sqlite_cannot_prove_readiness) ... ok
|
||||
test_passive_check_does_not_acquire_keys (test_protocol_cross_machine.StorageTests.test_passive_check_does_not_acquire_keys) ... ok
|
||||
test_registered_data_directory_takes_effect (test_protocol_cross_machine.StorageTests.test_registered_data_directory_takes_effect) ... ok
|
||||
test_registry_uses_both_views_and_ignores_numeric_data_flag (test_protocol_cross_machine.StorageTests.test_registry_uses_both_views_and_ignores_numeric_data_flag) ... ok
|
||||
test_root_account_data_and_file_paths_with_unicode_spaces (test_protocol_cross_machine.StorageTests.test_root_account_data_and_file_paths_with_unicode_spaces) ... ok
|
||||
test_exact_hash_required_and_versions_do_not_share_layouts (test_native_builds.BuildTests.test_exact_hash_required_and_versions_do_not_share_layouts) ... ok
|
||||
test_new_version_detection_reports_validation_state (test_native_builds.BuildTests.test_new_version_detection_reports_validation_state) ... ok
|
||||
test_unverified_build_cannot_be_enabled_by_report_flags (test_native_builds.BuildTests.test_unverified_build_cannot_be_enabled_by_report_flags) ... ok
|
||||
test_account_change_while_opening_write_handle_cancels (test_native_evidence.ClientGateTests.test_account_change_while_opening_write_handle_cancels) ... ok
|
||||
test_confirmed_evidence_allows_write_after_readonly_identity_check (test_native_evidence.ClientGateTests.test_confirmed_evidence_allows_write_after_readonly_identity_check) ... ok
|
||||
test_pending_build_cannot_even_acquire_write_handle_without_evidence (test_native_evidence.ClientGateTests.test_pending_build_cannot_even_acquire_write_handle_without_evidence) ... ok
|
||||
test_confirmed_evidence_is_account_build_and_revision_bound (test_native_evidence.EvidenceTests.test_confirmed_evidence_is_account_build_and_revision_bound) ... ok
|
||||
test_failed_incomplete_or_wrong_receipt_cannot_enable (test_native_evidence.EvidenceTests.test_failed_incomplete_or_wrong_receipt_cannot_enable) ... ok
|
||||
test_no_evidence_does_not_create_database_or_enable_sending (test_native_evidence.EvidenceTests.test_no_evidence_does_not_create_database_or_enable_sending) ... ok
|
||||
test_only_fixed_manual_test_with_matching_fingerprint_counts (test_native_evidence.EvidenceTests.test_only_fixed_manual_test_with_matching_fingerprint_counts) ... ok
|
||||
test_probe_moves_to_ready_only_after_confirmed_journal (test_native_evidence.EvidenceTests.test_probe_moves_to_ready_only_after_confirmed_journal) ... ok
|
||||
test_report_flags_and_exported_json_do_not_enable_without_journal (test_native_evidence.EvidenceTests.test_report_flags_and_exported_json_do_not_enable_without_journal) ... ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 发送结果待人工核对,已暂停监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_is_paused_without_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_is_paused_without_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_bad_or_oversized_history_is_ignored (test_wecom_native_protocol.NativeHistoryTest.test_bad_or_oversized_history_is_ignored) ... ok
|
||||
test_different_business_results_do_not_imply_open_access (test_wecom_native_protocol.NativeHistoryTest.test_different_business_results_do_not_imply_open_access) ... ok
|
||||
test_history_cannot_enable_sender_or_export_unknown_fields (test_wecom_native_protocol.NativeHistoryTest.test_history_cannot_enable_sender_or_export_unknown_fields) ... ok
|
||||
test_version_mismatch_remains_explicit (test_wecom_native_protocol.NativeHistoryTest.test_version_mismatch_remains_explicit) ... ok
|
||||
test_actual_gray_error_nested_inside_http_200 (test_wecom_native_protocol.NativeReplyTest.test_actual_gray_error_nested_inside_http_200) ... ok
|
||||
test_error_text_is_not_exposed (test_wecom_native_protocol.NativeReplyTest.test_error_text_is_not_exposed) ... ok
|
||||
test_incomplete_transport_wrong_id_and_malformed_json_are_rejected (test_wecom_native_protocol.NativeReplyTest.test_incomplete_transport_wrong_id_and_malformed_json_are_rejected) ... ok
|
||||
test_initialize_and_tools_list_are_transport_results_only (test_wecom_native_protocol.NativeReplyTest.test_initialize_and_tools_list_are_transport_results_only) ... ok
|
||||
test_nested_malformed_response_and_depth_are_bounded (test_wecom_native_protocol.NativeReplyTest.test_nested_malformed_response_and_depth_are_bounded) ... ok
|
||||
test_outer_and_tool_errors_are_never_success (test_wecom_native_protocol.NativeReplyTest.test_outer_and_tool_errors_are_never_success) ... ok
|
||||
test_actual_web_page_protocol_state_buttons_and_visual_return (test_protocol_features.ProtocolGuiTest.test_actual_web_page_protocol_state_buttons_and_visual_return) ... ok
|
||||
test_detection_state_keeps_binary_paths_out_of_web_payload (test_protocol_features.ProtocolGuiTest.test_detection_state_keeps_binary_paths_out_of_web_payload) ... ok
|
||||
test_probe_worker_coalesces_clicks_and_delivers_failures (test_protocol_features.ProtocolGuiTest.test_probe_worker_coalesces_clicks_and_delivers_failures) ... ok
|
||||
test_qt_and_classic_keep_protocol_even_when_other_settings_are_corrupt (test_protocol_features.ProtocolGuiTest.test_qt_and_classic_keep_protocol_even_when_other_settings_are_corrupt) ... ok
|
||||
test_qt_persists_transport_and_restores_memory_after_disk_failure (test_protocol_features.ProtocolGuiTest.test_qt_persists_transport_and_restores_memory_after_disk_failure) ... ok
|
||||
test_qt_protocol_start_passes_transport_to_background_thread (test_protocol_features.ProtocolGuiTest.test_qt_protocol_start_passes_transport_to_background_thread) ... ok
|
||||
test_transport_change_is_saved_and_rejected_while_running (test_protocol_features.ProtocolGuiTest.test_transport_change_is_saved_and_rejected_while_running) ... ok
|
||||
test_duplicate_names_and_server_ids_remain_isolated_by_exact_account_conversation (test_protocol_features.ProtocolIdContextTest.test_duplicate_names_and_server_ids_remain_isolated_by_exact_account_conversation) ... ok
|
||||
test_missing_account_unknown_conversation_and_group_never_guess (test_protocol_features.ProtocolIdContextTest.test_missing_account_unknown_conversation_and_group_never_guess) ... ok
|
||||
test_atomic_export_does_not_destroy_existing_report_on_failure (test_protocol_features.ProtocolProbeTest.test_atomic_export_does_not_destroy_existing_report_on_failure) ... ok
|
||||
test_installed_client_and_bundled_sdk_never_imply_send_or_login (test_protocol_features.ProtocolProbeTest.test_installed_client_and_bundled_sdk_never_imply_send_or_login) ... ok
|
||||
test_no_client_and_inaccessible_client (test_protocol_features.ProtocolProbeTest.test_no_client_and_inaccessible_client) ... ok
|
||||
test_pe_architecture_and_corrupt_header (test_protocol_features.ProtocolProbeTest.test_pe_architecture_and_corrupt_header) ... ok
|
||||
test_database_failure_is_propagated_and_request_identity_includes_limit (test_protocol_features.ProtocolRoutingTest.test_database_failure_is_propagated_and_request_identity_includes_limit) ... ok
|
||||
test_invalid_explicit_transport_never_defaults_to_visual (test_protocol_features.ProtocolRoutingTest.test_invalid_explicit_transport_never_defaults_to_visual) ... ok
|
||||
test_protocol_start_never_constructs_visual_sender_even_with_true_flag (test_protocol_features.ProtocolRoutingTest.test_protocol_start_never_constructs_visual_sender_even_with_true_flag) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_cloud_failure_is_recorded_for_retry (test_archive_upload_flow.ArchiveUploadFlowTest.test_cloud_failure_is_recorded_for_retry) ... ok
|
||||
test_desktop_keys_allow_upload_without_legacy_key_file (test_archive_upload_flow.ArchiveUploadFlowTest.test_desktop_keys_allow_upload_without_legacy_key_file) ... ok
|
||||
test_disabled_cloud_policy_never_launches_upload (test_archive_upload_flow.ArchiveUploadFlowTest.test_disabled_cloud_policy_never_launches_upload) ... ok
|
||||
test_disabled_policy_overrides_old_success (test_archive_upload_flow.ArchiveUploadFlowTest.test_disabled_policy_overrides_old_success) ... ok
|
||||
test_encrypted_database_to_cloud_client_and_checkpoint (test_archive_upload_flow.ArchiveUploadFlowTest.test_encrypted_database_to_cloud_client_and_checkpoint) ... ERROR
|
||||
test_installed_build_ignores_stale_override (test_archive_upload_flow.ArchiveUploadFlowTest.test_installed_build_ignores_stale_override) ... ok
|
||||
test_key_acquisition_failure_is_recorded_without_upload (test_archive_upload_flow.ArchiveUploadFlowTest.test_key_acquisition_failure_is_recorded_without_upload) ... ok
|
||||
test_missing_keys_are_acquired_once_then_decryption_retried (test_archive_upload_flow.ArchiveUploadFlowTest.test_missing_keys_are_acquired_once_then_decryption_retried) ... ok
|
||||
test_source_local_legacy_port_fallback (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_local_legacy_port_fallback) ... ok
|
||||
test_source_retains_explicit_development_endpoint (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_retains_explicit_development_endpoint) ... ok
|
||||
test_source_uses_configured_cloud_without_local_fallback (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_uses_configured_cloud_without_local_fallback) ... ok
|
||||
test_startup_uploads_immediately_then_respects_interval (test_archive_upload_flow.ArchiveUploadFlowTest.test_startup_uploads_immediately_then_respects_interval) ... ok
|
||||
test_status_handles_missing_and_malformed_file (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_handles_missing_and_malformed_file) ... ok
|
||||
test_status_removes_signed_storage_url_query (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_removes_signed_storage_url_query) ... ok
|
||||
test_status_shows_success_and_running_without_raw_fields (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_shows_success_and_running_without_raw_fields) ... ok
|
||||
|
||||
======================================================================
|
||||
ERROR: test_encrypted_database_to_cloud_client_and_checkpoint (test_archive_upload_flow.ArchiveUploadFlowTest.test_encrypted_database_to_cloud_client_and_checkpoint)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "C:\wechat_rpa\test_archive_upload_flow.py", line 131, in test_encrypted_database_to_cloud_client_and_checkpoint
|
||||
check_database_initialization()
|
||||
File "C:\wechat_rpa\packaging_checks.py", line 128, in check_database_initialization
|
||||
_check_archive_upload(source, data)
|
||||
File "C:\wechat_rpa\packaging_checks.py", line 272, in _check_archive_upload
|
||||
first = archive.run_backup_once(config)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\wechat_rpa\archive_auto_backup.py", line 1558, in run_backup_once
|
||||
api = ArchiveApiClient.connect(config.api_urls)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\wechat_rpa\archive_auto_backup.py", line 441, in connect
|
||||
response = client.session.get(
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\isard\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\sessions.py", line 671, in get
|
||||
return self.request("GET", url, params=params, **kwargs)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\isard\AppData\Local\Programs\Python\Python311\Lib\unittest\mock.py", line 1124, in __call__
|
||||
return self._mock_call(*args, **kwargs)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\isard\AppData\Local\Programs\Python\Python311\Lib\unittest\mock.py", line 1128, in _mock_call
|
||||
return self._execute_mock_call(*args, **kwargs)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\isard\AppData\Local\Programs\Python\Python311\Lib\unittest\mock.py", line 1189, in _execute_mock_call
|
||||
result = effect(*args, **kwargs)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\kefu\deploy\loading-performance-20260917\run_isolated.py", line 38, in reject
|
||||
raise RuntimeError("Audit blocks real external action: " + name)
|
||||
RuntimeError: Audit blocks real external action: HTTP request
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 157 tests in 7.405s
|
||||
|
||||
FAILED (errors=1)
|
||||
@@ -1,130 +0,0 @@
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
test_busy_refresh_does_not_start_a_second_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_busy_refresh_does_not_start_a_second_scan) ... ok
|
||||
test_first_load_automates_and_tab_return_does_not_retry_failure (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_first_load_automates_and_tab_return_does_not_retry_failure) ... ok
|
||||
test_manual_acquire_does_not_trigger_a_second_automatic_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_manual_acquire_does_not_trigger_a_second_automatic_scan) ... ok
|
||||
test_worker_error_exposes_manual_fallback (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_worker_error_exposes_manual_fallback) ... ok
|
||||
test_empty_cache_returns_actionable_error (test_wxwork_message_browser.WeChatMessageBrowserTests.test_empty_cache_returns_actionable_error) ... ok
|
||||
test_lists_databases_conversations_and_messages (test_wxwork_message_browser.WeChatMessageBrowserTests.test_lists_databases_conversations_and_messages) ... ok
|
||||
test_selects_conversation_and_filters (test_wxwork_message_browser.WeChatMessageBrowserTests.test_selects_conversation_and_filters) ... ok
|
||||
test_cached_message_page_makes_no_sqlite_queries (test_wxwork_browser_performance.BrowserPerformanceTest.test_cached_message_page_makes_no_sqlite_queries) ... ok
|
||||
test_concurrent_account_switches_cannot_leak_another_accounts_page (test_wxwork_browser_performance.BrowserPerformanceTest.test_concurrent_account_switches_cannot_leak_another_accounts_page) ... ok
|
||||
test_concurrent_navigation_uses_consistent_cache (test_wxwork_browser_performance.BrowserPerformanceTest.test_concurrent_navigation_uses_consistent_cache) ... ok
|
||||
test_content_search_checks_all_conversations (test_wxwork_browser_performance.BrowserPerformanceTest.test_content_search_checks_all_conversations) ... ok
|
||||
test_conversation_and_message_offsets_are_stable_with_timestamp_ties (test_wxwork_browser_performance.BrowserPerformanceTest.test_conversation_and_message_offsets_are_stable_with_timestamp_ties) ... ok
|
||||
test_database_replace_with_preserved_mtime_and_size_invalidates_inode (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replace_with_preserved_mtime_and_size_invalidates_inode) ... ok
|
||||
test_database_replaced_between_index_and_message_read_cannot_leak_conversation (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replaced_between_index_and_message_read_cannot_leak_conversation) ... ok
|
||||
test_database_replaced_between_index_and_preview_read_cannot_leak_conversation (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replaced_between_index_and_preview_read_cannot_leak_conversation) ... ok
|
||||
test_deletion_invalidates_message_and_conversation_counts (test_wxwork_browser_performance.BrowserPerformanceTest.test_deletion_invalidates_message_and_conversation_counts) ... ok
|
||||
test_multiple_accounts_do_not_rebuild_unselected_indexes (test_wxwork_browser_performance.BrowserPerformanceTest.test_multiple_accounts_do_not_rebuild_unselected_indexes) ... ok
|
||||
test_new_message_invalidates_counts_order_and_cached_page (test_wxwork_browser_performance.BrowserPerformanceTest.test_new_message_invalidates_counts_order_and_cached_page) ... ok
|
||||
test_reader_never_changes_source_database_or_adds_indexes (test_wxwork_browser_performance.BrowserPerformanceTest.test_reader_never_changes_source_database_or_adds_indexes) ... ok
|
||||
test_refresh_explicitly_invalidates_even_unchanged_metadata (test_wxwork_browser_performance.BrowserPerformanceTest.test_refresh_explicitly_invalidates_even_unchanged_metadata) ... ok
|
||||
test_rename_invalidates_names_without_touching_messages (test_wxwork_browser_performance.BrowserPerformanceTest.test_rename_invalidates_names_without_touching_messages) ... ok
|
||||
test_search_finds_conversations_older_than_the_newest_thousand (test_wxwork_browser_performance.BrowserPerformanceTest.test_search_finds_conversations_older_than_the_newest_thousand) ... ok
|
||||
test_search_offset_is_applied_after_filtering (test_wxwork_browser_performance.BrowserPerformanceTest.test_search_offset_is_applied_after_filtering) ... ok
|
||||
test_snapshots_do_not_expose_mutable_cache_objects (test_wxwork_browser_performance.BrowserPerformanceTest.test_snapshots_do_not_expose_mutable_cache_objects) ... ok
|
||||
test_system_conversations_are_excluded_but_total_message_count_is_exact (test_wxwork_browser_performance.BrowserPerformanceTest.test_system_conversations_are_excluded_but_total_message_count_is_exact) ... ok
|
||||
test_wal_only_commit_invalidates_without_main_db_change (test_wxwork_browser_performance.BrowserPerformanceTest.test_wal_only_commit_invalidates_without_main_db_change) ... ok
|
||||
test_warm_conversation_navigation_does_not_repeat_full_aggregates (test_wxwork_browser_performance.BrowserPerformanceTest.test_warm_conversation_navigation_does_not_repeat_full_aggregates) ... ok
|
||||
test_auto_failure_exposes_manual_fallback_and_refresh_retries (test_wxwork_local_setup.LocalDatabaseSetupTest.test_auto_failure_exposes_manual_fallback_and_refresh_retries) ... ok
|
||||
test_corrupt_fresh_cache_is_rebuilt_without_scanning (test_wxwork_local_setup.LocalDatabaseSetupTest.test_corrupt_fresh_cache_is_rebuilt_without_scanning) ... ok
|
||||
test_database_notice_keeps_specific_failure (test_wxwork_local_setup.LocalDatabaseSetupTest.test_database_notice_keeps_specific_failure) ... ok
|
||||
test_directory_choice_preserves_other_settings (test_wxwork_local_setup.LocalDatabaseSetupTest.test_directory_choice_preserves_other_settings) ... ok
|
||||
test_existing_key_and_plain_database_do_not_scan_processes (test_wxwork_local_setup.LocalDatabaseSetupTest.test_existing_key_and_plain_database_do_not_scan_processes) ... ok
|
||||
test_first_install_auto_discovers_and_decrypts_without_manual_input (test_wxwork_local_setup.LocalDatabaseSetupTest.test_first_install_auto_discovers_and_decrypts_without_manual_input) ... ok
|
||||
test_frozen_key_worker_uses_executable_without_python_script (test_wxwork_local_setup.LocalDatabaseSetupTest.test_frozen_key_worker_uses_executable_without_python_script) ... ok
|
||||
test_import_then_refresh_reads_encrypted_message (test_wxwork_local_setup.LocalDatabaseSetupTest.test_import_then_refresh_reads_encrypted_message) ... ok
|
||||
test_invalid_keys_produce_actionable_error_without_secret (test_wxwork_local_setup.LocalDatabaseSetupTest.test_invalid_keys_produce_actionable_error_without_secret) ... ok
|
||||
test_key_worker_only_persists_verified_keys (test_wxwork_local_setup.LocalDatabaseSetupTest.test_key_worker_only_persists_verified_keys) ... ok
|
||||
test_key_worker_timeout_and_no_process_are_actionable (test_wxwork_local_setup.LocalDatabaseSetupTest.test_key_worker_timeout_and_no_process_are_actionable) ... ok
|
||||
test_missing_directory_falls_back_without_scanning_processes (test_wxwork_local_setup.LocalDatabaseSetupTest.test_missing_directory_falls_back_without_scanning_processes) ... ok
|
||||
test_missing_key_is_not_reported_as_missing_database (test_wxwork_local_setup.LocalDatabaseSetupTest.test_missing_key_is_not_reported_as_missing_database) ... ok
|
||||
test_onedrive_directory_is_found_without_saved_config (test_wxwork_local_setup.LocalDatabaseSetupTest.test_onedrive_directory_is_found_without_saved_config) ... ok
|
||||
test_partial_accounts_trigger_auto_acquisition_and_manual_fallback (test_wxwork_local_setup.LocalDatabaseSetupTest.test_partial_accounts_trigger_auto_acquisition_and_manual_fallback) ... ok
|
||||
test_registry_documents_expands_environment_variables (test_wxwork_local_setup.LocalDatabaseSetupTest.test_registry_documents_expands_environment_variables) ... ok
|
||||
test_saved_custom_path_is_used_after_install (test_wxwork_local_setup.LocalDatabaseSetupTest.test_saved_custom_path_is_used_after_install) ... ok
|
||||
test_scanner_success_without_usable_key_is_still_a_failure (test_wxwork_local_setup.LocalDatabaseSetupTest.test_scanner_success_without_usable_key_is_still_a_failure) ... ok
|
||||
test_stale_or_malformed_key_automatically_recovers (test_wxwork_local_setup.LocalDatabaseSetupTest.test_stale_or_malformed_key_automatically_recovers) ... ok
|
||||
test_wrong_key_does_not_overwrite_saved_key (test_wxwork_local_setup.LocalDatabaseSetupTest.test_wrong_key_does_not_overwrite_saved_key) ... ok
|
||||
test_a_blank_name_leaves_the_current_one_alone (test_qt_console_bridge.ConsoleBridgeTest.test_a_blank_name_leaves_the_current_one_alone)
|
||||
空名字是"没填",不是"改成空"——改成空会让提示词里出现一个没有名字的客服。 ... ok
|
||||
test_a_failed_connection_says_why_in_the_log (test_qt_console_bridge.ConsoleBridgeTest.test_a_failed_connection_says_why_in_the_log)
|
||||
失败必须留下原因。只说"连接失败"的话,人不知道是地址错了还是后台没起。 ... ok
|
||||
test_an_over_long_agent_name_is_truncated (test_qt_console_bridge.ConsoleBridgeTest.test_an_over_long_agent_name_is_truncated)
|
||||
昵称会拼进系统提示词,不能让它无限长。 ... ok
|
||||
test_approve_task_reaches_the_host_with_the_exact_key (test_qt_console_bridge.ConsoleBridgeTest.test_approve_task_reaches_the_host_with_the_exact_key)
|
||||
「通过并发送」必须真的连到后端。 ... ok
|
||||
test_approving_a_task_that_left_the_queue_sends_nothing (test_qt_console_bridge.ConsoleBridgeTest.test_approving_a_task_that_left_the_queue_sends_nothing)
|
||||
任务已经不在队列里就别再放行——否则可能把草稿发到别的会话去。 ... ok
|
||||
test_archive_date_button_uses_real_business_filter (test_qt_console_bridge.ConsoleBridgeTest.test_archive_date_button_uses_real_business_filter) ... ok
|
||||
test_archive_selection_only_commits_an_existing_visible_key (test_qt_console_bridge.ConsoleBridgeTest.test_archive_selection_only_commits_an_existing_visible_key) ... ok
|
||||
test_auto_send_header_selects_auto_mode_before_starting (test_qt_console_bridge.ConsoleBridgeTest.test_auto_send_header_selects_auto_mode_before_starting) ... ok
|
||||
test_connect_backend_forwards_the_url_to_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_connect_backend_forwards_the_url_to_the_host)
|
||||
控制台上填的后台地址要真的到得了后端。 ... ok
|
||||
test_console_html_and_javascript_assets_are_packaged_together (test_qt_console_bridge.ConsoleBridgeTest.test_console_html_and_javascript_assets_are_packaged_together) ... ok
|
||||
test_console_push_timer_coalesces_against_earliest_deadline (test_qt_console_bridge.ConsoleBridgeTest.test_console_push_timer_coalesces_against_earliest_deadline) ... ok
|
||||
test_editable_fields_look_editable (test_qt_console_bridge.ConsoleBridgeTest.test_editable_fields_look_editable)
|
||||
能改的地方要看得出来能改。 ... ok
|
||||
test_every_html_navigation_schedules_authoritative_state (test_qt_console_bridge.ConsoleBridgeTest.test_every_html_navigation_schedules_authoritative_state) ... ok
|
||||
test_every_save_button_gives_the_user_feedback (test_qt_console_bridge.ConsoleBridgeTest.test_every_save_button_gives_the_user_feedback)
|
||||
点了保存必须看得见反馈。 ... ok
|
||||
test_handoff_only_reports_tasks_the_backend_accepted (test_qt_console_bridge.ConsoleBridgeTest.test_handoff_only_reports_tasks_the_backend_accepted) ... ok
|
||||
test_no_layout_container_keeps_a_hard_coded_height (test_qt_console_bridge.ConsoleBridgeTest.test_no_layout_container_keeps_a_hard_coded_height)
|
||||
去掉滚动条之后,"装不下"不再表现为滚动条,而是内容画到别的面板身上。 ... ok
|
||||
test_no_layout_scrolls_anywhere (test_qt_console_bridge.ConsoleBridgeTest.test_no_layout_scrolls_anywhere)
|
||||
整套界面不许出现滚动条——内容多了就往下铺,由整体缩放来兜。 ... ok
|
||||
test_number_fields_tell_you_the_allowed_range (test_qt_console_bridge.ConsoleBridgeTest.test_number_fields_tell_you_the_allowed_range) ... ok
|
||||
test_page_grids_use_proportional_columns (test_qt_console_bridge.ConsoleBridgeTest.test_page_grids_use_proportional_columns)
|
||||
各栏必须按比例分配宽度。写死像素的话,舞台变宽它们也不会跟着变宽, ... ok
|
||||
test_queue_actions_select_exact_key_before_forwarding (test_qt_console_bridge.ConsoleBridgeTest.test_queue_actions_select_exact_key_before_forwarding) ... ok
|
||||
test_ready_state_delivery_updates_cache_only_after_emit (test_qt_console_bridge.ConsoleBridgeTest.test_ready_state_delivery_updates_cache_only_after_emit) ... ok
|
||||
test_request_state_forces_webchannel_handshake_payload (test_qt_console_bridge.ConsoleBridgeTest.test_request_state_forces_webchannel_handshake_payload) ... ok
|
||||
test_same_view_state_push_preserves_sidebar_and_main_dom_identity (test_qt_console_bridge.ConsoleBridgeTest.test_same_view_state_push_preserves_sidebar_and_main_dom_identity) ... ok
|
||||
test_save_ai_only_applies_the_agent_name (test_qt_console_bridge.ConsoleBridgeTest.test_save_ai_only_applies_the_agent_name)
|
||||
AI 设置页现在只有客服昵称是真正的本机设置。 ... ok
|
||||
test_set_view_waits_for_loaded_document_and_replays_once (test_qt_console_bridge.ConsoleBridgeTest.test_set_view_waits_for_loaded_document_and_replays_once) ... ok
|
||||
test_sidebar_orb_is_wired_to_the_listen_toggle (test_qt_console_bridge.ConsoleBridgeTest.test_sidebar_orb_is_wired_to_the_listen_toggle)
|
||||
侧栏那颗球是用户最常点的开关,HTML 上必须真的绑着动作。 ... ok
|
||||
test_stale_queue_key_never_mutates_previous_selection (test_qt_console_bridge.ConsoleBridgeTest.test_stale_queue_key_never_mutates_previous_selection) ... ok
|
||||
test_state_is_not_cached_before_webchannel_handshake (test_qt_console_bridge.ConsoleBridgeTest.test_state_is_not_cached_before_webchannel_handshake) ... ok
|
||||
test_the_canvas_fills_the_window_in_both_directions (test_qt_console_bridge.ConsoleBridgeTest.test_the_canvas_fills_the_window_in_both_directions)
|
||||
画布要铺满窗口:高度按设计画布等比缩放,宽度靠加宽画布本身补齐。 ... ok
|
||||
test_the_console_script_handles_that_action (test_qt_console_bridge.ConsoleBridgeTest.test_the_console_script_handles_that_action) ... ok
|
||||
test_the_feedback_helper_covers_pending_result_and_failure (test_qt_console_bridge.ConsoleBridgeTest.test_the_feedback_helper_covers_pending_result_and_failure)
|
||||
反馈要三段齐全:立刻响应、真实结果、失败也要说清。 ... ok
|
||||
test_the_save_slots_report_their_result_back (test_qt_console_bridge.ConsoleBridgeTest.test_the_save_slots_report_their_result_back)
|
||||
Qt 侧的保存槽必须把结果回传,否则网页那边永远只能瞎猜。 ... ok
|
||||
test_the_scale_never_depends_on_which_page_is_open (test_qt_console_bridge.ConsoleBridgeTest.test_the_scale_never_depends_on_which_page_is_open)
|
||||
缩放只能由窗口尺寸决定,绝不能看当前页内容有多高。 ... ok
|
||||
test_the_side_rail_height_does_not_follow_page_content (test_qt_console_bridge.ConsoleBridgeTest.test_the_side_rail_height_does_not_follow_page_content)
|
||||
侧栏在每一页必须一样高。 ... ok
|
||||
test_the_stage_and_pages_grow_with_their_content (test_qt_console_bridge.ConsoleBridgeTest.test_the_stage_and_pages_grow_with_their_content)
|
||||
舞台和单页都必须是"下限高度",不能写死——写死就必然要么滚要么裁。 ... ok
|
||||
test_toggle_listen_starts_and_stops_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_toggle_listen_starts_and_stops_the_host) ... ok
|
||||
test_async_protocol_check_retains_explicit_approval_request (test_desktop_review_visibility.DesktopReviewTest.test_async_protocol_check_retains_explicit_approval_request) ... skipped 'This directory has no protocol transport'
|
||||
test_explicit_approval_reaches_thread_with_exact_key_and_refreshes (test_desktop_review_visibility.DesktopReviewTest.test_explicit_approval_reaches_thread_with_exact_key_and_refreshes) ... ok
|
||||
test_human_filter_includes_unknown_receipt_and_no_empty_send (test_desktop_review_visibility.DesktopReviewTest.test_human_filter_includes_unknown_receipt_and_no_empty_send) ... ok
|
||||
test_legacy_receipt_states_are_visible_but_not_sendable (test_desktop_review_visibility.DesktopReviewTest.test_legacy_receipt_states_are_visible_but_not_sendable) ... ok
|
||||
test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser (test_desktop_review_visibility.DesktopReviewTest.test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser) ... ok
|
||||
test_review_counts_remain_visible_under_an_unrelated_filter (test_desktop_review_visibility.DesktopReviewTest.test_review_counts_remain_visible_under_an_unrelated_filter) ... ok
|
||||
test_review_filter_surfaces_protocol_draft_and_reason (test_desktop_review_visibility.DesktopReviewTest.test_review_filter_surfaces_protocol_draft_and_reason) ... ok
|
||||
test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff (test_desktop_review_visibility.DesktopReviewTest.test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff) ... ok
|
||||
test_stopped_handoff_uses_offline_resolution_and_preserves_seen (test_desktop_review_visibility.DesktopReviewTest.test_stopped_handoff_uses_offline_resolution_and_preserves_seen) ... ok
|
||||
test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve (test_desktop_review_visibility.DesktopReviewTest.test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve) ... ok
|
||||
test_generation_failure_is_retryable_but_not_sendable (test_desktop_review_visibility.ReviewStateTest.test_generation_failure_is_retryable_but_not_sendable) ... ok
|
||||
test_media_without_draft_cannot_be_approved (test_desktop_review_visibility.ReviewStateTest.test_media_without_draft_cannot_be_approved) ... ok
|
||||
test_protocol_and_visual_reviews_have_the_same_action_contract (test_desktop_review_visibility.ReviewStateTest.test_protocol_and_visual_reviews_have_the_same_action_contract) ... ok
|
||||
test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag (test_desktop_review_visibility.ReviewStateTest.test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 106 tests in 6.222s
|
||||
|
||||
OK (skipped=1)
|
||||
@@ -1,356 +0,0 @@
|
||||
test_completed_result_is_not_reused_for_later_explicit_refresh (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_completed_result_is_not_reused_for_later_explicit_refresh) ... ok
|
||||
test_failure_is_shared_and_does_not_poison_later_retry (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_failure_is_shared_and_does_not_poison_later_retry) ... ok
|
||||
test_simultaneous_browser_and_protocol_initialization_start_one_worker (test_database_loading_performance.KeyAcquisitionSingleFlightTest.test_simultaneous_browser_and_protocol_initialization_start_one_worker) ... ok
|
||||
test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query (test_database_loading_performance.LocalFirstLoaderTest.test_busy_navigation_is_coalesced_to_latest_account_conversation_and_query) ... ok
|
||||
test_local_chat_arrives_before_remote_lookup_begins (test_database_loading_performance.LocalFirstLoaderTest.test_local_chat_arrives_before_remote_lookup_begins) ... ok
|
||||
test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued (test_database_loading_performance.LocalFirstLoaderTest.test_old_patient_result_never_replaces_new_selection_and_only_latest_is_queued) ... ok
|
||||
test_remote_timeout_keeps_local_chat_visible_and_not_setup_error (test_database_loading_performance.LocalFirstLoaderTest.test_remote_timeout_keeps_local_chat_visible_and_not_setup_error) ... ok
|
||||
test_repeated_refresh_during_load_does_not_queue_another_initialization (test_database_loading_performance.LocalFirstLoaderTest.test_repeated_refresh_during_load_does_not_queue_another_initialization) ... ok
|
||||
test_stale_database_result_is_ignored (test_database_loading_performance.LocalFirstLoaderTest.test_stale_database_result_is_ignored) ... ok
|
||||
test_busy_refresh_does_not_start_a_second_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_busy_refresh_does_not_start_a_second_scan) ... ok
|
||||
test_first_load_automates_and_tab_return_does_not_retry_failure (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_first_load_automates_and_tab_return_does_not_retry_failure) ... ok
|
||||
test_manual_acquire_does_not_trigger_a_second_automatic_scan (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_manual_acquire_does_not_trigger_a_second_automatic_scan) ... ok
|
||||
test_worker_error_exposes_manual_fallback (test_wechat_database_flow.AutomaticDatabaseFlowTest.test_worker_error_exposes_manual_fallback) ... ok
|
||||
test_empty_cache_returns_actionable_error (test_wxwork_message_browser.WeChatMessageBrowserTests.test_empty_cache_returns_actionable_error) ... ok
|
||||
test_lists_databases_conversations_and_messages (test_wxwork_message_browser.WeChatMessageBrowserTests.test_lists_databases_conversations_and_messages) ... ok
|
||||
test_selects_conversation_and_filters (test_wxwork_message_browser.WeChatMessageBrowserTests.test_selects_conversation_and_filters) ... ok
|
||||
test_cached_message_page_makes_no_sqlite_queries (test_wxwork_browser_performance.BrowserPerformanceTest.test_cached_message_page_makes_no_sqlite_queries) ... ok
|
||||
test_concurrent_account_switches_cannot_leak_another_accounts_page (test_wxwork_browser_performance.BrowserPerformanceTest.test_concurrent_account_switches_cannot_leak_another_accounts_page) ... ok
|
||||
test_concurrent_navigation_uses_consistent_cache (test_wxwork_browser_performance.BrowserPerformanceTest.test_concurrent_navigation_uses_consistent_cache) ... ok
|
||||
test_content_search_checks_all_conversations (test_wxwork_browser_performance.BrowserPerformanceTest.test_content_search_checks_all_conversations) ... ok
|
||||
test_conversation_and_message_offsets_are_stable_with_timestamp_ties (test_wxwork_browser_performance.BrowserPerformanceTest.test_conversation_and_message_offsets_are_stable_with_timestamp_ties) ... ok
|
||||
test_database_replace_with_preserved_mtime_and_size_invalidates_inode (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replace_with_preserved_mtime_and_size_invalidates_inode) ... ok
|
||||
test_database_replaced_between_index_and_message_read_cannot_leak_conversation (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replaced_between_index_and_message_read_cannot_leak_conversation) ... ok
|
||||
test_database_replaced_between_index_and_preview_read_cannot_leak_conversation (test_wxwork_browser_performance.BrowserPerformanceTest.test_database_replaced_between_index_and_preview_read_cannot_leak_conversation) ... ok
|
||||
test_deletion_invalidates_message_and_conversation_counts (test_wxwork_browser_performance.BrowserPerformanceTest.test_deletion_invalidates_message_and_conversation_counts) ... ok
|
||||
test_multiple_accounts_do_not_rebuild_unselected_indexes (test_wxwork_browser_performance.BrowserPerformanceTest.test_multiple_accounts_do_not_rebuild_unselected_indexes) ... ok
|
||||
test_new_message_invalidates_counts_order_and_cached_page (test_wxwork_browser_performance.BrowserPerformanceTest.test_new_message_invalidates_counts_order_and_cached_page) ... ok
|
||||
test_reader_never_changes_source_database_or_adds_indexes (test_wxwork_browser_performance.BrowserPerformanceTest.test_reader_never_changes_source_database_or_adds_indexes) ... ok
|
||||
test_refresh_explicitly_invalidates_even_unchanged_metadata (test_wxwork_browser_performance.BrowserPerformanceTest.test_refresh_explicitly_invalidates_even_unchanged_metadata) ... ok
|
||||
test_rename_invalidates_names_without_touching_messages (test_wxwork_browser_performance.BrowserPerformanceTest.test_rename_invalidates_names_without_touching_messages) ... ok
|
||||
test_search_finds_conversations_older_than_the_newest_thousand (test_wxwork_browser_performance.BrowserPerformanceTest.test_search_finds_conversations_older_than_the_newest_thousand) ... ok
|
||||
test_search_offset_is_applied_after_filtering (test_wxwork_browser_performance.BrowserPerformanceTest.test_search_offset_is_applied_after_filtering) ... ok
|
||||
test_snapshots_do_not_expose_mutable_cache_objects (test_wxwork_browser_performance.BrowserPerformanceTest.test_snapshots_do_not_expose_mutable_cache_objects) ... ok
|
||||
test_system_conversations_are_excluded_but_total_message_count_is_exact (test_wxwork_browser_performance.BrowserPerformanceTest.test_system_conversations_are_excluded_but_total_message_count_is_exact) ... ok
|
||||
test_wal_only_commit_invalidates_without_main_db_change (test_wxwork_browser_performance.BrowserPerformanceTest.test_wal_only_commit_invalidates_without_main_db_change) ... ok
|
||||
test_warm_conversation_navigation_does_not_repeat_full_aggregates (test_wxwork_browser_performance.BrowserPerformanceTest.test_warm_conversation_navigation_does_not_repeat_full_aggregates) ... ok
|
||||
test_auto_failure_exposes_manual_fallback_and_refresh_retries (test_wxwork_local_setup.LocalDatabaseSetupTest.test_auto_failure_exposes_manual_fallback_and_refresh_retries) ... ok
|
||||
test_corrupt_fresh_cache_is_rebuilt_without_scanning (test_wxwork_local_setup.LocalDatabaseSetupTest.test_corrupt_fresh_cache_is_rebuilt_without_scanning) ... ok
|
||||
test_database_notice_keeps_specific_failure (test_wxwork_local_setup.LocalDatabaseSetupTest.test_database_notice_keeps_specific_failure) ... ok
|
||||
test_directory_choice_preserves_other_settings (test_wxwork_local_setup.LocalDatabaseSetupTest.test_directory_choice_preserves_other_settings) ... ok
|
||||
test_existing_key_and_plain_database_do_not_scan_processes (test_wxwork_local_setup.LocalDatabaseSetupTest.test_existing_key_and_plain_database_do_not_scan_processes) ... ok
|
||||
test_first_install_auto_discovers_and_decrypts_without_manual_input (test_wxwork_local_setup.LocalDatabaseSetupTest.test_first_install_auto_discovers_and_decrypts_without_manual_input) ... ok
|
||||
test_frozen_key_worker_uses_executable_without_python_script (test_wxwork_local_setup.LocalDatabaseSetupTest.test_frozen_key_worker_uses_executable_without_python_script) ... ok
|
||||
test_import_then_refresh_reads_encrypted_message (test_wxwork_local_setup.LocalDatabaseSetupTest.test_import_then_refresh_reads_encrypted_message) ... ok
|
||||
test_invalid_keys_produce_actionable_error_without_secret (test_wxwork_local_setup.LocalDatabaseSetupTest.test_invalid_keys_produce_actionable_error_without_secret) ... ok
|
||||
test_key_worker_only_persists_verified_keys (test_wxwork_local_setup.LocalDatabaseSetupTest.test_key_worker_only_persists_verified_keys) ... ok
|
||||
test_key_worker_timeout_and_no_process_are_actionable (test_wxwork_local_setup.LocalDatabaseSetupTest.test_key_worker_timeout_and_no_process_are_actionable) ... ok
|
||||
test_missing_directory_falls_back_without_scanning_processes (test_wxwork_local_setup.LocalDatabaseSetupTest.test_missing_directory_falls_back_without_scanning_processes) ... ok
|
||||
test_missing_key_is_not_reported_as_missing_database (test_wxwork_local_setup.LocalDatabaseSetupTest.test_missing_key_is_not_reported_as_missing_database) ... ok
|
||||
test_onedrive_directory_is_found_without_saved_config (test_wxwork_local_setup.LocalDatabaseSetupTest.test_onedrive_directory_is_found_without_saved_config) ... ok
|
||||
test_partial_accounts_trigger_auto_acquisition_and_manual_fallback (test_wxwork_local_setup.LocalDatabaseSetupTest.test_partial_accounts_trigger_auto_acquisition_and_manual_fallback) ... ok
|
||||
test_registry_documents_expands_environment_variables (test_wxwork_local_setup.LocalDatabaseSetupTest.test_registry_documents_expands_environment_variables) ... ok
|
||||
test_saved_custom_path_is_used_after_install (test_wxwork_local_setup.LocalDatabaseSetupTest.test_saved_custom_path_is_used_after_install) ... ok
|
||||
test_scanner_success_without_usable_key_is_still_a_failure (test_wxwork_local_setup.LocalDatabaseSetupTest.test_scanner_success_without_usable_key_is_still_a_failure) ... ok
|
||||
test_stale_or_malformed_key_automatically_recovers (test_wxwork_local_setup.LocalDatabaseSetupTest.test_stale_or_malformed_key_automatically_recovers) ... ok
|
||||
test_wrong_key_does_not_overwrite_saved_key (test_wxwork_local_setup.LocalDatabaseSetupTest.test_wrong_key_does_not_overwrite_saved_key) ... ok
|
||||
test_a_blank_name_leaves_the_current_one_alone (test_qt_console_bridge.ConsoleBridgeTest.test_a_blank_name_leaves_the_current_one_alone)
|
||||
空名字是"没填",不是"改成空"——改成空会让提示词里出现一个没有名字的客服。 ... ok
|
||||
test_a_failed_connection_says_why_in_the_log (test_qt_console_bridge.ConsoleBridgeTest.test_a_failed_connection_says_why_in_the_log)
|
||||
失败必须留下原因。只说"连接失败"的话,人不知道是地址错了还是后台没起。 ... ok
|
||||
test_an_over_long_agent_name_is_truncated (test_qt_console_bridge.ConsoleBridgeTest.test_an_over_long_agent_name_is_truncated)
|
||||
昵称会拼进系统提示词,不能让它无限长。 ... ok
|
||||
test_approve_task_reaches_the_host_with_the_exact_key (test_qt_console_bridge.ConsoleBridgeTest.test_approve_task_reaches_the_host_with_the_exact_key)
|
||||
「通过并发送」必须真的连到后端。 ... ok
|
||||
test_approving_a_task_that_left_the_queue_sends_nothing (test_qt_console_bridge.ConsoleBridgeTest.test_approving_a_task_that_left_the_queue_sends_nothing)
|
||||
任务已经不在队列里就别再放行——否则可能把草稿发到别的会话去。 ... ok
|
||||
test_archive_date_button_uses_real_business_filter (test_qt_console_bridge.ConsoleBridgeTest.test_archive_date_button_uses_real_business_filter) ... ok
|
||||
test_archive_selection_only_commits_an_existing_visible_key (test_qt_console_bridge.ConsoleBridgeTest.test_archive_selection_only_commits_an_existing_visible_key) ... ok
|
||||
test_auto_send_header_selects_auto_mode_before_starting (test_qt_console_bridge.ConsoleBridgeTest.test_auto_send_header_selects_auto_mode_before_starting) ... ok
|
||||
test_canvas_uses_available_logical_space_without_design_minimum (test_qt_console_bridge.ConsoleBridgeTest.test_canvas_uses_available_logical_space_without_design_minimum) ... ok
|
||||
test_connect_backend_forwards_the_url_to_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_connect_backend_forwards_the_url_to_the_host)
|
||||
控制台上填的后台地址要真的到得了后端。 ... ok
|
||||
test_console_html_and_javascript_assets_are_packaged_together (test_qt_console_bridge.ConsoleBridgeTest.test_console_html_and_javascript_assets_are_packaged_together) ... ok
|
||||
test_console_push_timer_coalesces_against_earliest_deadline (test_qt_console_bridge.ConsoleBridgeTest.test_console_push_timer_coalesces_against_earliest_deadline) ... ok
|
||||
test_editable_fields_look_editable (test_qt_console_bridge.ConsoleBridgeTest.test_editable_fields_look_editable)
|
||||
能改的地方要看得出来能改。 ... ok
|
||||
test_every_html_navigation_schedules_authoritative_state (test_qt_console_bridge.ConsoleBridgeTest.test_every_html_navigation_schedules_authoritative_state) ... ok
|
||||
test_every_save_button_gives_the_user_feedback (test_qt_console_bridge.ConsoleBridgeTest.test_every_save_button_gives_the_user_feedback)
|
||||
点了保存必须看得见反馈。 ... ok
|
||||
test_handoff_only_reports_tasks_the_backend_accepted (test_qt_console_bridge.ConsoleBridgeTest.test_handoff_only_reports_tasks_the_backend_accepted) ... ok
|
||||
test_long_pages_scroll_without_shrinking_text (test_qt_console_bridge.ConsoleBridgeTest.test_long_pages_scroll_without_shrinking_text) ... ok
|
||||
test_no_layout_container_keeps_a_hard_coded_height (test_qt_console_bridge.ConsoleBridgeTest.test_no_layout_container_keeps_a_hard_coded_height)
|
||||
去掉滚动条之后,"装不下"不再表现为滚动条,而是内容画到别的面板身上。 ... ok
|
||||
test_number_fields_tell_you_the_allowed_range (test_qt_console_bridge.ConsoleBridgeTest.test_number_fields_tell_you_the_allowed_range) ... ok
|
||||
test_page_grids_use_proportional_columns (test_qt_console_bridge.ConsoleBridgeTest.test_page_grids_use_proportional_columns)
|
||||
各栏必须按比例分配宽度。写死像素的话,舞台变宽它们也不会跟着变宽, ... ok
|
||||
test_queue_actions_select_exact_key_before_forwarding (test_qt_console_bridge.ConsoleBridgeTest.test_queue_actions_select_exact_key_before_forwarding) ... ok
|
||||
test_ready_state_delivery_updates_cache_only_after_emit (test_qt_console_bridge.ConsoleBridgeTest.test_ready_state_delivery_updates_cache_only_after_emit) ... ok
|
||||
test_request_state_forces_webchannel_handshake_payload (test_qt_console_bridge.ConsoleBridgeTest.test_request_state_forces_webchannel_handshake_payload) ... ok
|
||||
test_responsive_styles_are_bundled_after_reference_styles (test_qt_console_bridge.ConsoleBridgeTest.test_responsive_styles_are_bundled_after_reference_styles) ... ok
|
||||
test_same_view_state_push_preserves_sidebar_and_main_dom_identity (test_qt_console_bridge.ConsoleBridgeTest.test_same_view_state_push_preserves_sidebar_and_main_dom_identity) ... ok
|
||||
test_save_ai_only_applies_the_agent_name (test_qt_console_bridge.ConsoleBridgeTest.test_save_ai_only_applies_the_agent_name)
|
||||
AI 设置页现在只有客服昵称是真正的本机设置。 ... ok
|
||||
test_set_view_waits_for_loaded_document_and_replays_once (test_qt_console_bridge.ConsoleBridgeTest.test_set_view_waits_for_loaded_document_and_replays_once) ... ok
|
||||
test_sidebar_orb_is_wired_to_the_listen_toggle (test_qt_console_bridge.ConsoleBridgeTest.test_sidebar_orb_is_wired_to_the_listen_toggle)
|
||||
侧栏那颗球是用户最常点的开关,HTML 上必须真的绑着动作。 ... ok
|
||||
test_stale_queue_key_never_mutates_previous_selection (test_qt_console_bridge.ConsoleBridgeTest.test_stale_queue_key_never_mutates_previous_selection) ... ok
|
||||
test_state_is_not_cached_before_webchannel_handshake (test_qt_console_bridge.ConsoleBridgeTest.test_state_is_not_cached_before_webchannel_handshake) ... ok
|
||||
test_the_console_script_handles_that_action (test_qt_console_bridge.ConsoleBridgeTest.test_the_console_script_handles_that_action) ... ok
|
||||
test_the_feedback_helper_covers_pending_result_and_failure (test_qt_console_bridge.ConsoleBridgeTest.test_the_feedback_helper_covers_pending_result_and_failure)
|
||||
反馈要三段齐全:立刻响应、真实结果、失败也要说清。 ... ok
|
||||
test_the_save_slots_report_their_result_back (test_qt_console_bridge.ConsoleBridgeTest.test_the_save_slots_report_their_result_back)
|
||||
Qt 侧的保存槽必须把结果回传,否则网页那边永远只能瞎猜。 ... ok
|
||||
test_the_scale_never_depends_on_page_height_or_device_pixel_ratio (test_qt_console_bridge.ConsoleBridgeTest.test_the_scale_never_depends_on_page_height_or_device_pixel_ratio) ... ok
|
||||
test_the_side_rail_height_does_not_follow_page_content (test_qt_console_bridge.ConsoleBridgeTest.test_the_side_rail_height_does_not_follow_page_content)
|
||||
侧栏在每一页必须一样高。 ... ok
|
||||
test_toggle_listen_starts_and_stops_the_host (test_qt_console_bridge.ConsoleBridgeTest.test_toggle_listen_starts_and_stops_the_host) ... ok
|
||||
test_async_protocol_check_retains_explicit_approval_request (test_desktop_review_visibility.DesktopReviewTest.test_async_protocol_check_retains_explicit_approval_request) ... ok
|
||||
test_explicit_approval_reaches_thread_with_exact_key_and_refreshes (test_desktop_review_visibility.DesktopReviewTest.test_explicit_approval_reaches_thread_with_exact_key_and_refreshes) ... ok
|
||||
test_human_filter_includes_unknown_receipt_and_no_empty_send (test_desktop_review_visibility.DesktopReviewTest.test_human_filter_includes_unknown_receipt_and_no_empty_send) ... ok
|
||||
test_legacy_receipt_states_are_visible_but_not_sendable (test_desktop_review_visibility.DesktopReviewTest.test_legacy_receipt_states_are_visible_but_not_sendable) ... ok
|
||||
test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser (test_desktop_review_visibility.DesktopReviewTest.test_real_queue_snapshot_renders_review_and_handoff_in_embedded_browser) ... ok
|
||||
test_review_counts_remain_visible_under_an_unrelated_filter (test_desktop_review_visibility.DesktopReviewTest.test_review_counts_remain_visible_under_an_unrelated_filter) ... ok
|
||||
test_review_filter_surfaces_protocol_draft_and_reason (test_desktop_review_visibility.DesktopReviewTest.test_review_filter_surfaces_protocol_draft_and_reason) ... ok
|
||||
test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff (test_desktop_review_visibility.DesktopReviewTest.test_stale_snapshot_requires_explicit_confirmation_before_backend_handoff) ... ok
|
||||
test_stopped_handoff_uses_offline_resolution_and_preserves_seen (test_desktop_review_visibility.DesktopReviewTest.test_stopped_handoff_uses_offline_resolution_and_preserves_seen) ... ok
|
||||
test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve (test_desktop_review_visibility.DesktopReviewTest.test_unknown_receipt_handoff_requires_confirmation_and_never_calls_approve) ... ok
|
||||
test_generation_failure_is_retryable_but_not_sendable (test_desktop_review_visibility.ReviewStateTest.test_generation_failure_is_retryable_but_not_sendable) ... ok
|
||||
test_media_without_draft_cannot_be_approved (test_desktop_review_visibility.ReviewStateTest.test_media_without_draft_cannot_be_approved) ... ok
|
||||
test_protocol_and_visual_reviews_have_the_same_action_contract (test_desktop_review_visibility.ReviewStateTest.test_protocol_and_visual_reviews_have_the_same_action_contract) ... ok
|
||||
test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag (test_desktop_review_visibility.ReviewStateTest.test_uncertain_delivery_cannot_be_approved_or_retried_even_with_stale_review_flag) ... ok
|
||||
test_actual_send_mode_never_uses_probe_hash_cache (test_protocol_probe_performance.BuildHashReuseTests.test_actual_send_mode_never_uses_probe_hash_cache) ... ok
|
||||
test_changed_binary_is_not_reused_with_same_process (test_protocol_probe_performance.BuildHashReuseTests.test_changed_binary_is_not_reused_with_same_process) ... ok
|
||||
test_file_change_during_hash_fails_closed (test_protocol_probe_performance.BuildHashReuseTests.test_file_change_during_hash_fails_closed) ... ok
|
||||
test_native_client_still_validates_live_identity_each_time (test_protocol_probe_performance.BuildHashReuseTests.test_native_client_still_validates_live_identity_each_time) ... ok
|
||||
test_new_pid_and_reused_pid_with_new_creation_time_rehash (test_protocol_probe_performance.BuildHashReuseTests.test_new_pid_and_reused_pid_with_new_creation_time_rehash) ... ok
|
||||
test_one_probe_reads_same_process_build_once_but_next_probe_rechecks (test_protocol_probe_performance.BuildHashReuseTests.test_one_probe_reads_same_process_build_once_but_next_probe_rechecks) ... ok
|
||||
test_unavailable_process_start_time_does_not_enable_cache (test_protocol_probe_performance.BuildHashReuseTests.test_unavailable_process_start_time_does_not_enable_cache) ... ok
|
||||
test_change_after_database_check_is_never_hidden_by_static_reuse (test_protocol_probe_performance.ProbeFreshnessTests.test_change_after_database_check_is_never_hidden_by_static_reuse) ... ok
|
||||
test_repeated_probes_revalidate_account_and_database (test_protocol_probe_performance.ProbeFreshnessTests.test_repeated_probes_revalidate_account_and_database) ... ok
|
||||
test_actual_reply_startup_loads_current_account_metadata (test_protocol_probe_performance.ScopedDatabaseTests.test_actual_reply_startup_loads_current_account_metadata) ... ok
|
||||
test_default_database_keeps_all_account_and_metadata_behavior (test_protocol_probe_performance.ScopedDatabaseTests.test_default_database_keeps_all_account_and_metadata_behavior) ... ok
|
||||
test_other_account_cache_cannot_prove_current_account_ready (test_protocol_probe_performance.ScopedDatabaseTests.test_other_account_cache_cannot_prove_current_account_ready) ... ok
|
||||
test_probe_prepares_only_current_message_database_without_metadata (test_protocol_probe_performance.ScopedDatabaseTests.test_probe_prepares_only_current_message_database_without_metadata) ... ok
|
||||
test_schema_check_is_preserved_in_lightweight_probe (test_protocol_probe_performance.ScopedDatabaseTests.test_schema_check_is_preserved_in_lightweight_probe) ... ok
|
||||
test_unsafe_account_or_database_name_is_rejected (test_protocol_probe_performance.ScopedDatabaseTests.test_unsafe_account_or_database_name_is_rejected) ... ok
|
||||
test_only_success_resumes_pending_start (test_protocol_cross_machine.GuiTests.test_only_success_resumes_pending_start) ... ok
|
||||
test_saved_protocol_gets_auto_probe_and_recent_report_is_reused (test_protocol_cross_machine.GuiTests.test_saved_protocol_gets_auto_probe_and_recent_report_is_reused) ... ok
|
||||
test_start_waits_without_constructing_sender (test_protocol_cross_machine.GuiTests.test_start_waits_without_constructing_sender) ... ok
|
||||
test_stop_cancels_delayed_start (test_protocol_cross_machine.GuiTests.test_stop_cancels_delayed_start) ... ok
|
||||
test_account_change_and_exit_during_initialization_are_blocked (test_protocol_cross_machine.ProbeTests.test_account_change_and_exit_during_initialization_are_blocked) ... ok
|
||||
test_custom_install_path_needs_no_sdk (test_protocol_cross_machine.ProbeTests.test_custom_install_path_needs_no_sdk) ... ok
|
||||
test_database_failure_cannot_report_ready (test_protocol_cross_machine.ProbeTests.test_database_failure_cannot_report_ready) ... ok
|
||||
test_missing_database_flag_never_enables_sender (test_protocol_cross_machine.ProbeTests.test_missing_database_flag_never_enables_sender) ... ok
|
||||
test_not_running_still_reports_custom_install (test_protocol_cross_machine.ProbeTests.test_not_running_still_reports_custom_install) ... ok
|
||||
test_real_failure_is_visible_instead_of_sdk_message (test_protocol_cross_machine.ProbeTests.test_real_failure_is_visible_instead_of_sdk_message) ... ok
|
||||
test_unsupported_version_or_architecture_does_not_access_sender (test_protocol_cross_machine.ProbeTests.test_unsupported_version_or_architecture_does_not_access_sender) ... ok
|
||||
test_current_account_ignores_stale_saved_directory (test_protocol_cross_machine.StorageTests.test_current_account_ignores_stale_saved_directory) ... ok
|
||||
test_encrypted_first_install_initializes_only_current_machine_keys (test_protocol_cross_machine.StorageTests.test_encrypted_first_install_initializes_only_current_machine_keys) ... ok
|
||||
test_fresh_account_with_plain_db_needs_no_key_worker (test_protocol_cross_machine.StorageTests.test_fresh_account_with_plain_db_needs_no_key_worker) ... ok
|
||||
test_historical_account_and_empty_sqlite_cannot_prove_readiness (test_protocol_cross_machine.StorageTests.test_historical_account_and_empty_sqlite_cannot_prove_readiness) ... ok
|
||||
test_passive_check_does_not_acquire_keys (test_protocol_cross_machine.StorageTests.test_passive_check_does_not_acquire_keys) ... ok
|
||||
test_registered_data_directory_takes_effect (test_protocol_cross_machine.StorageTests.test_registered_data_directory_takes_effect) ... ok
|
||||
test_registry_uses_both_views_and_ignores_numeric_data_flag (test_protocol_cross_machine.StorageTests.test_registry_uses_both_views_and_ignores_numeric_data_flag) ... ok
|
||||
test_root_account_data_and_file_paths_with_unicode_spaces (test_protocol_cross_machine.StorageTests.test_root_account_data_and_file_paths_with_unicode_spaces) ... ok
|
||||
test_exact_hash_required_and_versions_do_not_share_layouts (test_native_builds.BuildTests.test_exact_hash_required_and_versions_do_not_share_layouts) ... ok
|
||||
test_new_version_detection_reports_validation_state (test_native_builds.BuildTests.test_new_version_detection_reports_validation_state) ... ok
|
||||
test_unverified_build_cannot_be_enabled_by_report_flags (test_native_builds.BuildTests.test_unverified_build_cannot_be_enabled_by_report_flags) ... ok
|
||||
test_account_change_while_opening_write_handle_cancels (test_native_evidence.ClientGateTests.test_account_change_while_opening_write_handle_cancels) ... ok
|
||||
test_confirmed_evidence_allows_write_after_readonly_identity_check (test_native_evidence.ClientGateTests.test_confirmed_evidence_allows_write_after_readonly_identity_check) ... ok
|
||||
test_pending_build_cannot_even_acquire_write_handle_without_evidence (test_native_evidence.ClientGateTests.test_pending_build_cannot_even_acquire_write_handle_without_evidence) ... ok
|
||||
test_confirmed_evidence_is_account_build_and_revision_bound (test_native_evidence.EvidenceTests.test_confirmed_evidence_is_account_build_and_revision_bound) ... ok
|
||||
test_failed_incomplete_or_wrong_receipt_cannot_enable (test_native_evidence.EvidenceTests.test_failed_incomplete_or_wrong_receipt_cannot_enable) ... ok
|
||||
test_no_evidence_does_not_create_database_or_enable_sending (test_native_evidence.EvidenceTests.test_no_evidence_does_not_create_database_or_enable_sending) ... ok
|
||||
test_only_fixed_manual_test_with_matching_fingerprint_counts (test_native_evidence.EvidenceTests.test_only_fixed_manual_test_with_matching_fingerprint_counts) ... ok
|
||||
test_probe_moves_to_ready_only_after_confirmed_journal (test_native_evidence.EvidenceTests.test_probe_moves_to_ready_only_after_confirmed_journal) ... ok
|
||||
test_report_flags_and_exported_json_do_not_enable_without_journal (test_native_evidence.EvidenceTests.test_report_flags_and_exported_json_do_not_enable_without_journal) ... ok
|
||||
test_cancel_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_cancel_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_crash_in_sending_becomes_uncertain (test_native_protocol_pipeline.EngineTests.test_crash_in_sending_becomes_uncertain) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_database_read_failure_never_announces_healthy_listener (test_native_protocol_pipeline.EngineTests.test_database_read_failure_never_announces_healthy_listener) ... ok
|
||||
test_duplicate_event_only_sent_once (test_native_protocol_pipeline.EngineTests.test_duplicate_event_only_sent_once) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_manual_reply_during_generation_cancels_send (test_native_protocol_pipeline.EngineTests.test_manual_reply_during_generation_cancels_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_media_is_left_for_manual_handling (test_native_protocol_pipeline.EngineTests.test_media_is_left_for_manual_handling) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 当前消息需要人工处理;当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理
|
||||
ok
|
||||
test_memory_setting_preserves_only_unanswered_batch_when_disabled (test_native_protocol_pipeline.EngineTests.test_memory_setting_preserves_only_unanswered_batch_when_disabled) ... ok
|
||||
test_model_control_tokens_are_not_sent (test_native_protocol_pipeline.EngineTests.test_model_control_tokens_are_not_sent) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;模型未返回有效文本
|
||||
ok
|
||||
test_model_error_can_retry_before_send (test_native_protocol_pipeline.EngineTests.test_model_error_can_retry_before_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 模型生成失败,可重试;offline
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_new_incoming_during_generation_discards_old_answer (test_native_protocol_pipeline.EngineTests.test_new_incoming_during_generation_discards_old_answer) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_new_message_invalidates_approved_draft (test_native_protocol_pipeline.EngineTests.test_new_message_invalidates_approved_draft) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
ok
|
||||
test_only_current_account_processed (test_native_protocol_pipeline.EngineTests.test_only_current_account_processed) ... ok
|
||||
test_pending_batch_window_is_honored (test_native_protocol_pipeline.EngineTests.test_pending_batch_window_is_honored) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_pending_review_and_errors_do_not_show_idle (test_native_protocol_pipeline.EngineTests.test_pending_review_and_errors_do_not_show_idle) ... ok
|
||||
test_progress_callback_failure_does_not_repeat_or_block_send (test_native_protocol_pipeline.EngineTests.test_progress_callback_failure_does_not_repeat_or_block_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_progress_follows_receive_generate_send_then_waiting (test_native_protocol_pipeline.EngineTests.test_progress_follows_receive_generate_send_then_waiting) ... ok
|
||||
test_ready_flag_alone_cannot_enable_transport (test_native_protocol_pipeline.EngineTests.test_ready_flag_alone_cannot_enable_transport) ... ok
|
||||
test_restart_after_confirmed_journal_clears_pending_without_send (test_native_protocol_pipeline.EngineTests.test_restart_after_confirmed_journal_clears_pending_without_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
ok
|
||||
test_review_requires_approval (test_native_protocol_pipeline.EngineTests.test_review_requires_approval) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 人工审核
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_runtime_uses_protocol_engine_without_visual_construction (test_native_protocol_pipeline.EngineTests.test_runtime_uses_protocol_engine_without_visual_construction) ... ok
|
||||
test_same_name_conversations_use_distinct_ids (test_native_protocol_pipeline.EngineTests.test_same_name_conversations_use_distinct_ids) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_stop_during_generation_does_not_send (test_native_protocol_pipeline.EngineTests.test_stop_during_generation_does_not_send) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
ok
|
||||
test_text_pipeline_with_native_receipt_and_no_feedback (test_native_protocol_pipeline.EngineTests.test_text_pipeline_with_native_receipt_and_no_feedback) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议发送成功] 同名客户 · 服务器消息 999
|
||||
ok
|
||||
test_uncertain_send_is_persisted_and_not_retried (test_native_protocol_pipeline.EngineTests.test_uncertain_send_is_persisted_and_not_retried) ... [协议收信] 同名客户 · 已加入回复队列
|
||||
[协议处理] 同名客户 · 根据当前会话生成回复
|
||||
[协议处理] 同名客户 · 原账号单聊发送
|
||||
[协议处理] 同名客户 · 发送结果待人工核对,已暂停监听;timeout
|
||||
ok
|
||||
test_unknown_receipt_is_paused_without_healthy_poll_log (test_native_protocol_pipeline.EngineTests.test_unknown_receipt_is_paused_without_healthy_poll_log) ... ok
|
||||
test_waiting_progress_and_periodic_read_confirmation_are_throttled (test_native_protocol_pipeline.EngineTests.test_waiting_progress_and_periodic_read_confirmation_are_throttled) ... ok
|
||||
test_cancelled_before_send_does_not_consume_id (test_native_protocol_pipeline.JournalTests.test_cancelled_before_send_does_not_consume_id) ... ok
|
||||
test_changed_payload_same_event_is_blocked (test_native_protocol_pipeline.JournalTests.test_changed_payload_same_event_is_blocked) ... ok
|
||||
test_failure_does_not_automatically_retry (test_native_protocol_pipeline.JournalTests.test_failure_does_not_automatically_retry) ... ok
|
||||
test_invalid_text_rejected (test_native_protocol_pipeline.JournalTests.test_invalid_text_rejected) ... ok
|
||||
test_missing_conversation_blocks_send (test_native_protocol_pipeline.JournalTests.test_missing_conversation_blocks_send) ... ok
|
||||
test_reopen_after_success_never_resends (test_native_protocol_pipeline.JournalTests.test_reopen_after_success_never_resends) ... ok
|
||||
test_success_receipt_and_repeat_returns_saved_result (test_native_protocol_pipeline.JournalTests.test_success_receipt_and_repeat_returns_saved_result) ... ok
|
||||
test_unknown_blocks_retry (test_native_protocol_pipeline.JournalTests.test_unknown_blocks_retry) ... ok
|
||||
test_wrong_account_rejected_before_journaling_or_send (test_native_protocol_pipeline.JournalTests.test_wrong_account_rejected_before_journaling_or_send) ... ok
|
||||
test_bad_or_oversized_history_is_ignored (test_wecom_native_protocol.NativeHistoryTest.test_bad_or_oversized_history_is_ignored) ... ok
|
||||
test_different_business_results_do_not_imply_open_access (test_wecom_native_protocol.NativeHistoryTest.test_different_business_results_do_not_imply_open_access) ... ok
|
||||
test_history_cannot_enable_sender_or_export_unknown_fields (test_wecom_native_protocol.NativeHistoryTest.test_history_cannot_enable_sender_or_export_unknown_fields) ... ok
|
||||
test_version_mismatch_remains_explicit (test_wecom_native_protocol.NativeHistoryTest.test_version_mismatch_remains_explicit) ... ok
|
||||
test_actual_gray_error_nested_inside_http_200 (test_wecom_native_protocol.NativeReplyTest.test_actual_gray_error_nested_inside_http_200) ... ok
|
||||
test_error_text_is_not_exposed (test_wecom_native_protocol.NativeReplyTest.test_error_text_is_not_exposed) ... ok
|
||||
test_incomplete_transport_wrong_id_and_malformed_json_are_rejected (test_wecom_native_protocol.NativeReplyTest.test_incomplete_transport_wrong_id_and_malformed_json_are_rejected) ... ok
|
||||
test_initialize_and_tools_list_are_transport_results_only (test_wecom_native_protocol.NativeReplyTest.test_initialize_and_tools_list_are_transport_results_only) ... ok
|
||||
test_nested_malformed_response_and_depth_are_bounded (test_wecom_native_protocol.NativeReplyTest.test_nested_malformed_response_and_depth_are_bounded) ... ok
|
||||
test_outer_and_tool_errors_are_never_success (test_wecom_native_protocol.NativeReplyTest.test_outer_and_tool_errors_are_never_success) ... ok
|
||||
test_actual_web_page_protocol_state_buttons_and_visual_return (test_protocol_features.ProtocolGuiTest.test_actual_web_page_protocol_state_buttons_and_visual_return) ... ok
|
||||
test_detection_state_keeps_binary_paths_out_of_web_payload (test_protocol_features.ProtocolGuiTest.test_detection_state_keeps_binary_paths_out_of_web_payload) ... ok
|
||||
test_probe_worker_coalesces_clicks_and_delivers_failures (test_protocol_features.ProtocolGuiTest.test_probe_worker_coalesces_clicks_and_delivers_failures) ... ok
|
||||
test_qt_and_classic_keep_protocol_even_when_other_settings_are_corrupt (test_protocol_features.ProtocolGuiTest.test_qt_and_classic_keep_protocol_even_when_other_settings_are_corrupt) ... ok
|
||||
test_qt_persists_transport_and_restores_memory_after_disk_failure (test_protocol_features.ProtocolGuiTest.test_qt_persists_transport_and_restores_memory_after_disk_failure) ... ok
|
||||
test_qt_protocol_start_passes_transport_to_background_thread (test_protocol_features.ProtocolGuiTest.test_qt_protocol_start_passes_transport_to_background_thread) ... ok
|
||||
test_transport_change_is_saved_and_rejected_while_running (test_protocol_features.ProtocolGuiTest.test_transport_change_is_saved_and_rejected_while_running) ... ok
|
||||
test_duplicate_names_and_server_ids_remain_isolated_by_exact_account_conversation (test_protocol_features.ProtocolIdContextTest.test_duplicate_names_and_server_ids_remain_isolated_by_exact_account_conversation) ... ok
|
||||
test_missing_account_unknown_conversation_and_group_never_guess (test_protocol_features.ProtocolIdContextTest.test_missing_account_unknown_conversation_and_group_never_guess) ... ok
|
||||
test_atomic_export_does_not_destroy_existing_report_on_failure (test_protocol_features.ProtocolProbeTest.test_atomic_export_does_not_destroy_existing_report_on_failure) ... ok
|
||||
test_installed_client_and_bundled_sdk_never_imply_send_or_login (test_protocol_features.ProtocolProbeTest.test_installed_client_and_bundled_sdk_never_imply_send_or_login) ... ok
|
||||
test_no_client_and_inaccessible_client (test_protocol_features.ProtocolProbeTest.test_no_client_and_inaccessible_client) ... ok
|
||||
test_pe_architecture_and_corrupt_header (test_protocol_features.ProtocolProbeTest.test_pe_architecture_and_corrupt_header) ... ok
|
||||
test_database_failure_is_propagated_and_request_identity_includes_limit (test_protocol_features.ProtocolRoutingTest.test_database_failure_is_propagated_and_request_identity_includes_limit) ... ok
|
||||
test_invalid_explicit_transport_never_defaults_to_visual (test_protocol_features.ProtocolRoutingTest.test_invalid_explicit_transport_never_defaults_to_visual) ... ok
|
||||
test_protocol_start_never_constructs_visual_sender_even_with_true_flag (test_protocol_features.ProtocolRoutingTest.test_protocol_start_never_constructs_visual_sender_even_with_true_flag) ... ok
|
||||
test_context_failure_returns_none_and_can_recover (test_database_reply_priority.BackgroundDatabaseTests.test_context_failure_returns_none_and_can_recover) ... ok
|
||||
test_polling_during_retry_cooldown_does_not_extend_it (test_database_reply_priority.BackgroundDatabaseTests.test_polling_during_retry_cooldown_does_not_extend_it) ... ok
|
||||
test_slow_key_setup_does_not_block_and_late_poll_result_is_retained (test_database_reply_priority.BackgroundDatabaseTests.test_slow_key_setup_does_not_block_and_late_poll_result_is_retained) ... ok
|
||||
test_active_task_receives_followup_instead_of_only_merging_tag (test_database_reply_priority.DatabaseDetectionTests.test_active_task_receives_followup_instead_of_only_merging_tag) ... [引擎B] 已登记新消息 → 客户甲
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_duplicate_message_and_ambiguous_name_are_not_queued (test_database_reply_priority.DatabaseDetectionTests.test_duplicate_message_and_ambiguous_name_are_not_queued) ... [引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_failed_enqueue_is_retried_without_new_database_row (test_database_reply_priority.DatabaseDetectionTests.test_failed_enqueue_is_retried_without_new_database_row) ... [引擎B] [!] 投递未执行: busy
|
||||
[引擎B] 已登记新消息 → 客户甲
|
||||
ok
|
||||
test_last_outgoing_is_not_queued_and_failure_changes_health (test_database_reply_priority.DatabaseDetectionTests.test_last_outgoing_is_not_queued_and_failure_changes_health) ... [引擎B] DB 直读失败: unreadable,备用检测继续运行
|
||||
ok
|
||||
test_accounts_keep_independent_cursors_and_accept_late_writes (test_database_reply_priority.DatabaseFixture.test_accounts_keep_independent_cursors_and_accept_late_writes) ... ok
|
||||
test_closed_database_reports_failure (test_database_reply_priority.DatabaseFixture.test_closed_database_reports_failure) ... ok
|
||||
test_context_has_sender_direction_and_media_placeholder (test_database_reply_priority.DatabaseFixture.test_context_has_sender_direction_and_media_placeholder) ... ok
|
||||
test_cross_thread_reads_and_wal_only_messages (test_database_reply_priority.DatabaseFixture.test_cross_thread_reads_and_wal_only_messages) ... ok
|
||||
test_duplicate_titles_never_select_another_account (test_database_reply_priority.DatabaseFixture.test_duplicate_titles_never_select_another_account) ... ok
|
||||
test_initial_history_boundary_ms_and_new_account (test_database_reply_priority.DatabaseFixture.test_initial_history_boundary_ms_and_new_account) ... ok
|
||||
test_large_batch_and_same_second_insertion_do_not_skip (test_database_reply_priority.DatabaseFixture.test_large_batch_and_same_second_insertion_do_not_skip) ... ok
|
||||
test_schema_failure_does_not_advance_valid_account_cursor (test_database_reply_priority.DatabaseFixture.test_schema_failure_does_not_advance_valid_account_cursor) ... ok
|
||||
test_service_reconnect_preserves_consumed_database_rows (test_database_reply_priority.DatabaseFixture.test_service_reconnect_preserves_consumed_database_rows) ... ok
|
||||
test_actual_generation_uses_database_text_without_clipboard_or_remote_vision (test_database_reply_priority.PriorityReplyTests.test_actual_generation_uses_database_text_without_clipboard_or_remote_vision) ... [档案] 首次遇到该会话,已暂存(2 行可见历史)
|
||||
[档案] 旧会话档案归属无法唯一证明,已保留但不会自动用于当前会话。
|
||||
[AI] 本次提取的新内容:
|
||||
客户甲 2026/09/14 10:00:00
|
||||
你好
|
||||
[AI] 回复内容: 有什么可以帮您?
|
||||
ok
|
||||
test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts (test_database_reply_priority.PriorityReplyTests.test_ambiguous_or_unverified_database_names_cannot_map_visual_contacts) ... ok
|
||||
test_current_database_context_overrides_stale_pre_copied_text (test_database_reply_priority.PriorityReplyTests.test_current_database_context_overrides_stale_pre_copied_text) ... [档案] 首次遇到该会话,已建档(2 行可见历史)
|
||||
ok
|
||||
test_database_direction_beats_old_visible_outgoing_bubble (test_database_reply_priority.PriorityReplyTests.test_database_direction_beats_old_visible_outgoing_bubble) ... ok
|
||||
test_database_event_merges_into_existing_external_visual_task (test_database_reply_priority.PriorityReplyTests.test_database_event_merges_into_existing_external_visual_task) ... ok
|
||||
test_database_success_never_touches_clipboard_or_geometry (test_database_reply_priority.PriorityReplyTests.test_database_success_never_touches_clipboard_or_geometry) ... ok
|
||||
test_empty_database_uses_copy_fallback (test_database_reply_priority.PriorityReplyTests.test_empty_database_uses_copy_fallback) ... [档案] 首次遇到该会话,已建档(1 行可见历史)
|
||||
ok
|
||||
test_external_label_maps_to_unique_database_task_without_changing_hashes (test_database_reply_priority.PriorityReplyTests.test_external_label_maps_to_unique_database_task_without_changing_hashes) ... ok
|
||||
test_failed_active_task_yields_to_new_customer (test_database_reply_priority.PriorityReplyTests.test_failed_active_task_yields_to_new_customer) ... ok
|
||||
test_followup_invalidates_reply_generated_for_old_message (test_database_reply_priority.PriorityReplyTests.test_followup_invalidates_reply_generated_for_old_message) ... ok
|
||||
test_followup_preserves_inflight_stage_and_wakes_worker (test_database_reply_priority.PriorityReplyTests.test_followup_preserves_inflight_stage_and_wakes_worker) ... ok
|
||||
test_new_message_arriving_before_send_rejects_stale_reply (test_database_reply_priority.PriorityReplyTests.test_new_message_arriving_before_send_rejects_stale_reply) ... ok
|
||||
test_new_task_does_not_bind_foreground_identity (test_database_reply_priority.PriorityReplyTests.test_new_task_does_not_bind_foreground_identity) ... ok
|
||||
test_uncertain_send_is_not_reset_by_followup (test_database_reply_priority.PriorityReplyTests.test_uncertain_send_is_not_reset_by_followup) ... ok
|
||||
test_wrong_title_or_missing_latest_id_does_not_use_database (test_database_reply_priority.PriorityReplyTests.test_wrong_title_or_missing_latest_id_does_not_use_database) ... ok
|
||||
test_bad_rows_do_not_crash_context_or_skip_later_valid_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_bad_rows_do_not_crash_context_or_skip_later_valid_messages) ... ok
|
||||
test_nonfinite_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_nonfinite_timestamps_are_not_messages) ... ok
|
||||
test_out_of_range_timestamps_are_not_messages (test_database_timestamp_audit.DatabaseTimestampAudit.test_out_of_range_timestamps_are_not_messages) ... ok
|
||||
test_seconds_and_milliseconds_preserve_chronology (test_database_timestamp_audit.DatabaseTimestampAudit.test_seconds_and_milliseconds_preserve_chronology) ... ok
|
||||
test_cloud_failure_is_recorded_for_retry (test_archive_upload_flow.ArchiveUploadFlowTest.test_cloud_failure_is_recorded_for_retry) ... ok
|
||||
test_desktop_keys_allow_upload_without_legacy_key_file (test_archive_upload_flow.ArchiveUploadFlowTest.test_desktop_keys_allow_upload_without_legacy_key_file) ... ok
|
||||
test_disabled_cloud_policy_never_launches_upload (test_archive_upload_flow.ArchiveUploadFlowTest.test_disabled_cloud_policy_never_launches_upload) ... ok
|
||||
test_disabled_policy_overrides_old_success (test_archive_upload_flow.ArchiveUploadFlowTest.test_disabled_policy_overrides_old_success) ... ok
|
||||
test_encrypted_database_to_cloud_client_and_checkpoint (test_archive_upload_flow.ArchiveUploadFlowTest.test_encrypted_database_to_cloud_client_and_checkpoint) ... [引擎B] 已登记新消息 → test
|
||||
ok
|
||||
test_installed_build_ignores_stale_override (test_archive_upload_flow.ArchiveUploadFlowTest.test_installed_build_ignores_stale_override) ... ok
|
||||
test_key_acquisition_failure_is_recorded_without_upload (test_archive_upload_flow.ArchiveUploadFlowTest.test_key_acquisition_failure_is_recorded_without_upload) ... ok
|
||||
test_missing_keys_are_acquired_once_then_decryption_retried (test_archive_upload_flow.ArchiveUploadFlowTest.test_missing_keys_are_acquired_once_then_decryption_retried) ... ok
|
||||
test_source_local_legacy_port_fallback (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_local_legacy_port_fallback) ... ok
|
||||
test_source_retains_explicit_development_endpoint (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_retains_explicit_development_endpoint) ... ok
|
||||
test_source_uses_configured_cloud_without_local_fallback (test_archive_upload_flow.ArchiveUploadFlowTest.test_source_uses_configured_cloud_without_local_fallback) ... ok
|
||||
test_startup_uploads_immediately_then_respects_interval (test_archive_upload_flow.ArchiveUploadFlowTest.test_startup_uploads_immediately_then_respects_interval) ... ok
|
||||
test_status_handles_missing_and_malformed_file (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_handles_missing_and_malformed_file) ... ok
|
||||
test_status_removes_signed_storage_url_query (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_removes_signed_storage_url_query) ... ok
|
||||
test_status_shows_success_and_running_without_raw_fields (test_archive_upload_flow.ArchiveUploadFlowTest.test_status_shows_success_and_running_without_raw_fields) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 263 tests in 13.052s
|
||||
|
||||
OK
|
||||
@@ -1,169 +0,0 @@
|
||||
test_admin_can_query_all_usage_and_filter_model (test_model_usage_ledger.ModelUsageApiTests.test_admin_can_query_all_usage_and_filter_model) ... ok
|
||||
test_invalid_query_ranges_are_rejected (test_model_usage_ledger.ModelUsageApiTests.test_invalid_query_ranges_are_rejected) ... ok
|
||||
test_scoped_admin_all_means_only_authorized_accounts (test_model_usage_ledger.ModelUsageApiTests.test_scoped_admin_all_means_only_authorized_accounts) ... ok
|
||||
test_stats_and_log_require_login_and_stats_read (test_model_usage_ledger.ModelUsageApiTests.test_stats_and_log_require_login_and_stats_read) ... ok
|
||||
test_all_purposes_default_and_precise_provider_model_filters (test_model_usage_ledger.ModelUsageLedgerTests.test_all_purposes_default_and_precise_provider_model_filters) ... ok
|
||||
test_answer_candidates_judge_retry_and_error_are_all_charged (test_model_usage_ledger.ModelUsageLedgerTests.test_answer_candidates_judge_retry_and_error_are_all_charged) ... ok
|
||||
test_batch_retry_only_inserts_new_events (test_model_usage_ledger.ModelUsageLedgerTests.test_batch_retry_only_inserts_new_events) ... ok
|
||||
test_concurrent_duplicate_writers_insert_once (test_model_usage_ledger.ModelUsageLedgerTests.test_concurrent_duplicate_writers_insert_once) ... ok
|
||||
test_default_specific_and_multi_account_scopes_are_isolated (test_model_usage_ledger.ModelUsageLedgerTests.test_default_specific_and_multi_account_scopes_are_isolated) ... ok
|
||||
test_empty_statistics_are_zero_with_all_requested_calendar_days (test_model_usage_ledger.ModelUsageLedgerTests.test_empty_statistics_are_zero_with_all_requested_calendar_days) ... ok
|
||||
test_event_id_is_idempotent_and_first_record_is_immutable (test_model_usage_ledger.ModelUsageLedgerTests.test_event_id_is_idempotent_and_first_record_is_immutable) ... ok
|
||||
test_invalid_metadata_and_noninteger_tokens_are_rejected (test_model_usage_ledger.ModelUsageLedgerTests.test_invalid_metadata_and_noninteger_tokens_are_rejected) ... ok
|
||||
test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted) ... ok
|
||||
test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches) ... ok
|
||||
test_migration_preserves_old_rows_and_is_repeatable (test_model_usage_ledger.ModelUsageLedgerTests.test_migration_preserves_old_rows_and_is_repeatable) ... ok
|
||||
test_missing_usage_stays_null_and_is_not_counted_as_known (test_model_usage_ledger.ModelUsageLedgerTests.test_missing_usage_stays_null_and_is_not_counted_as_known) ... ok
|
||||
test_only_allowlisted_metadata_is_persisted (test_model_usage_ledger.ModelUsageLedgerTests.test_only_allowlisted_metadata_is_persisted) ... ok
|
||||
test_pagination_is_stable_and_database_limit_is_capped (test_model_usage_ledger.ModelUsageLedgerTests.test_pagination_is_stable_and_database_limit_is_capped) ... ok
|
||||
test_partial_usage_is_never_filled_or_total_estimated (test_model_usage_ledger.ModelUsageLedgerTests.test_partial_usage_is_never_filled_or_total_estimated) ... ok
|
||||
test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets (test_model_usage_ledger.ModelUsageLedgerTests.test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets) ... ok
|
||||
test_validation_or_storage_failure_raises_and_batch_does_not_partially_write (test_model_usage_ledger.ModelUsageLedgerTests.test_validation_or_storage_failure_raises_and_batch_does_not_partially_write) ... ok
|
||||
test_zero_reported_tokens_are_known (test_model_usage_ledger.ModelUsageLedgerTests.test_zero_reported_tokens_are_known) ... ok
|
||||
test_a_rule_without_keywords_is_rejected (test_admin_api.AgentApiTest.test_a_rule_without_keywords_is_rejected) ... ok
|
||||
test_agents_are_pushed_to_the_desktop_with_the_config (test_admin_api.AgentApiTest.test_agents_are_pushed_to_the_desktop_with_the_config)
|
||||
客户端只认 config 里的键——不放进 config 就等于新配置静默不生效。 ... ok
|
||||
test_an_agent_on_duty_cannot_be_deleted (test_admin_api.AgentApiTest.test_an_agent_on_duty_cannot_be_deleted)
|
||||
删掉在岗的角色,那份方案就指向一个不存在的人。 ... ok
|
||||
test_default_agents_are_seeded_and_on_duty (test_admin_api.AgentApiTest.test_default_agents_are_seeded_and_on_duty) ... ok
|
||||
test_saving_and_switching_an_agent (test_admin_api.AgentApiTest.test_saving_and_switching_an_agent) ... ok
|
||||
test_the_plan_cannot_reference_an_unknown_agent (test_admin_api.AgentApiTest.test_the_plan_cannot_reference_an_unknown_agent) ... ok
|
||||
test_the_plan_is_versioned_not_overwritten (test_admin_api.AgentApiTest.test_the_plan_is_versioned_not_overwritten)
|
||||
和角色编排一样按版本追加:回滚就是指回旧版本。 ... ok
|
||||
test_the_seeded_rule_forbids_the_encoding_excuse (test_admin_api.AgentApiTest.test_the_seeded_rule_forbids_the_encoding_excuse)
|
||||
线上翻过的那条车:客户发血糖值「13」,模型回"这串像系统编码"。 ... ok
|
||||
test_viewer_can_read_agents_but_not_change_them (test_admin_api.AgentApiTest.test_viewer_can_read_agents_but_not_change_them) ... ok
|
||||
test_a_garbage_token_is_rejected (test_admin_api.AuthTest.test_a_garbage_token_is_rejected) ... ok
|
||||
test_a_second_device_revokes_the_first_desktop_session (test_admin_api.AuthTest.test_a_second_device_revokes_the_first_desktop_session) ... ok
|
||||
test_a_weak_new_password_is_refused (test_admin_api.AuthTest.test_a_weak_new_password_is_refused) ... ok
|
||||
test_a_wrong_password_is_rejected (test_admin_api.AuthTest.test_a_wrong_password_is_rejected) ... ok
|
||||
test_account_backup_policy_overrides_the_global_desktop_config (test_admin_api.AuthTest.test_account_backup_policy_overrides_the_global_desktop_config) ... ok
|
||||
test_admin_force_logout_revokes_session_and_device (test_admin_api.AuthTest.test_admin_force_logout_revokes_session_and_device) ... ok
|
||||
test_desktop_account_appears_in_the_management_api (test_admin_api.AuthTest.test_desktop_account_appears_in_the_management_api) ... ok
|
||||
test_desktop_auth_config_is_public_and_has_the_effective_login_domain (test_admin_api.AuthTest.test_desktop_auth_config_is_public_and_has_the_effective_login_domain) ... ok
|
||||
test_desktop_session_is_long_lived_and_slides_on_heartbeat (test_admin_api.AuthTest.test_desktop_session_is_long_lived_and_slides_on_heartbeat) ... ok
|
||||
test_first_login_can_still_reach_the_password_endpoint (test_admin_api.AuthTest.test_first_login_can_still_reach_the_password_endpoint)
|
||||
老实现首登一律 403,连改密接口都调不通,只能去网页后台改。 ... ok
|
||||
test_login_returns_the_permission_list (test_admin_api.AuthTest.test_login_returns_the_permission_list) ... ok
|
||||
test_logout_actually_kills_the_token (test_admin_api.AuthTest.test_logout_actually_kills_the_token) ... ok
|
||||
test_no_token_means_401_not_403 (test_admin_api.AuthTest.test_no_token_means_401_not_403) ... ok
|
||||
test_scoped_manager_cannot_reach_an_unassigned_desktop_account (test_admin_api.AuthTest.test_scoped_manager_cannot_reach_an_unassigned_desktop_account) ... ok
|
||||
test_auto_backup_policy_round_trips_to_desktop_clients (test_admin_api.ConfigApiTest.test_auto_backup_policy_round_trips_to_desktop_clients) ... ok
|
||||
test_config_read_and_write_are_separate_permissions (test_admin_api.ConfigApiTest.test_config_read_and_write_are_separate_permissions)
|
||||
排查线上问题的人要能看配置,但不该能改。 ... ok
|
||||
test_invalid_values_are_refused_with_a_usable_reason (test_admin_api.ConfigApiTest.test_invalid_values_are_refused_with_a_usable_reason) ... ok
|
||||
test_login_domain_is_saved_and_returned_to_desktop_before_login (test_admin_api.ConfigApiTest.test_login_domain_is_saved_and_returned_to_desktop_before_login) ... ok
|
||||
test_model_settings_are_gone_from_the_config (test_admin_api.ConfigApiTest.test_model_settings_are_gone_from_the_config)
|
||||
服务类型 / API 地址 / 密钥 / 模型名 / 温度 / tokens / 超时都搬去了角色编排。 ... ok
|
||||
test_no_api_key_value_is_ever_returned (test_admin_api.ConfigApiTest.test_no_api_key_value_is_ever_returned)
|
||||
库里可能还留着老记录的密钥,但一个字节都不能出接口。 ... ok
|
||||
test_saving_bumps_the_version_so_clients_notice (test_admin_api.ConfigApiTest.test_saving_bumps_the_version_so_clients_notice) ... ok
|
||||
test_smuggling_a_retired_field_back_in_does_not_take_effect (test_admin_api.ConfigApiTest.test_smuggling_a_retired_field_back_in_does_not_take_effect)
|
||||
老客户端或手工调接口的人可能还带着这些字段。 ... ok
|
||||
test_the_config_payload_matches_the_legacy_key_set (test_admin_api.ConfigApiTest.test_the_config_payload_matches_the_legacy_key_set)
|
||||
字段少一个,桌面端就少读一个设置——而且是静悄悄地少。 ... ok
|
||||
test_a_deliberately_set_false_is_not_mistaken_for_unset (test_admin_api.ConfigNullPoisoningTest.test_a_deliberately_set_false_is_not_mistaken_for_unset)
|
||||
补默认值的判据必须是"None",不能是"假值"——否则关掉的开关会被强制打开。 ... ok
|
||||
test_a_stale_cached_page_that_still_sends_null_is_tolerated (test_admin_api.ConfigNullPoisoningTest.test_a_stale_cached_page_that_still_sends_null_is_tolerated)
|
||||
浏览器里开着修复之前拉取的旧页面,表单里还揣着当时的 null。 ... ok
|
||||
test_get_config_never_leaks_null_for_a_missing_or_null_field (test_admin_api.ConfigNullPoisoningTest.test_get_config_never_leaks_null_for_a_missing_or_null_field) ... ok
|
||||
test_round_tripping_what_get_returns_never_422s (test_admin_api.ConfigNullPoisoningTest.test_round_tripping_what_get_returns_never_422s)
|
||||
这就是这个 bug 真实发生的顺序:前端 GET 拿表单初值,原样 POST 回去。 ... ok
|
||||
test_the_legacy_desktop_sync_endpoint_is_covered_too (test_admin_api.ConfigNullPoisoningTest.test_the_legacy_desktop_sync_endpoint_is_covered_too)
|
||||
下发给桌面端的那一份,也走同一段"透传 CONFIG_KEYS"的代码。 ... ok
|
||||
test_the_v2_desktop_sync_endpoint_is_covered_too (test_admin_api.ConfigNullPoisoningTest.test_the_v2_desktop_sync_endpoint_is_covered_too) ... ok
|
||||
test_a_published_release_reaches_the_desktop_payload (test_admin_api.DesktopSyncApiTest.test_a_published_release_reaches_the_desktop_payload)
|
||||
后台点了发布,客户端下一次同步就该看到——这条链断了没人会立刻发现。 ... ok
|
||||
test_a_wrong_sync_key_is_rejected (test_admin_api.DesktopSyncApiTest.test_a_wrong_sync_key_is_rejected) ... ok
|
||||
test_model_keys_go_out_masked_never_in_the_clear (test_admin_api.DesktopSyncApiTest.test_model_keys_go_out_masked_never_in_the_clear)
|
||||
桌面端拿到的是遮罩值;真正的调用要走模型网关。 ... ok
|
||||
test_payload_preserves_legacy_fields_and_adds_tenant_knowledge_summary (test_admin_api.DesktopSyncApiTest.test_payload_preserves_legacy_fields_and_adds_tenant_knowledge_summary) ... ok
|
||||
test_a_missing_model_is_404 (test_admin_api.ModelTestApiTest.test_a_missing_model_is_404) ... ok
|
||||
test_a_test_is_written_to_the_audit_log (test_admin_api.ModelTestApiTest.test_a_test_is_written_to_the_audit_log) ... ok
|
||||
test_an_unreachable_endpoint_reports_200_with_a_failed_result (test_admin_api.ModelTestApiTest.test_an_unreachable_endpoint_reports_200_with_a_failed_result)
|
||||
测试跑成功了、结论是"连不上"——这是 200,不是 5xx。 ... ok
|
||||
test_claude_says_why_instead_of_pretending_to_test (test_admin_api.ModelTestApiTest.test_claude_says_why_instead_of_pretending_to_test)
|
||||
老后台的测试器只认 openai/dify/comfyui。硬套 claude 只会得到误导性的 404。 ... ok
|
||||
test_testing_a_catalog_model_never_needs_the_key_from_the_browser (test_admin_api.ModelTestApiTest.test_testing_a_catalog_model_never_needs_the_key_from_the_browser)
|
||||
前端只送 id,密钥由后端从库里解密——明文不在网络上多走一趟。 ... ok
|
||||
test_testing_requires_write_because_it_spends_money (test_admin_api.ModelTestApiTest.test_testing_requires_write_because_it_spends_money)
|
||||
只读用户能看模型清单,但不该能拿着公司的密钥往外发请求。 ... ok
|
||||
test_operator_can_change_models_but_not_touch_roles (test_admin_api.PermissionEnforcementTest.test_operator_can_change_models_but_not_touch_roles) ... ok
|
||||
test_revoking_a_permission_takes_effect_immediately (test_admin_api.PermissionEnforcementTest.test_revoking_a_permission_takes_effect_immediately)
|
||||
权限存在库里,不在代码里——改完不用重启,也不用重新登录。 ... ok
|
||||
test_the_error_says_which_permission_is_missing (test_admin_api.PermissionEnforcementTest.test_the_error_says_which_permission_is_missing) ... ok
|
||||
test_viewer_can_read_models_but_not_change_them (test_admin_api.PermissionEnforcementTest.test_viewer_can_read_models_but_not_change_them) ... ok
|
||||
test_viewer_cannot_manage_users (test_admin_api.PermissionEnforcementTest.test_viewer_cannot_manage_users) ... ok
|
||||
test_viewer_cannot_read_the_audit_log (test_admin_api.PermissionEnforcementTest.test_viewer_cannot_read_the_audit_log) ... ok
|
||||
test_a_v_prefix_is_stripped_not_rejected (test_admin_api.ReleaseApiTest.test_a_v_prefix_is_stripped_not_rejected)
|
||||
人习惯写 v2.5.0。存进去必须是 2.5.0,否则客户端比对版本号永远不相等。 ... ok
|
||||
test_bad_versions_and_urls_are_refused (test_admin_api.ReleaseApiTest.test_bad_versions_and_urls_are_refused) ... ok
|
||||
test_desktop_can_report_update_progress (test_admin_api.ReleaseApiTest.test_desktop_can_report_update_progress) ... ok
|
||||
test_force_upgrade_without_a_download_url_is_refused (test_admin_api.ReleaseApiTest.test_force_upgrade_without_a_download_url_is_refused)
|
||||
开了强制升级又没给下载地址,等于把所有客户端堵死在原地。 ... ok
|
||||
test_package_upload_builds_a_verified_public_manifest (test_admin_api.ReleaseApiTest.test_package_upload_builds_a_verified_public_manifest) ... ok
|
||||
test_paused_release_is_not_offered_and_history_is_retained (test_admin_api.ReleaseApiTest.test_paused_release_is_not_offered_and_history_is_retained) ... ok
|
||||
test_publishing_a_version_records_it (test_admin_api.ReleaseApiTest.test_publishing_a_version_records_it) ... ok
|
||||
test_reading_needs_config_read_but_writing_needs_release_write (test_admin_api.ReleaseApiTest.test_reading_needs_config_read_but_writing_needs_release_write) ... ok
|
||||
test_an_invalid_rule_is_rejected_with_a_readable_reason (test_admin_api.ReviewRuleConfigApiTest.test_an_invalid_rule_is_rejected_with_a_readable_reason) ... ok
|
||||
test_saving_a_rule_set_round_trips_through_the_api (test_admin_api.ReviewRuleConfigApiTest.test_saving_a_rule_set_round_trips_through_the_api) ... ok
|
||||
test_the_desktop_sync_endpoints_ship_the_rules_too (test_admin_api.ReviewRuleConfigApiTest.test_the_desktop_sync_endpoints_ship_the_rules_too) ... ok
|
||||
test_the_seeded_defaults_come_with_three_starter_rules (test_admin_api.ReviewRuleConfigApiTest.test_the_seeded_defaults_come_with_three_starter_rules)
|
||||
全新的库不该是空的——刚上线这个功能时,起步规则不能一条都没有。 ... ok
|
||||
test_a_normal_rule_round_trips (test_admin_api.ReviewRuleValidationTest.test_a_normal_rule_round_trips) ... ok
|
||||
test_a_rule_with_no_keywords_is_refused (test_admin_api.ReviewRuleValidationTest.test_a_rule_with_no_keywords_is_refused)
|
||||
空关键词的规则不是"温和一点",是"这条规则永远不会命中"——必须当错误处理。 ... ok
|
||||
test_a_rule_without_a_label_is_refused (test_admin_api.ReviewRuleValidationTest.test_a_rule_without_a_label_is_refused) ... ok
|
||||
test_an_absurdly_long_label_is_refused (test_admin_api.ReviewRuleValidationTest.test_an_absurdly_long_label_is_refused) ... ok
|
||||
test_an_item_that_is_not_an_object_is_refused (test_admin_api.ReviewRuleValidationTest.test_an_item_that_is_not_an_object_is_refused) ... ok
|
||||
test_enabled_defaults_to_true_when_omitted (test_admin_api.ReviewRuleValidationTest.test_enabled_defaults_to_true_when_omitted) ... ok
|
||||
test_enabled_false_is_respected (test_admin_api.ReviewRuleValidationTest.test_enabled_false_is_respected) ... ok
|
||||
test_keywords_must_be_a_list (test_admin_api.ReviewRuleValidationTest.test_keywords_must_be_a_list) ... ok
|
||||
test_keywords_that_are_all_blank_strings_still_count_as_empty (test_admin_api.ReviewRuleValidationTest.test_keywords_that_are_all_blank_strings_still_count_as_empty) ... ok
|
||||
test_missing_ids_are_auto_generated_and_deduplicated (test_admin_api.ReviewRuleValidationTest.test_missing_ids_are_auto_generated_and_deduplicated) ... ok
|
||||
test_the_root_must_be_a_list (test_admin_api.ReviewRuleValidationTest.test_the_root_must_be_a_list) ... ok
|
||||
test_too_many_keywords_on_one_rule_is_refused (test_admin_api.ReviewRuleValidationTest.test_too_many_keywords_on_one_rule_is_refused) ... ok
|
||||
test_too_many_rules_is_refused (test_admin_api.ReviewRuleValidationTest.test_too_many_rules_is_refused) ... ok
|
||||
test_a_legacy_database_migrates_without_losing_anything (test_admin_api.RoleCheckMigrationTest.test_a_legacy_database_migrates_without_losing_anything) ... [RBAC] users.role 已从写死的 CHECK 迁移为角色表外键
|
||||
ok
|
||||
test_an_unknown_role_is_downgraded_instead_of_crashing (test_admin_api.RoleCheckMigrationTest.test_an_unknown_role_is_downgraded_instead_of_crashing)
|
||||
手工改库或早期版本会留下角色表里没有的值。收紧权限,不是崩掉服务。 ... ok
|
||||
test_leftovers_from_a_failed_run_are_cleaned_up (test_admin_api.RoleCheckMigrationTest.test_leftovers_from_a_failed_run_are_cleaned_up) ... [RBAC] users.role 已从写死的 CHECK 迁移为角色表外键
|
||||
ok
|
||||
test_running_it_twice_is_harmless (test_admin_api.RoleCheckMigrationTest.test_running_it_twice_is_harmless) ... [RBAC] users.role 已从写死的 CHECK 迁移为角色表外键
|
||||
ok
|
||||
test_a_custom_role_can_be_created_and_used (test_admin_api.RoleManagementTest.test_a_custom_role_can_be_created_and_used) ... ok
|
||||
test_a_role_still_in_use_cannot_be_deleted (test_admin_api.RoleManagementTest.test_a_role_still_in_use_cannot_be_deleted) ... ok
|
||||
test_an_unknown_permission_code_is_refused (test_admin_api.RoleManagementTest.test_an_unknown_permission_code_is_refused) ... ok
|
||||
test_assigning_a_nonexistent_role_is_refused (test_admin_api.RoleManagementTest.test_assigning_a_nonexistent_role_is_refused) ... ok
|
||||
test_builtin_roles_cannot_be_deleted (test_admin_api.RoleManagementTest.test_builtin_roles_cannot_be_deleted) ... ok
|
||||
test_granting_replaces_rather_than_appends (test_admin_api.RoleManagementTest.test_granting_replaces_rather_than_appends)
|
||||
界面是一组勾选框,提交的是最终状态。增量语义会让"取消勾选"静默失效。 ... ok
|
||||
test_the_admin_role_cannot_be_stripped_of_its_powers (test_admin_api.RoleManagementTest.test_the_admin_role_cannot_be_stripped_of_its_powers)
|
||||
把 admin 削权之后就没人能再加回来了,只能改库。 ... ok
|
||||
test_a_build_without_an_assets_folder_still_boots (test_admin_api.StaticMountTest.test_a_build_without_an_assets_folder_still_boots)
|
||||
vite 默认输出 js/ 和 css/,没有 assets/。这种产物必须能起来。 ... ok
|
||||
test_all_of_the_usual_asset_folders_get_mounted (test_admin_api.StaticMountTest.test_all_of_the_usual_asset_folders_get_mounted) ... ok
|
||||
test_an_empty_dist_directory_is_ignored (test_admin_api.StaticMountTest.test_an_empty_dist_directory_is_ignored)
|
||||
只有一个空 dist 目录时不挂 SPA 兜底路由。 ... ok
|
||||
test_an_unknown_api_path_is_404_not_the_spa_page (test_admin_api.StaticMountTest.test_an_unknown_api_path_is_404_not_the_spa_page)
|
||||
兜底路由不能把打错的接口地址伪装成一个正常页面。 ... ok
|
||||
test_a_malformed_call_report_never_500s (test_admin_api.StatsTest.test_a_malformed_call_report_never_500s)
|
||||
观测数据出问题不能让桌面端以为回复流程失败了。 ... ok
|
||||
test_model_call_logs_are_isolated_by_desktop_account (test_admin_api.StatsTest.test_model_call_logs_are_isolated_by_desktop_account) ... ok
|
||||
test_model_call_stats_answers_the_cost_question (test_admin_api.StatsTest.test_model_call_stats_answers_the_cost_question) ... ok
|
||||
test_reporting_a_call_without_the_sync_key_is_refused (test_admin_api.StatsTest.test_reporting_a_call_without_the_sync_key_is_refused) ... ok
|
||||
test_the_audit_log_records_who_changed_what (test_admin_api.StatsTest.test_the_audit_log_records_who_changed_what) ... ok
|
||||
test_the_call_log_is_gated_behind_stats_read (test_admin_api.StatsTest.test_the_call_log_is_gated_behind_stats_read) ... ok
|
||||
test_the_call_log_lists_individual_calls_for_tracing (test_admin_api.StatsTest.test_the_call_log_lists_individual_calls_for_tracing)
|
||||
聚合统计答不了"这一条到底怎么回的"——这个接口按条翻,供排查问题用。 ... ok
|
||||
test_the_call_log_search_filters_by_keyword (test_admin_api.StatsTest.test_the_call_log_search_filters_by_keyword) ... ok
|
||||
test_the_desktop_can_report_a_model_call_to_the_new_api (test_admin_api.StatsTest.test_the_desktop_can_report_a_model_call_to_the_new_api)
|
||||
8766 得能收调用留痕,否则桌面端改指过来就会静悄悄丢掉全部调用记录。 ... ok
|
||||
test_a_weak_password_is_refused_on_create (test_admin_api.UserApiTest.test_a_weak_password_is_refused_on_create) ... ok
|
||||
test_the_listing_never_leaks_password_material (test_admin_api.UserApiTest.test_the_listing_never_leaks_password_material) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 127 tests in 157.595s
|
||||
|
||||
OK
|
||||
@@ -1,27 +0,0 @@
|
||||
test_admin_can_query_all_usage_and_filter_model (test_model_usage_ledger.ModelUsageApiTests.test_admin_can_query_all_usage_and_filter_model) ... ok
|
||||
test_invalid_query_ranges_are_rejected (test_model_usage_ledger.ModelUsageApiTests.test_invalid_query_ranges_are_rejected) ... ok
|
||||
test_scoped_admin_all_means_only_authorized_accounts (test_model_usage_ledger.ModelUsageApiTests.test_scoped_admin_all_means_only_authorized_accounts) ... ok
|
||||
test_stats_and_log_require_login_and_stats_read (test_model_usage_ledger.ModelUsageApiTests.test_stats_and_log_require_login_and_stats_read) ... ok
|
||||
test_all_purposes_default_and_precise_provider_model_filters (test_model_usage_ledger.ModelUsageLedgerTests.test_all_purposes_default_and_precise_provider_model_filters) ... ok
|
||||
test_answer_candidates_judge_retry_and_error_are_all_charged (test_model_usage_ledger.ModelUsageLedgerTests.test_answer_candidates_judge_retry_and_error_are_all_charged) ... ok
|
||||
test_batch_retry_only_inserts_new_events (test_model_usage_ledger.ModelUsageLedgerTests.test_batch_retry_only_inserts_new_events) ... ok
|
||||
test_concurrent_duplicate_writers_insert_once (test_model_usage_ledger.ModelUsageLedgerTests.test_concurrent_duplicate_writers_insert_once) ... ok
|
||||
test_default_specific_and_multi_account_scopes_are_isolated (test_model_usage_ledger.ModelUsageLedgerTests.test_default_specific_and_multi_account_scopes_are_isolated) ... ok
|
||||
test_empty_statistics_are_zero_with_all_requested_calendar_days (test_model_usage_ledger.ModelUsageLedgerTests.test_empty_statistics_are_zero_with_all_requested_calendar_days) ... ok
|
||||
test_event_id_is_idempotent_and_first_record_is_immutable (test_model_usage_ledger.ModelUsageLedgerTests.test_event_id_is_idempotent_and_first_record_is_immutable) ... ok
|
||||
test_invalid_metadata_and_noninteger_tokens_are_rejected (test_model_usage_ledger.ModelUsageLedgerTests.test_invalid_metadata_and_noninteger_tokens_are_rejected) ... ok
|
||||
test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted) ... ok
|
||||
test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches) ... ok
|
||||
test_migration_preserves_old_rows_and_is_repeatable (test_model_usage_ledger.ModelUsageLedgerTests.test_migration_preserves_old_rows_and_is_repeatable) ... ok
|
||||
test_missing_usage_stays_null_and_is_not_counted_as_known (test_model_usage_ledger.ModelUsageLedgerTests.test_missing_usage_stays_null_and_is_not_counted_as_known) ... ok
|
||||
test_only_allowlisted_metadata_is_persisted (test_model_usage_ledger.ModelUsageLedgerTests.test_only_allowlisted_metadata_is_persisted) ... ok
|
||||
test_pagination_is_stable_and_database_limit_is_capped (test_model_usage_ledger.ModelUsageLedgerTests.test_pagination_is_stable_and_database_limit_is_capped) ... ok
|
||||
test_partial_usage_is_never_filled_or_total_estimated (test_model_usage_ledger.ModelUsageLedgerTests.test_partial_usage_is_never_filled_or_total_estimated) ... ok
|
||||
test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets (test_model_usage_ledger.ModelUsageLedgerTests.test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets) ... ok
|
||||
test_validation_or_storage_failure_raises_and_batch_does_not_partially_write (test_model_usage_ledger.ModelUsageLedgerTests.test_validation_or_storage_failure_raises_and_batch_does_not_partially_write) ... ok
|
||||
test_zero_reported_tokens_are_known (test_model_usage_ledger.ModelUsageLedgerTests.test_zero_reported_tokens_are_known) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 12.063s
|
||||
|
||||
OK
|
||||
@@ -1,28 +0,0 @@
|
||||
test_admin_can_query_all_usage_and_filter_model (test_model_usage_ledger.ModelUsageApiTests.test_admin_can_query_all_usage_and_filter_model) ... ok
|
||||
test_invalid_query_ranges_are_rejected (test_model_usage_ledger.ModelUsageApiTests.test_invalid_query_ranges_are_rejected) ... ok
|
||||
test_scoped_admin_all_means_only_authorized_accounts (test_model_usage_ledger.ModelUsageApiTests.test_scoped_admin_all_means_only_authorized_accounts) ... ok
|
||||
test_stats_and_log_require_login_and_stats_read (test_model_usage_ledger.ModelUsageApiTests.test_stats_and_log_require_login_and_stats_read) ... ok
|
||||
test_all_purposes_default_and_precise_provider_model_filters (test_model_usage_ledger.ModelUsageLedgerTests.test_all_purposes_default_and_precise_provider_model_filters) ... ok
|
||||
test_answer_candidates_judge_retry_and_error_are_all_charged (test_model_usage_ledger.ModelUsageLedgerTests.test_answer_candidates_judge_retry_and_error_are_all_charged) ... ok
|
||||
test_batch_retry_only_inserts_new_events (test_model_usage_ledger.ModelUsageLedgerTests.test_batch_retry_only_inserts_new_events) ... ok
|
||||
test_concurrent_duplicate_writers_insert_once (test_model_usage_ledger.ModelUsageLedgerTests.test_concurrent_duplicate_writers_insert_once) ... ok
|
||||
test_default_specific_and_multi_account_scopes_are_isolated (test_model_usage_ledger.ModelUsageLedgerTests.test_default_specific_and_multi_account_scopes_are_isolated) ... ok
|
||||
test_empty_statistics_are_zero_with_all_requested_calendar_days (test_model_usage_ledger.ModelUsageLedgerTests.test_empty_statistics_are_zero_with_all_requested_calendar_days) ... ok
|
||||
test_event_id_is_idempotent_and_first_record_is_immutable (test_model_usage_ledger.ModelUsageLedgerTests.test_event_id_is_idempotent_and_first_record_is_immutable) ... ok
|
||||
test_invalid_metadata_and_noninteger_tokens_are_rejected (test_model_usage_ledger.ModelUsageLedgerTests.test_invalid_metadata_and_noninteger_tokens_are_rejected) ... ok
|
||||
test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_logs_are_not_fabricated_and_only_unmatched_tasks_are_counted) ... ok
|
||||
test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches (test_model_usage_ledger.ModelUsageLedgerTests.test_legacy_task_match_does_not_cross_tenants_and_default_alias_matches) ... ok
|
||||
test_migration_preserves_old_rows_and_is_repeatable (test_model_usage_ledger.ModelUsageLedgerTests.test_migration_preserves_old_rows_and_is_repeatable) ... ok
|
||||
test_missing_usage_stays_null_and_is_not_counted_as_known (test_model_usage_ledger.ModelUsageLedgerTests.test_missing_usage_stays_null_and_is_not_counted_as_known) ... ok
|
||||
test_only_allowlisted_metadata_is_persisted (test_model_usage_ledger.ModelUsageLedgerTests.test_only_allowlisted_metadata_is_persisted) ... ok
|
||||
test_pagination_is_stable_and_database_limit_is_capped (test_model_usage_ledger.ModelUsageLedgerTests.test_pagination_is_stable_and_database_limit_is_capped) ... ok
|
||||
test_partial_usage_is_never_filled_or_total_estimated (test_model_usage_ledger.ModelUsageLedgerTests.test_partial_usage_is_never_filled_or_total_estimated) ... ok
|
||||
test_usage_write_lock_has_short_budget_without_changing_other_connections (test_model_usage_ledger.ModelUsageLedgerTests.test_usage_write_lock_has_short_budget_without_changing_other_connections) ... ok
|
||||
test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets (test_model_usage_ledger.ModelUsageLedgerTests.test_utc_window_includes_today_excludes_tomorrow_and_normalizes_offsets) ... ok
|
||||
test_validation_or_storage_failure_raises_and_batch_does_not_partially_write (test_model_usage_ledger.ModelUsageLedgerTests.test_validation_or_storage_failure_raises_and_batch_does_not_partially_write) ... ok
|
||||
test_zero_reported_tokens_are_known (test_model_usage_ledger.ModelUsageLedgerTests.test_zero_reported_tokens_are_known) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 23 tests in 10.161s
|
||||
|
||||
OK
|
||||
@@ -1,209 +0,0 @@
|
||||
Build Python: C:\wechat_rpa\.build-venv\Scripts\python.exe
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_final.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_export_media.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_voice2text.py -> archive_exporter
|
||||
Archive source verified: C:\wechat_rpa\archive_exporter\wxwork_crypto.py -> archive_exporter
|
||||
206 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
206 INFO: Python: 3.12.14
|
||||
247 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
248 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
2110 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
2780 INFO: Appending 'binaries' from .spec
|
||||
2780 INFO: Appending 'datas' from .spec
|
||||
2782 INFO: checking Analysis
|
||||
2942 INFO: Building because excludes changed
|
||||
2942 INFO: Looking for Python shared library...
|
||||
2942 INFO: Using Python shared library: C:\Users\isard\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python312.dll
|
||||
2942 INFO: Running Analysis Analysis-00.toc
|
||||
2942 INFO: Target bytecode optimization level: 1
|
||||
2942 INFO: Initializing module dependency graph...
|
||||
2945 INFO: Initializing module graph hook caches...
|
||||
2968 INFO: Analyzing modules for base_library.zip ...
|
||||
4722 INFO: Processing standard module hook 'hook-heapq.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
4838 INFO: Processing standard module hook 'hook-encodings.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
6776 INFO: Processing standard module hook 'hook-math.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
7145 INFO: Processing standard module hook 'hook-pickle.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
9198 INFO: Caching module dependency graph...
|
||||
9255 INFO: Analyzing C:\wechat_rpa\app_main.py
|
||||
9421 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
9641 INFO: Processing standard module hook 'hook-xml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10007 INFO: Processing standard module hook 'hook-_ctypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10115 INFO: Processing standard module hook 'hook-sqlite3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
10664 INFO: Processing standard module hook 'hook-Crypto.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
11700 INFO: Processing standard module hook 'hook-pycparser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
11909 INFO: Processing standard module hook 'hook-setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
11911 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
12917 INFO: Processing standard module hook 'hook-platform.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
12921 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
13005 INFO: Processing standard module hook 'hook-sysconfig.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13021 INFO: Processing pre-safe-import-module hook 'hook-jaraco.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
13022 INFO: Setuptools: 'jaraco' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.jaraco'!
|
||||
13044 INFO: Processing pre-safe-import-module hook 'hook-more_itertools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
13046 INFO: Setuptools: 'more_itertools' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.more_itertools'!
|
||||
13238 INFO: Processing standard module hook 'hook-_osx_support.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
13244 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14032 INFO: Processing pre-safe-import-module hook 'hook-packaging.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14381 INFO: Processing standard module hook 'hook-setuptools._vendor.jaraco.text.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
14383 INFO: Processing pre-safe-import-module hook 'hook-importlib_resources.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14638 INFO: Processing pre-safe-import-module hook 'hook-backports.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
14639 INFO: Setuptools: 'backports' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.backports'!
|
||||
15461 INFO: Processing pre-safe-import-module hook 'hook-tomli.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
15462 INFO: Setuptools: 'tomli' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.tomli'!
|
||||
16222 INFO: Processing pre-safe-import-module hook 'hook-wheel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module'
|
||||
16223 INFO: Setuptools: 'wheel' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.wheel'!
|
||||
16928 INFO: Processing standard module hook 'hook-webbrowser.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
17656 INFO: Processing standard module hook 'hook-urllib3.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18313 INFO: Processing standard module hook 'hook-certifi.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18377 INFO: Processing standard module hook 'hook-charset_normalizer.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
18573 INFO: Processing standard module hook 'hook-cryptography.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
20452 INFO: hook-cryptography: cryptography does not seem to be using dynamically linked OpenSSL.
|
||||
22513 INFO: Processing standard module hook 'hook-PySide6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
22838 INFO: Processing standard module hook 'hook-shiboken6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
23036 INFO: Processing standard module hook 'hook-PySide6.QtNetwork.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
30721 INFO: Processing standard module hook 'hook-PySide6.QtCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
36962 INFO: Processing standard module hook 'hook-PySide6.QtGui.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
67197 INFO: Processing standard module hook 'hook-PySide6.QtWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
74906 INFO: Processing standard module hook 'hook-PySide6.QtWebChannel.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
77035 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineCore.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
83554 INFO: Processing standard module hook 'hook-PySide6.QtWebEngineWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
87041 INFO: Processing standard module hook 'hook-PySide6.QtPrintSupport.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
92063 INFO: Processing pre-find-module-path hook 'hook-tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
92065 INFO: TclTkInfo: initializing cached Tcl/Tk info...
|
||||
93565 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
93608 INFO: Processing standard module hook 'hook-PIL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
93758 INFO: Processing standard module hook 'hook-PIL.Image.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
94317 INFO: Processing standard module hook 'hook-numpy.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
96412 INFO: Processing standard module hook 'hook-difflib.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
97852 INFO: Processing standard module hook 'hook-xml.etree.cElementTree.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
98405 INFO: Processing standard module hook 'hook-PIL.ImageFilter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
98969 INFO: Processing standard module hook 'hook-cv2.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
99993 INFO: Processing standard module hook 'hook-onnxruntime.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
100108 INFO: Processing pre-safe-import-module hook 'hook-tensorflow.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\pre_safe_import_module'
|
||||
100169 INFO: Processing standard module hook 'hook-shapely.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
100595 INFO: Processing standard module hook 'hook-pydantic.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
101592 INFO: Processing standard module hook 'hook-rich.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
102805 INFO: Processing standard module hook 'hook-pygments.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
106040 INFO: Processing standard module hook 'hook-zoneinfo.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
107769 INFO: Processing standard module hook 'hook-anyio.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
109314 INFO: Processing standard module hook 'hook-opentelemetry.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
109868 INFO: Processing standard module hook 'hook-uvicorn.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
112063 INFO: Processing standard module hook 'hook-websockets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
114714 INFO: Processing standard module hook 'hook-pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
114972 INFO: Processing standard module hook 'hook-jsonschema.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
115137 INFO: Processing standard module hook 'hook-jsonschema_specifications.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\stdhooks'
|
||||
116005 INFO: Analyzing hidden import 'mcp.cli'
|
||||
116461 INFO: Analyzing hidden import 'mcp.client.__main__'
|
||||
116466 INFO: Analyzing hidden import 'mcp.client.auth'
|
||||
116511 INFO: Analyzing hidden import 'mcp.client.auth.extensions'
|
||||
116512 INFO: Analyzing hidden import 'mcp.client.auth.extensions.client_credentials'
|
||||
116613 INFO: Analyzing hidden import 'mcp.client.auth.extensions.identity_assertion'
|
||||
116620 INFO: Analyzing hidden import 'mcp.server.__main__'
|
||||
116622 INFO: Analyzing hidden import 'mcp.server.apps'
|
||||
116629 INFO: Analyzing hidden import 'mcp.server.fastmcp'
|
||||
116630 INFO: Analyzing hidden import 'mcp.shared.metadata_utils'
|
||||
116631 INFO: Processing module hooks (post-graph stage)...
|
||||
116837 WARNING: Hidden import "pycparser.lextab" not found!
|
||||
116837 WARNING: Hidden import "pycparser.yacctab" not found!
|
||||
117410 WARNING: Hidden import "tzdata" not found!
|
||||
117788 INFO: Processing standard module hook 'hook-PIL.SpiderImagePlugin.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
120839 INFO: Processing standard module hook 'hook-PySide6.QtQuick.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
124732 INFO: Processing standard module hook 'hook-PySide6.QtOpenGL.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
128662 INFO: Processing standard module hook 'hook-PySide6.QtQml.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
167667 INFO: Processing standard module hook 'hook-PySide6.QtPositioning.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
169833 INFO: Processing standard module hook 'hook-PySide6.QtQuickWidgets.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
171111 INFO: Processing standard module hook 'hook-_tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
171183 INFO: Performing binary vs. data reclassification (3714 entries)
|
||||
171963 INFO: Looking for ctypes DLLs
|
||||
172589 INFO: Analyzing run-time hooks ...
|
||||
172601 INFO: Including run-time hook 'pyi_rth_inspect.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172605 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172608 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172611 INFO: Including run-time hook 'pyi_rth_setuptools.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172613 INFO: Including run-time hook 'pyi_rth_cryptography_openssl.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
172614 INFO: Including run-time hook 'pyi_rth_pywintypes.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\_pyinstaller_hooks_contrib\\rthooks'
|
||||
172616 INFO: Including run-time hook 'pyi_rth_pyside6.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172618 INFO: Processing pre-find-module-path hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path'
|
||||
172622 INFO: Processing standard module hook 'hook-_pyi_rth_utils.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks'
|
||||
172626 INFO: Including run-time hook 'pyi_rth__tkinter.py' from 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks'
|
||||
172786 INFO: Creating base_library.zip...
|
||||
173129 INFO: Looking for dynamic libraries
|
||||
177010 INFO: Extra DLL search directories (AddDllDirectory): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shiboken6', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\numpy.libs', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\shapely.libs']
|
||||
177010 INFO: Extra DLL search directories (PATH): ['C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\cv2\\../../x64/vc17/bin', 'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\PySide6']
|
||||
183631 INFO: Warnings written to C:\wechat_rpa\build\wechat_rpa\warn-wechat_rpa.txt
|
||||
183892 INFO: Graph cross-reference written to C:\wechat_rpa\build\wechat_rpa\xref-wechat_rpa.html
|
||||
184127 INFO: checking PYZ
|
||||
184180 INFO: Building because C:\wechat_rpa\app_version.py changed
|
||||
184180 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz
|
||||
C:\wechat_rpa\.build-venv\Lib\site-packages\pyautogui\_pyautogui_x11.py:284: SyntaxWarning: invalid escape sequence '\e'
|
||||
'\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
|
||||
195204 INFO: Building PYZ (ZlibArchive) C:\wechat_rpa\build\wechat_rpa\PYZ-00.pyz completed successfully.
|
||||
195253 INFO: checking PKG
|
||||
195268 INFO: Building because name changed
|
||||
195268 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.26.pkg
|
||||
195324 INFO: Building PKG (CArchive) ZhenAI-WeCom-Assistant-v1.4.26.pkg completed successfully.
|
||||
195326 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\runw.exe
|
||||
195326 INFO: checking EXE
|
||||
195341 INFO: Rebuilding EXE-00.toc because ZhenAI-WeCom-Assistant-v1.4.26.exe missing
|
||||
195341 INFO: Building EXE from EXE-00.toc
|
||||
195341 INFO: Copying bootloader EXE to C:\wechat_rpa\build\wechat_rpa\ZhenAI-WeCom-Assistant-v1.4.26.exe
|
||||
195403 INFO: Copying icon to EXE
|
||||
195450 INFO: Copying version information to EXE
|
||||
195499 INFO: Copying 0 resources to EXE
|
||||
195499 INFO: Embedding manifest in EXE
|
||||
195543 INFO: Appending PKG archive to EXE
|
||||
195666 INFO: Fixing EXE headers
|
||||
196101 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
196233 INFO: checking COLLECT
|
||||
196352 INFO: Building COLLECT COLLECT-00.toc
|
||||
202283 INFO: Building COLLECT COLLECT-00.toc completed successfully.
|
||||
202399 INFO: Build complete! The results are available in: C:\wechat_rpa\dist
|
||||
Embedded browser and VC runtime files verified
|
||||
204 INFO: PyInstaller: 6.22.2, contrib hooks: 2026.7
|
||||
204 INFO: Python: 3.12.14
|
||||
242 INFO: Platform: Windows-11-10.0.26200-SP0
|
||||
242 INFO: Python environment: C:\wechat_rpa\.build-venv
|
||||
243 INFO: wrote C:\wechat_rpa\build\updater-helper\ZhenAIUpdater.spec
|
||||
258 INFO: Module search paths (PYTHONPATH):
|
||||
['C:\\wechat_rpa',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\python312.zip',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\DLLs',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python\\Lib',
|
||||
'C:\\Users\\isard\\.cache\\codex-runtimes\\codex-primary-runtime\\dependencies\\python',
|
||||
'C:\\wechat_rpa\\.build-venv',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\win32\\lib',
|
||||
'C:\\wechat_rpa\\.build-venv\\Lib\\site-packages\\pythonwin',
|
||||
'C:\\wechat_rpa']
|
||||
845 INFO: checking Analysis
|
||||
869 INFO: checking PYZ
|
||||
876 INFO: checking PKG
|
||||
879 INFO: Bootloader C:\wechat_rpa\.build-venv\Lib\site-packages\PyInstaller\bootloader\Windows-64bit-intel\run.exe
|
||||
879 INFO: checking EXE
|
||||
880 INFO: Build complete! The results are available in: C:\wechat_rpa\dist\updater-helper
|
||||
Code signing skipped (no certificate configured): ZhenAIUpdater.exe
|
||||
Independent updater built and bundled
|
||||
Code signing skipped (no certificate configured): ZhenAI-WeCom-Assistant-v1.4.26.exe
|
||||
Packaged Qt WebEngine self-check passed
|
||||
Packaged real HTTPS and certificate verification checks passed (clean PATH)
|
||||
Packaged automatic decryption and incremental cloud upload checks passed (synthetic data, mocked transport)
|
||||
Packaged Messages navigation and OCR checks passed (synthetic UI, mocked input)
|
||||
Packaged cross-machine capture, DPI and unread click checks passed (synthetic pixels, mocked input)
|
||||
Packaged self-reply feedback and send guards passed (synthetic archive, mocked input)
|
||||
Packaged background database detection and database-first reply checks passed (synthetic data, mocked input)
|
||||
App folder: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.26
|
||||
EXE: C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.26\ZhenAI-WeCom-Assistant-v1.4.26.exe
|
||||
SHA256: F826524800D2CB923E9C68017ED2B01EE54F6767E054971807AF27665046A427
|
||||
@@ -1,30 +0,0 @@
|
||||
MakeNSIS v3.12 - Copyright 1999-2026 Contributors
|
||||
See the file COPYING for license details.
|
||||
Credits can be found in the Users Manual.
|
||||
|
||||
Command line defined: "APP_VERSION=1.4.26"
|
||||
Command line defined: "APP_FILE_VERSION=1.4.26.0"
|
||||
Command line defined: "SOURCE_DIR=C:\wechat_rpa\dist\ZhenAI-WeCom-Assistant-v1.4.26"
|
||||
Processing config: C:\wechat_rpa\.installer-tools\NSIS\nsisconf.nsh
|
||||
Processing script file: "C:\wechat_rpa\installer.nsi" (UTF8)
|
||||
|
||||
Processed 1 file, writing output (x86-unicode):
|
||||
|
||||
Output: "C:\wechat_rpa\dist\installer\��AI�ͷ�-��װ��-v1.4.26.exe"
|
||||
Install: 4 pages (256 bytes), 1 section (2072 bytes), 4725 instructions (132300 bytes), 3342 strings (141484 bytes), 1 language table (302 bytes).
|
||||
Uninstall: 3 pages (256 bytes), 1 section (2072 bytes), 285 instructions (7980 bytes), 167 strings (3562 bytes), 1 language table (282 bytes).
|
||||
Datablock optimizer saved 1775 KiB (~0.2%).
|
||||
|
||||
Using zlib (compress whole) compression.
|
||||
|
||||
EXE header size: 118784 / 40960 bytes
|
||||
Install code: (276878 bytes)
|
||||
Install data: (868783817 bytes)
|
||||
Uninstall code+data: (141472 bytes)
|
||||
Compressed data: 352133446 / 869202167 bytes
|
||||
CRC (0x931220A2): 4 / 4 bytes
|
||||
|
||||
Total size: 352252234 / 869243131 bytes (40.5%)
|
||||
Code signing skipped (no certificate configured): 甄AI客服-安装包-v1.4.26.exe
|
||||
Installer: C:\wechat_rpa\dist\installer\甄AI客服-安装包-v1.4.26.exe
|
||||
SHA256: A558C24F7DB00EC907BE46F8CE67F2D9D7BB1F60992306BFA64020E294818A38
|
||||
@@ -1,849 +0,0 @@
|
||||
.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFF......FFFF [100%]
|
||||
=================================== ERRORS ====================================
|
||||
___________ ERROR at setup of test_deduplicate_episode_and_restart ____________
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_deduplicate_episode_and_r0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_human_completion_is_idempotent_and_new_risk_is_new_episode _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_human_completion_is_idemp0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes0] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes1] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o1')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes2] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o2')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes3] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o3')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes4] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o4')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes5] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o5')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes6] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o6')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes7] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o7')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes8] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o8')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes9] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o9')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes10] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o10')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes11] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o11')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes12] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o12')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_untrusted_or_historical_outbound_does_not_complete[changes13] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_untrusted_or_historical_o13')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
__ ERROR at setup of test_delivery_protection_survives_human_reply[sending] ___
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_delivery_protection_survi0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
__ ERROR at setup of test_delivery_protection_survives_human_reply[unknown] ___
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_delivery_protection_survi1')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_delivery_protection_survives_human_reply[uncertain] __
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_delivery_protection_survi2')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
___ ERROR at setup of test_delivery_protection_survives_human_reply[failed] ___
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_delivery_protection_survi3')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_delivery_protection_survives_human_reply[sent_uncommitted] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_delivery_protection_survi4')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
________ ERROR at setup of test_bot_receipt_and_attempt_are_not_human _________
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_bot_receipt_and_attempt_a0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
____ ERROR at setup of test_unknown_native_send_fingerprint_cannot_release ____
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_unknown_native_send_finge0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_local_approve_cancels_reminder_without_granting_resume _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_local_approve_cancels_rem0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
____ ERROR at setup of test_recipient_excluded_and_account_config_isolated ____
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_recipient_excluded_and_ac0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
________ ERROR at setup of test_notification_has_detail_and_utf8_limit ________
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_has_detail_a0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
___ ERROR at setup of test_notification_success_and_worker_owned_resources ____
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_success_and_0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_notification_outcomes_never_release_customer[DeliveryUnknown-unknown] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_outcomes_nev0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_notification_outcomes_never_release_customer[DeliveryFailed-unknown] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_outcomes_nev1')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_notification_outcomes_never_release_customer[NativeUnavailable-retry] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_outcomes_nev2')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_notification_outcomes_never_release_customer[SendCancelled-retry] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_notification_outcomes_nev3')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_recipient_or_account_change_never_sends[False-1688856770803435] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_recipient_or_account_chan0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
__ ERROR at setup of test_recipient_or_account_change_never_sends[True-999] ___
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_recipient_or_account_chan1')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_completed_or_changed_recipient_cancels_queued_notification _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_completed_or_changed_reci0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
_ ERROR at setup of test_cancel_while_disabled_closes_episode_without_resuming _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_cancel_while_disabled_clo0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
____ ERROR at setup of test_old_cancel_tombstone_does_not_clear_new_resume ____
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_old_cancel_tombstone_does0')
|
||||
|
||||
@pytest.fixture
|
||||
def setup(tmp_path):
|
||||
settings = {'review_assistant_accounts': {ACCOUNT: {'enabled': True, 'recipient_conv_id': RECIPIENT}}}
|
||||
service = ReviewAssistantCoordinator(tmp_path, lambda: settings, ACCOUNT)
|
||||
state = dict(account=ACCOUNT, conv_id=CONV, display_name='测试客户', awaiting_review=True,
|
||||
stage='awaiting_review', send_state='', review_reason='新风控', reply_text='未发送的草稿')
|
||||
incoming = msg()
|
||||
state['assistant_review_id'] = service.ensure_review(state, context(incoming))
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_assistant.py:39: AssertionError
|
||||
================================== FAILURES ===================================
|
||||
_ test_customer_recipient_m_and_both_s_orders_send_reminder[M:7881302444555666] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_customer_recipient_m_and_0')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x00000162701880E0>
|
||||
recipient = 'M:7881302444555666'
|
||||
|
||||
@pytest.mark.parametrize('recipient', RECIPIENTS)
|
||||
def test_customer_recipient_m_and_both_s_orders_send_reminder(tmp_path, monkeypatch, recipient):
|
||||
service, _ = make_service(tmp_path, recipient)
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:87:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x00000162701892B0>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_customer_recipient_m_and_both_s_orders_send_reminder[S:1688856770803435_7881302444555666] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_customer_recipient_m_and_1')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000016271719790>
|
||||
recipient = 'S:1688856770803435_7881302444555666'
|
||||
|
||||
@pytest.mark.parametrize('recipient', RECIPIENTS)
|
||||
def test_customer_recipient_m_and_both_s_orders_send_reminder(tmp_path, monkeypatch, recipient):
|
||||
service, _ = make_service(tmp_path, recipient)
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:87:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271719610>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_customer_recipient_m_and_both_s_orders_send_reminder[S:7881302444555666_1688856770803435] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_customer_recipient_m_and_2')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000016271718590>
|
||||
recipient = 'S:7881302444555666_1688856770803435'
|
||||
|
||||
@pytest.mark.parametrize('recipient', RECIPIENTS)
|
||||
def test_customer_recipient_m_and_both_s_orders_send_reminder(tmp_path, monkeypatch, recipient):
|
||||
service, _ = make_service(tmp_path, recipient)
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:87:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271719DF0>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_assistant_s_incoming_does_not_create_or_approve_customer_review[S:1688856770803435_7881302444555666] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_assistant_s_incoming_does0')
|
||||
recipient = 'S:1688856770803435_7881302444555666'
|
||||
|
||||
@pytest.mark.parametrize('recipient', RECIPIENTS[1:])
|
||||
def test_assistant_s_incoming_does_not_create_or_approve_customer_review(tmp_path, recipient):
|
||||
service, _ = make_service(tmp_path, recipient)
|
||||
> state = add_episode(service)
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:105:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271719EE0>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_assistant_s_incoming_does_not_create_or_approve_customer_review[S:7881302444555666_1688856770803435] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_assistant_s_incoming_does1')
|
||||
recipient = 'S:7881302444555666_1688856770803435'
|
||||
|
||||
@pytest.mark.parametrize('recipient', RECIPIENTS[1:])
|
||||
def test_assistant_s_incoming_does_not_create_or_approve_customer_review(tmp_path, recipient):
|
||||
service, _ = make_service(tmp_path, recipient)
|
||||
> state = add_episode(service)
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:105:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271857E90>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send[last_check0] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_relationship_revoked_or_u0')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000016271854CB0>
|
||||
last_check = {'ok': False, 'reason': '客户关系已解除'}
|
||||
|
||||
@pytest.mark.parametrize('last_check', [{'ok': False, 'reason': '客户关系已解除'},
|
||||
RuntimeError('合成关系读取失败')])
|
||||
def test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send(tmp_path, monkeypatch, last_check):
|
||||
service, _ = make_service(tmp_path, RECIPIENTS[1])
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:132:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271856690>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_ test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send[last_check1] _
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_relationship_revoked_or_u1')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000016271855D90>
|
||||
last_check = RuntimeError('合成关系读取失败')
|
||||
|
||||
@pytest.mark.parametrize('last_check', [{'ok': False, 'reason': '客户关系已解除'},
|
||||
RuntimeError('合成关系读取失败')])
|
||||
def test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send(tmp_path, monkeypatch, last_check):
|
||||
service, _ = make_service(tmp_path, RECIPIENTS[1])
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:132:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271855730>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
_____ test_recipient_changed_during_fresh_relationship_check_blocks_send ______
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_recipient_changed_during_0')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x00000162717194F0>
|
||||
|
||||
def test_recipient_changed_during_fresh_relationship_check_blocks_send(tmp_path, monkeypatch):
|
||||
service, settings = make_service(tmp_path, RECIPIENTS[1])
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:143:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x0000016271718B00>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
__________ test_unknown_notification_survives_restart_without_retry ___________
|
||||
|
||||
tmp_path = WindowsPath('C:/Users/isard/AppData/Local/Temp/frozen-customer-notify-xkzhai2q/pytest-tmp/test_unknown_notification_surv0')
|
||||
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x0000016271719D90>
|
||||
|
||||
def test_unknown_notification_survives_restart_without_retry(tmp_path, monkeypatch):
|
||||
service, settings = make_service(tmp_path, RECIPIENTS[1])
|
||||
> add_episode(service)
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:163:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
service = <review_assistant.ReviewAssistantCoordinator object at 0x000001627171AC90>
|
||||
|
||||
def add_episode(service):
|
||||
state = {'account': ACCOUNT, 'conv_id': CUSTOMER, 'display_name': '合成客户',
|
||||
'awaiting_review': True, 'stage': 'awaiting_review', 'send_state': '',
|
||||
'review_reason': '合成审核原因', 'reply_text': '未发送的合成草稿'}
|
||||
state['assistant_review_id'] = service.ensure_review(state, make_context())
|
||||
> assert state['assistant_review_id']
|
||||
E AssertionError: assert ''
|
||||
|
||||
C:\wechat_rpa\tests\test_review_customer_notifications.py:47: AssertionError
|
||||
=========================== short test summary info ===========================
|
||||
FAILED ::test_customer_recipient_m_and_both_s_orders_send_reminder[M:7881302444555666]
|
||||
FAILED ::test_customer_recipient_m_and_both_s_orders_send_reminder[S:1688856770803435_7881302444555666]
|
||||
FAILED ::test_customer_recipient_m_and_both_s_orders_send_reminder[S:7881302444555666_1688856770803435]
|
||||
FAILED ::test_assistant_s_incoming_does_not_create_or_approve_customer_review[S:1688856770803435_7881302444555666]
|
||||
FAILED ::test_assistant_s_incoming_does_not_create_or_approve_customer_review[S:7881302444555666_1688856770803435]
|
||||
FAILED ::test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send[last_check0]
|
||||
FAILED ::test_relationship_revoked_or_unreadable_at_final_native_guard_blocks_send[last_check1]
|
||||
FAILED ::test_recipient_changed_during_fresh_relationship_check_blocks_send
|
||||
FAILED ::test_unknown_notification_survives_restart_without_retry - Assertion...
|
||||
ERROR ::test_deduplicate_episode_and_restart - AssertionError: assert ''
|
||||
ERROR ::test_human_completion_is_idempotent_and_new_risk_is_new_episode - Ass...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes0] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes1] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes2] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes3] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes4] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes5] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes6] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes7] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes8] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes9] - A...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes10] - ...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes11] - ...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes12] - ...
|
||||
ERROR ::test_untrusted_or_historical_outbound_does_not_complete[changes13] - ...
|
||||
ERROR ::test_delivery_protection_survives_human_reply[sending] - AssertionErr...
|
||||
ERROR ::test_delivery_protection_survives_human_reply[unknown] - AssertionErr...
|
||||
ERROR ::test_delivery_protection_survives_human_reply[uncertain] - AssertionE...
|
||||
ERROR ::test_delivery_protection_survives_human_reply[failed] - AssertionErro...
|
||||
ERROR ::test_delivery_protection_survives_human_reply[sent_uncommitted] - Ass...
|
||||
ERROR ::test_bot_receipt_and_attempt_are_not_human - AssertionError: assert ''
|
||||
ERROR ::test_unknown_native_send_fingerprint_cannot_release - AssertionError:...
|
||||
ERROR ::test_local_approve_cancels_reminder_without_granting_resume - Asserti...
|
||||
ERROR ::test_recipient_excluded_and_account_config_isolated - AssertionError:...
|
||||
ERROR ::test_notification_has_detail_and_utf8_limit - AssertionError: assert ''
|
||||
ERROR ::test_notification_success_and_worker_owned_resources - AssertionError...
|
||||
ERROR ::test_notification_outcomes_never_release_customer[DeliveryUnknown-unknown]
|
||||
ERROR ::test_notification_outcomes_never_release_customer[DeliveryFailed-unknown]
|
||||
ERROR ::test_notification_outcomes_never_release_customer[NativeUnavailable-retry]
|
||||
ERROR ::test_notification_outcomes_never_release_customer[SendCancelled-retry]
|
||||
ERROR ::test_recipient_or_account_change_never_sends[False-1688856770803435]
|
||||
ERROR ::test_recipient_or_account_change_never_sends[True-999] - AssertionErr...
|
||||
ERROR ::test_completed_or_changed_recipient_cancels_queued_notification - Ass...
|
||||
ERROR ::test_cancel_while_disabled_closes_episode_without_resuming - Assertio...
|
||||
ERROR ::test_old_cancel_tombstone_does_not_clear_new_resume - AssertionError:...
|
||||
9 failed, 7 passed, 36 errors in 1.28s
|
||||
@@ -1,2 +0,0 @@
|
||||
.................................................... [100%]
|
||||
52 passed in 2.46s
|
||||
@@ -1,95 +0,0 @@
|
||||
test_absent_optional_phone_tables_do_not_affect_customer_list (test_review_assistant_contacts.ContactDirectoryTest.test_absent_optional_phone_tables_do_not_affect_customer_list) ... ok
|
||||
test_blocked_session_is_not_a_selectable_target (test_review_assistant_contacts.ContactDirectoryTest.test_blocked_session_is_not_a_selectable_target) ... ok
|
||||
test_both_s_id_orders_are_supported_but_no_address_is_synthesized (test_review_assistant_contacts.ContactDirectoryTest.test_both_s_id_orders_are_supported_but_no_address_is_synthesized) ... ok
|
||||
test_customer_remarks_precede_true_remarks_and_user_names_and_all_are_searchable (test_review_assistant_contacts.ContactDirectoryTest.test_customer_remarks_precede_true_remarks_and_user_names_and_all_are_searchable) ... ok
|
||||
test_default_roots_include_protocol_cache_before_archived_copy (test_review_assistant_contacts.ContactDirectoryTest.test_default_roots_include_protocol_cache_before_archived_copy) ... ok
|
||||
test_deleted_blacklisted_and_internal_users_are_excluded (test_review_assistant_contacts.ContactDirectoryTest.test_deleted_blacklisted_and_internal_users_are_excluded) ... ok
|
||||
test_existing_wecom_and_wechat_targets_keep_exact_identity_and_kind (test_review_assistant_contacts.ContactDirectoryTest.test_existing_wecom_and_wechat_targets_keep_exact_identity_and_kind) ... ok
|
||||
test_fresh_validation_bypasses_cached_membership_and_rechecks_account (test_review_assistant_contacts.ContactDirectoryTest.test_fresh_validation_bypasses_cached_membership_and_rechecks_account) ... ok
|
||||
test_latest_wal_revision_wins_between_account_caches (test_review_assistant_contacts.ContactDirectoryTest.test_latest_wal_revision_wins_between_account_caches) ... ok
|
||||
test_lookup_does_not_change_database_files_or_read_sensitive_columns (test_review_assistant_contacts.ContactDirectoryTest.test_lookup_does_not_change_database_files_or_read_sensitive_columns) ... ok
|
||||
test_missing_or_incomplete_customer_relation_table_fails_closed (test_review_assistant_contacts.ContactDirectoryTest.test_missing_or_incomplete_customer_relation_table_fails_closed) ... ok
|
||||
test_missing_user_database_returns_clear_failure_not_keyerror (test_review_assistant_contacts.ContactDirectoryTest.test_missing_user_database_returns_clear_failure_not_keyerror) ... ok
|
||||
test_no_conversation_customer_is_visible_but_cannot_be_selected (test_review_assistant_contacts.ContactDirectoryTest.test_no_conversation_customer_is_visible_but_cannot_be_selected) ... ok
|
||||
test_no_message_cache_lists_customers_pending_without_fake_targets (test_review_assistant_contacts.ContactDirectoryTest.test_no_message_cache_lists_customers_pending_without_fake_targets) ... ok
|
||||
test_only_my_customer_relationships_are_listed_not_phone_contacts_or_arbitrary_chats (test_review_assistant_contacts.ContactDirectoryTest.test_only_my_customer_relationships_are_listed_not_phone_contacts_or_arbitrary_chats) ... ok
|
||||
test_other_account_directory_is_never_read (test_review_assistant_contacts.ContactDirectoryTest.test_other_account_directory_is_never_read) ... ok
|
||||
test_refresh_invalidates_cache_for_new_customer_relationship (test_review_assistant_contacts.ContactDirectoryTest.test_refresh_invalidates_cache_for_new_customer_relationship) ... ok
|
||||
test_same_name_customers_remain_separate_and_pagination_is_after_filter (test_review_assistant_contacts.ContactDirectoryTest.test_same_name_customers_remain_separate_and_pagination_is_after_filter) ... ok
|
||||
test_strangers_unadded_self_and_invalid_uids_are_not_my_customers (test_review_assistant_contacts.ContactDirectoryTest.test_strangers_unadded_self_and_invalid_uids_are_not_my_customers) ... ok
|
||||
test_system_customer_names_and_session_metadata_cannot_enable_sends (test_review_assistant_contacts.ContactDirectoryTest.test_system_customer_names_and_session_metadata_cannot_enable_sends) ... ok
|
||||
test_unknown_name_does_not_become_fake_nickname_or_raw_s_identifier (test_review_assistant_contacts.ContactDirectoryTest.test_unknown_name_does_not_become_fake_nickname_or_raw_s_identifier) ... ok
|
||||
test_unknown_relation_status_is_visible_but_cannot_be_selected (test_review_assistant_contacts.ContactDirectoryTest.test_unknown_relation_status_is_visible_but_cannot_be_selected) ... ok
|
||||
test_wal_change_invalidates_customer_relationship_cache (test_review_assistant_contacts.ContactDirectoryTest.test_wal_change_invalidates_customer_relationship_cache) ... ok
|
||||
test_only_exact_account_bound_direct_ids_are_accepted (test_review_assistant_contacts.RecipientPeerTest.test_only_exact_account_bound_direct_ids_are_accepted) ... ok
|
||||
test_account_mismatch_never_reads_the_old_accounts_database (test_review_assistant_ui.ReminderContactTest.test_account_mismatch_never_reads_the_old_accounts_database) ... ok
|
||||
test_account_switch_during_validation_rejects_selection (test_review_assistant_ui.ReminderContactTest.test_account_switch_during_validation_rejects_selection) ... ok
|
||||
test_duplicate_names_remain_separate_and_identifiable (test_review_assistant_ui.ReminderContactTest.test_duplicate_names_remain_separate_and_identifiable) ... ok
|
||||
test_group_internal_or_unknown_recipient_cannot_be_saved (test_review_assistant_ui.ReminderContactTest.test_group_internal_or_unknown_recipient_cannot_be_saved) ... ok
|
||||
test_lists_relation_customers_with_s_and_m_chats_without_message_content (test_review_assistant_ui.ReminderContactTest.test_lists_relation_customers_with_s_and_m_chats_without_message_content) ... ok
|
||||
test_missing_account_does_not_fall_back_to_another_account (test_review_assistant_ui.ReminderContactTest.test_missing_account_does_not_fall_back_to_another_account) ... ok
|
||||
test_preview_is_static_and_does_not_load_real_customer_data (test_review_assistant_ui.ReminderContactTest.test_preview_is_static_and_does_not_load_real_customer_data) ... ok
|
||||
test_queries_are_read_only_and_do_not_initialize_or_modify_databases (test_review_assistant_ui.ReminderContactTest.test_queries_are_read_only_and_do_not_initialize_or_modify_databases) ... ok
|
||||
test_recipient_validation_uses_id_and_rechecks_identity (test_review_assistant_ui.ReminderContactTest.test_recipient_validation_uses_id_and_rechecks_identity) ... ok
|
||||
test_search_and_pagination_are_independent_of_message_preview (test_review_assistant_ui.ReminderContactTest.test_search_and_pagination_are_independent_of_message_preview) ... ok
|
||||
test_active_identity_only_uses_native_readonly_scope (test_review_assistant_ui.ReminderIdentityTest.test_active_identity_only_uses_native_readonly_scope) ... ok
|
||||
test_native_unavailable_is_clear_and_does_not_use_another_account (test_review_assistant_ui.ReminderIdentityTest.test_native_unavailable_is_clear_and_does_not_use_another_account) ... ok
|
||||
test_refresh_cannot_race_pending_recipient_validation (test_review_assistant_ui.ReminderPickerTest.test_refresh_cannot_race_pending_recipient_validation) ... ok
|
||||
test_refresh_remains_available_after_account_or_cache_error (test_review_assistant_ui.ReminderPickerTest.test_refresh_remains_available_after_account_or_cache_error) ... ok
|
||||
test_refresh_rereads_cached_list_and_preserves_query_from_first_page (test_review_assistant_ui.ReminderPickerTest.test_refresh_rereads_cached_list_and_preserves_query_from_first_page) ... ok
|
||||
test_same_name_rows_keep_exact_identity_and_validate_selected_one (test_review_assistant_ui.ReminderPickerTest.test_same_name_rows_keep_exact_identity_and_validate_selected_one) ... ok
|
||||
test_stale_list_and_late_validation_after_cancel_are_ignored (test_review_assistant_ui.ReminderPickerTest.test_stale_list_and_late_validation_after_cancel_are_ignored) ... ok
|
||||
test_stale_validation_result_cannot_accept_after_a_newer_request (test_review_assistant_ui.ReminderPickerTest.test_stale_validation_result_cannot_accept_after_a_newer_request) ... ok
|
||||
test_unmapped_contact_is_visible_but_cannot_be_accepted (test_review_assistant_ui.ReminderPickerTest.test_unmapped_contact_is_visible_but_cannot_be_accepted) ... ok
|
||||
test_wrong_account_cannot_load_or_accept_and_retry_stays_available (test_review_assistant_ui.ReminderPickerTest.test_wrong_account_cannot_load_or_accept_and_retry_stays_available) ... ok
|
||||
test_only_explicit_refresh_reads_notification_summary (test_review_assistant_ui.ReminderRefreshTest.test_only_explicit_refresh_reads_notification_summary) ... ok
|
||||
test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it (test_review_assistant_ui.ReminderRefreshTest.test_refresh_warns_for_invalid_saved_m_without_rewriting_or_disabling_it) ... ok
|
||||
test_warning_for_old_target_is_not_applied_to_new_target_or_other_account (test_review_assistant_ui.ReminderRefreshTest.test_warning_for_old_target_is_not_applied_to_new_target_or_other_account) ... ok
|
||||
test_default_disabled_and_cannot_enable_without_recipient (test_review_assistant_ui.ReminderSettingsTest.test_default_disabled_and_cannot_enable_without_recipient) ... ok
|
||||
test_enable_revalidates_target_and_does_not_change_other_accounts (test_review_assistant_ui.ReminderSettingsTest.test_enable_revalidates_target_and_does_not_change_other_accounts) ... ok
|
||||
test_expected_account_mismatch_or_validation_failure_never_saves (test_review_assistant_ui.ReminderSettingsTest.test_expected_account_mismatch_or_validation_failure_never_saves) ... ok
|
||||
test_explicit_disable_only_needs_current_account_not_deleted_contact (test_review_assistant_ui.ReminderSettingsTest.test_explicit_disable_only_needs_current_account_not_deleted_contact) ... ok
|
||||
test_persist_failure_does_not_claim_config_is_enabled (test_review_assistant_ui.ReminderSettingsTest.test_persist_failure_does_not_claim_config_is_enabled) ... ok
|
||||
test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat (test_review_assistant_ui.ReminderSettingsTest.test_rejected_legacy_m_recipient_is_not_silently_replaced_by_s_chat) ... ok
|
||||
test_replacing_an_enabled_contact_requires_explicit_reenable (test_review_assistant_ui.ReminderSettingsTest.test_replacing_an_enabled_contact_requires_explicit_reenable) ... ok
|
||||
test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure (test_review_assistant_ui.ReminderSettingsTest.test_runtime_save_preserves_other_account_mapping_and_rolls_back_failure) ... ok
|
||||
test_s_recipient_round_trip_preserves_raw_id_and_customer_kind (test_review_assistant_ui.ReminderSettingsTest.test_s_recipient_round_trip_preserves_raw_id_and_customer_kind) ... ok
|
||||
test_selection_persists_exact_verified_recipient_and_stays_off (test_review_assistant_ui.ReminderSettingsTest.test_selection_persists_exact_verified_recipient_and_stays_off) ... ok
|
||||
test_snapshot_does_not_probe_scan_or_query_databases (test_review_assistant_ui.ReminderSettingsTest.test_snapshot_does_not_probe_scan_or_query_databases) ... ok
|
||||
test_stale_async_reply_and_shutdown_do_not_save (test_review_assistant_ui.ReminderSettingsTest.test_stale_async_reply_and_shutdown_do_not_save) ... ok
|
||||
test_successful_reselection_clears_matching_warning_without_enabling (test_review_assistant_ui.ReminderSettingsTest.test_successful_reselection_clears_matching_warning_without_enabling) ... ok
|
||||
test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle (test_review_assistant_ui.ReminderWebTest.test_setting_panel_disables_until_verified_and_uses_exact_account_for_toggle) ... ok
|
||||
test_all_view_keeps_sendable_and_directory_groups_separate (test_review_assistant_contact_order.ContactOrderingTest.test_all_view_keeps_sendable_and_directory_groups_separate) ... ok
|
||||
test_chinese_names_and_decorative_prefixes_sort_consistently (test_review_assistant_contact_order.ContactOrderingTest.test_chinese_names_and_decorative_prefixes_sort_consistently) ... ok
|
||||
test_invalid_filters_fail_without_reading_other_data (test_review_assistant_contact_order.ContactOrderingTest.test_invalid_filters_fail_without_reading_other_data) ... ok
|
||||
test_numeric_nickname_and_duplicate_name_order_is_stable (test_review_assistant_contact_order.ContactOrderingTest.test_numeric_nickname_and_duplicate_name_order_is_stable) ... ok
|
||||
test_recent_sort_happens_before_page_slice (test_review_assistant_contact_order.ContactOrderingTest.test_recent_sort_happens_before_page_slice) ... ok
|
||||
test_state_filter_counts_include_full_search_results_before_paging (test_review_assistant_contact_order.ContactOrderingTest.test_state_filter_counts_include_full_search_results_before_paging) ... ok
|
||||
test_unknown_names_are_last_for_name_sort (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_are_last_for_name_sort) ... ok
|
||||
test_unknown_names_explicitly_show_identity_without_inventing_a_name (test_review_assistant_contact_order.ContactOrderingTest.test_unknown_names_explicitly_show_identity_without_inventing_a_name) ... ok
|
||||
test_named_saved_recipient_keeps_name_and_full_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_named_saved_recipient_keeps_name_and_full_identity) ... ok
|
||||
test_old_generic_saved_name_becomes_explicit_unknown_identity (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_old_generic_saved_name_becomes_explicit_unknown_identity) ... ok
|
||||
test_reselecting_same_recipient_still_names_the_saved_contact (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_reselecting_same_recipient_still_names_the_saved_contact) ... ok
|
||||
test_s_identity_displays_peer_for_both_endpoint_orders (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_s_identity_displays_peer_for_both_endpoint_orders) ... ok
|
||||
test_save_keeps_verified_identity_and_clear_feedback (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_save_keeps_verified_identity_and_clear_feedback) ... ok
|
||||
test_state_uses_current_account_mapping_and_never_rewrites_old_m (test_review_assistant_contact_order.RecipientStateFeedbackTest.test_state_uses_current_account_mapping_and_never_rewrites_old_m) ... ok
|
||||
test_compact_screen_keeps_footer_visible_and_details_scrollable (test_review_assistant_picker_layout.PickerLayoutTest.test_compact_screen_keeps_footer_visible_and_details_scrollable) ... ok
|
||||
test_configured_recipient_mark_survives_selection_and_group_change (test_review_assistant_picker_layout.PickerLayoutTest.test_configured_recipient_mark_survives_selection_and_group_change) ... ok
|
||||
test_confirmation_validates_exact_selected_identity (test_review_assistant_picker_layout.PickerLayoutTest.test_confirmation_validates_exact_selected_identity) ... ok
|
||||
test_defaults_to_all_customers_and_queries_backend_sort_before_pagination (test_review_assistant_picker_layout.PickerLayoutTest.test_defaults_to_all_customers_and_queries_backend_sort_before_pagination) ... ok
|
||||
test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm (test_review_assistant_picker_layout.PickerLayoutTest.test_directory_click_previews_complete_identity_and_reason_but_cannot_confirm) ... ok
|
||||
test_named_selection_is_blue_and_checked_after_focus_moves (test_review_assistant_picker_layout.PickerLayoutTest.test_named_selection_is_blue_and_checked_after_focus_moves) ... ok
|
||||
test_no_sendable_matches_shows_how_to_open_directory (test_review_assistant_picker_layout.PickerLayoutTest.test_no_sendable_matches_shows_how_to_open_directory) ... ok
|
||||
test_pending_validation_blocks_navigation_and_cancel_ignores_late_result (test_review_assistant_picker_layout.PickerLayoutTest.test_pending_validation_blocks_navigation_and_cancel_ignores_late_result) ... ok
|
||||
test_query_change_invalidates_inflight_list_before_debounce (test_review_assistant_picker_layout.PickerLayoutTest.test_query_change_invalidates_inflight_list_before_debounce) ... ok
|
||||
test_refresh_clears_old_selection_and_preserves_search_and_sort (test_review_assistant_picker_layout.PickerLayoutTest.test_refresh_clears_old_selection_and_preserves_search_and_sort) ... ok
|
||||
test_s_details_show_customer_peer_and_confirmation_preserves_raw_id (test_review_assistant_picker_layout.PickerLayoutTest.test_s_details_show_customer_peer_and_confirmation_preserves_raw_id) ... ok
|
||||
test_same_name_rows_have_distinct_tail_numbers_before_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_same_name_rows_have_distinct_tail_numbers_before_selection) ... ok
|
||||
test_stale_validation_and_list_from_other_account_are_ignored (test_review_assistant_picker_layout.PickerLayoutTest.test_stale_validation_and_list_from_other_account_are_ignored) ... ok
|
||||
test_unknown_name_is_explicit_and_gets_same_visible_selection (test_review_assistant_picker_layout.PickerLayoutTest.test_unknown_name_is_explicit_and_gets_same_visible_selection) ... ok
|
||||
test_wrong_account_or_returned_identity_never_accepts (test_review_assistant_picker_layout.PickerLayoutTest.test_wrong_account_or_returned_identity_never_accepts) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 90 tests in 8.481s
|
||||
|
||||
OK
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
python3 -c 'import json;from pathlib import Path;p=json.loads(Path("order-release-plan.json").read_text());assert p["schemaMigration"] is False'
|
||||
python3 order_server_guard.py baseline
|
||||
test ! -e source-before
|
||||
test ! -e preflight-complete
|
||||
if docker image inspect zyt/wecom-admin:before-order-hint-20260922 >/dev/null 2>&1; then echo 'Refuse to replace existing rollback tag' >&2; exit 1; fi
|
||||
mkdir -m 700 source-before
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import shutil, json
|
||||
r = Path('/home/ps/order-hint-20260922')
|
||||
p = json.loads((r / 'order-release-plan.json').read_text())
|
||||
for name in p['backendFiles']:
|
||||
shutil.copy2(Path('/opt/im-admin/wechat_rpa') / name, r / 'source-before' / name)
|
||||
shutil.copy2('/opt/im-admin/deploy/im-admin/compose.yaml', r / 'source-before/compose.yaml')
|
||||
PY
|
||||
docker tag zyt/wecom-admin:current zyt/wecom-admin:before-order-hint-20260922
|
||||
docker image inspect zyt/wecom-admin:current --format '{{.Id}}' > image-before.txt
|
||||
printf '%s\n' ready > preflight-complete
|
||||
echo "preflight complete; rollback image tagged before-order-hint-20260922 ($(cat image-before.txt))"
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
test -f preflight-complete
|
||||
test ! -e candidate-passed
|
||||
python3 order_server_guard.py baseline
|
||||
test "$(docker image inspect zyt/wecom-admin:before-order-hint-20260922 --format '{{.Id}}')" = "$(cat image-before.txt)"
|
||||
# Consistent read-only snapshot of the live database plus the encryption key; no schema change, backup is a safety net.
|
||||
docker exec -i im-admin-api-1 python - <<'PY' > backup-order.json
|
||||
from pathlib import Path
|
||||
import sqlite3, shutil, os, json
|
||||
folder = Path('/data/backups/order-hint-20260922'); folder.mkdir(mode=0o700)
|
||||
source = sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30)
|
||||
backup = sqlite3.connect(folder / 'backend.db')
|
||||
try:
|
||||
source.backup(backup, pages=0)
|
||||
finally:
|
||||
backup.close(); source.close()
|
||||
with sqlite3.connect('file:' + str(folder / 'backend.db') + '?mode=ro', uri=True) as check:
|
||||
assert check.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
os.chmod(folder / 'backend.db', 0o600)
|
||||
keys = list(Path('/data').glob('*.key')); assert keys, 'Encryption key backup missing'
|
||||
for p in keys:
|
||||
shutil.copy2(p, folder / p.name); os.chmod(folder / p.name, 0o600)
|
||||
print(json.dumps({'backup': str(folder), 'quick_check': 'ok', 'bytes': (folder / 'backend.db').stat().st_size, 'keyCount': len(keys)}))
|
||||
PY
|
||||
docker build --network=none --pull=false -f Dockerfile.order-overlay -t zyt/wecom-admin:order-hint-20260922 . > candidate-build.log 2>&1
|
||||
mapfile -t modules < <(python3 -c 'import json;print("\n".join(json.load(open("order-release-plan.json"))["serverTestModules"]))')
|
||||
test "${#modules[@]}" -gt 0
|
||||
docker run --rm --network=none --read-only --tmpfs /tmp:size=512m,mode=1777 --tmpfs /data:size=256m,mode=1777 \
|
||||
-v "$release/tests:/order-tests:ro" -e PYTHONPATH=/order-tests:/app/wechat_rpa \
|
||||
zyt/wecom-admin:order-hint-20260922 python -X utf8 -B -m unittest "${modules[@]}" -q > candidate-tests.log 2>&1
|
||||
tail -n 3 candidate-tests.log
|
||||
python3 order_server_guard.py candidate
|
||||
printf '%s\n' passed > candidate-passed
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
test -f candidate-passed
|
||||
test -f backup-order.json
|
||||
python3 order_server_guard.py baseline
|
||||
cd /opt/im-admin/deploy/im-admin
|
||||
docker compose config --quiet
|
||||
rollback_on_error() { rc=$?; trap - ERR; bash "$release/rollback-order.sh"; exit "$rc"; }
|
||||
trap rollback_on_error ERR
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import json, hashlib, os
|
||||
r = Path('/home/ps/order-hint-20260922'); target = Path('/opt/im-admin')
|
||||
reference = (target / 'wechat_rpa/archive_api.py').stat().st_mode & 0o777
|
||||
for row in json.loads((r / 'order-manifest.json').read_text()):
|
||||
if not row['path'].startswith('wechat_rpa/'):
|
||||
continue
|
||||
p = (target / row['path']).resolve(); assert p.is_relative_to(target)
|
||||
data = (r / 'payload' / row['path']).read_bytes(); assert hashlib.sha256(data).hexdigest() == row['sha256']
|
||||
tmp = p.with_name(p.name + '.order-mcp.tmp'); assert not tmp.exists()
|
||||
with tmp.open('xb') as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, p.stat().st_mode & 0o777 if p.exists() else reference); os.replace(tmp, p)
|
||||
PY
|
||||
docker compose stop -t 190 knowledge-worker
|
||||
docker compose stop -t 65 gateway
|
||||
docker tag zyt/wecom-admin:order-hint-20260922 zyt/wecom-admin:current
|
||||
docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker
|
||||
bash "$release/04-order-verify.sh"
|
||||
trap - ERR
|
||||
printf '%s\n' 'Order MCP proxy overlay deployed and verified.'
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
python3 order_server_guard.py deployed > deployed-order-verification.json
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18766/api/v2/health
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18770/health
|
||||
docker exec -i im-admin-api-1 python - <<'PY'
|
||||
import sqlite3, json
|
||||
with sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30) as c:
|
||||
assert c.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
print(json.dumps({'databaseQuickCheck': 'ok', 'patientDataRead': False}))
|
||||
PY
|
||||
cat deployed-order-verification.json
|
||||
@@ -0,0 +1,4 @@
|
||||
ARG BASE_IMAGE=zyt/wecom-admin:before-order-hint-20260922
|
||||
FROM ${BASE_IMAGE}
|
||||
COPY --chown=app:app payload/wechat_rpa/archive_api.py /app/wechat_rpa/archive_api.py
|
||||
WORKDIR /app/wechat_rpa
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"path": "wechat_rpa/archive_api.py",
|
||||
"sha256": "fe789f749adb2b7aa7cef1551e76fc1fe3ecb967b4be192d45fad6571d0cf74f",
|
||||
"bytes": 62730
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_order_api.py",
|
||||
"sha256": "2b65a6eadac728603a45bf088d977e012c4a565b02ce8b878313d1b0027756e4",
|
||||
"bytes": 18611
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_patient_client.py",
|
||||
"sha256": "a3801fb7a69628aa4c9f396e2348236296b2306568d11cc04b95ff7aa7ff6fd3",
|
||||
"bytes": 4968
|
||||
},
|
||||
{
|
||||
"path": "tests/test_archive_api.py",
|
||||
"sha256": "9a9a59945a0a0e2c082ef1d2fe7800c269041469132e336e8766edc0f224ed06",
|
||||
"bytes": 51682
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"release": "order-hint-20260922",
|
||||
"candidateRoot": "C:/kefu/wechat_rpa",
|
||||
"windowsRoot": "C:/wechat_rpa",
|
||||
"backendFiles": [
|
||||
"archive_api.py"
|
||||
],
|
||||
"newBackendFiles": [],
|
||||
"serverTestModules": [
|
||||
"test_zyt_order_api",
|
||||
"test_zyt_patient_client",
|
||||
"test_archive_api"
|
||||
],
|
||||
"schemaMigration": false,
|
||||
"notes": "Zero-order hint wording only: tell the customer no order was found and verify manually; never ask for an order number."
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
"""Read-only baseline / candidate / deployed verification. Prints hashes and status only."""
|
||||
from pathlib import Path
|
||||
import argparse, hashlib, json, subprocess, urllib.request, urllib.error
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('mode', choices=['baseline', 'candidate', 'deployed'])
|
||||
args = parser.parse_args()
|
||||
RELEASE = 'order-hint-20260922'
|
||||
folder = Path(__file__).resolve().parent
|
||||
project = Path('/opt/im-admin')
|
||||
base = json.loads((folder / 'server-baseline-order.json').read_text())
|
||||
manifest = json.loads((folder / 'order-manifest.json').read_text())
|
||||
containers = ['im-admin-api-1', 'im-admin-gateway-1', 'im-admin-knowledge-worker-1']
|
||||
image = lambda ref: subprocess.check_output(['docker', 'image', 'inspect', ref, '--format', '{{.Id}}'], text=True).strip()
|
||||
sha = lambda data: hashlib.sha256(data).hexdigest()
|
||||
|
||||
# Files that must match on the host and inside the running container.
|
||||
expected = dict(base['expected'])
|
||||
if args.mode != 'baseline':
|
||||
for row in manifest:
|
||||
if row['path'].startswith('wechat_rpa/'):
|
||||
expected[Path(row['path']).name] = row['sha256']
|
||||
|
||||
# The payload itself must be intact.
|
||||
for row in manifest:
|
||||
path = folder / ('payload/' + row['path'] if row['path'].startswith('wechat_rpa/') else row['path'])
|
||||
assert path.resolve().is_relative_to(folder.resolve())
|
||||
assert path.stat().st_size == row['bytes'] and sha(path.read_bytes()) == row['sha256'], row['path']
|
||||
|
||||
current = image('zyt/wecom-admin:current')
|
||||
if args.mode == 'baseline':
|
||||
# Code drift is the real signal; the image id is recorded, not assumed.
|
||||
for container in containers:
|
||||
actual = subprocess.check_output(['docker', 'inspect', container, '--format', '{{.Image}}'], text=True).strip()
|
||||
assert actual == current, 'Running container is not on zyt/wecom-admin:current: ' + container
|
||||
for name in base.get('must_not_exist', []):
|
||||
assert not (project / 'wechat_rpa' / name).exists(), 'Unexpected existing file: ' + name
|
||||
|
||||
if args.mode != 'candidate':
|
||||
for name, wanted in expected.items():
|
||||
assert sha((project / 'wechat_rpa' / name).read_bytes()) == wanted, 'Host drift: ' + name
|
||||
code = ('from pathlib import Path;import hashlib,json,sys;names=json.load(sys.stdin);'
|
||||
'print(json.dumps({n:hashlib.sha256((Path("/app/wechat_rpa")/n).read_bytes()).hexdigest() for n in names}))')
|
||||
actual = json.loads(subprocess.check_output(
|
||||
['docker', 'exec', '-i', 'im-admin-api-1', 'python', '-c', code], input=json.dumps(list(expected)).encode()))
|
||||
assert actual == expected, 'Container code differs from expected'
|
||||
|
||||
if args.mode == 'deployed':
|
||||
wanted = image('zyt/wecom-admin:' + RELEASE)
|
||||
assert current == wanted
|
||||
for name in containers:
|
||||
raw = json.loads(subprocess.check_output(['docker', 'inspect', name]))[0]
|
||||
assert raw['Image'] == wanted and raw['State']['Running'] and raw['RestartCount'] == 0, name
|
||||
assert raw['State'].get('Health', {}).get('Status', 'not_configured') in ('healthy', 'not_configured'), name
|
||||
for url in ['http://127.0.0.1:18766/api/v2/health', 'http://127.0.0.1:18770/health']:
|
||||
with urllib.request.urlopen(url, timeout=15) as response:
|
||||
assert response.status == 200
|
||||
# New order routes must exist and must reject anonymous reads. No real patient is queried.
|
||||
for path in ['/api/v2/archive/desktop/patient-orders/summary', '/api/v2/archive/desktop/patient-orders',
|
||||
'/api/v2/archive/desktop/patient-orders/1/tracking']:
|
||||
try:
|
||||
urllib.request.urlopen('http://127.0.0.1:18766' + path
|
||||
+ '?external_account_id=synthetic&conversation_external_id=synthetic', timeout=15)
|
||||
except urllib.error.HTTPError as exc:
|
||||
assert exc.code in (401, 403), (path, exc.code)
|
||||
else:
|
||||
raise AssertionError('Order API accessible without authentication: ' + path)
|
||||
|
||||
print(json.dumps({'mode': args.mode, 'image': current, 'files': len(expected), 'status': 'passed', 'patientDataRead': False}))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
"""Build the server bundle locally: manifest + tar.gz. No upload, no deployment."""
|
||||
from pathlib import Path
|
||||
import hashlib, json, shutil, tarfile
|
||||
|
||||
folder = Path(__file__).resolve().parent
|
||||
plan = json.loads((folder / 'order-release-plan.json').read_text(encoding='utf-8'))
|
||||
base = json.loads((folder / 'server-baseline-order.json').read_text(encoding='utf-8'))
|
||||
assert plan['schemaMigration'] is False
|
||||
payload = folder / 'payload/wechat_rpa'
|
||||
production = list(plan['backendFiles']) + list(plan['newBackendFiles'])
|
||||
assert sorted(p.name for p in payload.iterdir() if p.is_file()) == sorted(production), 'payload does not match plan'
|
||||
for name in plan['backendFiles']:
|
||||
before = folder / 'before-backend' / name
|
||||
assert hashlib.sha256(before.read_bytes()).hexdigest() == base['expected'][name], 'Server baseline differs: ' + name
|
||||
manifest = []
|
||||
for name in sorted(production):
|
||||
data = (payload / name).read_bytes(); compile(data, name, 'exec')
|
||||
manifest.append({'path': 'wechat_rpa/' + name, 'sha256': hashlib.sha256(data).hexdigest(), 'bytes': len(data)})
|
||||
for name in [m + '.py' for m in plan['serverTestModules']]:
|
||||
data = (folder / 'tests' / name).read_bytes(); compile(data, name, 'exec')
|
||||
manifest.append({'path': 'tests/' + name, 'sha256': hashlib.sha256(data).hexdigest(), 'bytes': len(data)})
|
||||
(folder / 'order-manifest.json').write_text(json.dumps(manifest, indent=2), encoding='utf-8')
|
||||
bundle = folder / 'server-bundle'
|
||||
assert not bundle.exists(), 'Refusing to overwrite previous bundle'
|
||||
bundle.mkdir()
|
||||
ignore = shutil.ignore_patterns('__pycache__', '*.pyc')
|
||||
shutil.copytree(folder / 'payload', bundle / 'payload', ignore=ignore)
|
||||
shutil.copytree(folder / 'tests', bundle / 'tests', ignore=ignore)
|
||||
for name in ['server-baseline-order.json', 'order-release-plan.json', 'order-manifest.json', 'Dockerfile.order-overlay',
|
||||
'order_server_guard.py', '01-order-preflight.sh', '02-order-backup-build.sh', '03-order-deploy.sh',
|
||||
'04-order-verify.sh', 'rollback-order.sh']:
|
||||
data = (folder / name).read_bytes().replace(b'\r\n', b'\n')
|
||||
(bundle / name).write_bytes(data)
|
||||
archive = folder / 'order-server-bundle.tar.gz'
|
||||
assert not archive.exists()
|
||||
with tarfile.open(archive, 'x:gz') as tf:
|
||||
for p in sorted(bundle.rglob('*')):
|
||||
if p.is_file():
|
||||
arc = p.relative_to(bundle).as_posix(); assert not arc.startswith(('/', '..'))
|
||||
tf.add(p, arcname=arc, recursive=False)
|
||||
print(json.dumps({'archive': str(archive), 'bytes': archive.stat().st_size,
|
||||
'sha256': hashlib.sha256(archive.read_bytes()).hexdigest(),
|
||||
'productionFiles': production, 'uploaded': False}, ensure_ascii=False, indent=1))
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd /opt/im-admin/deploy/im-admin
|
||||
test -d "$release/source-before"
|
||||
test "$(docker image inspect zyt/wecom-admin:before-order-hint-20260922 --format '{{.Id}}')" = "$(cat "$release/image-before.txt")"
|
||||
docker compose stop -t 190 knowledge-worker
|
||||
docker compose stop -t 65 gateway
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import hashlib, json, os
|
||||
r = Path('/home/ps/order-hint-20260922')
|
||||
base = json.loads((r / 'server-baseline-order.json').read_text())
|
||||
plan = json.loads((r / 'order-release-plan.json').read_text())
|
||||
for name in plan['backendFiles']:
|
||||
data = (r / 'source-before' / name).read_bytes(); assert hashlib.sha256(data).hexdigest() == base['expected'][name]
|
||||
target = Path('/opt/im-admin/wechat_rpa') / name; tmp = target.with_name(name + '.rollback-order.tmp')
|
||||
with tmp.open('xb') as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, target.stat().st_mode & 0o777); os.replace(tmp, target)
|
||||
for name in plan['newBackendFiles']:
|
||||
target = Path('/opt/im-admin/wechat_rpa') / name
|
||||
if target.exists():
|
||||
target.unlink()
|
||||
PY
|
||||
docker tag zyt/wecom-admin:before-order-hint-20260922 zyt/wecom-admin:current
|
||||
docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18766/api/v2/health
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18770/health
|
||||
printf '%s\n' 'Previous image and source files restored; live database retained (no schema migration).'
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"host": "192.168.110.111",
|
||||
"user": "ps",
|
||||
"project": "/opt/im-admin",
|
||||
"compose": "/opt/im-admin/deploy/im-admin",
|
||||
"image_hint": "sha256:6cb6a2d5f7ba94b11b3cf478a0937dc1aeded8d8fa2b4ba9d903cccfbf326815",
|
||||
"checked_at": "2026-09-22",
|
||||
"source": "deployed payload of order-mcp-20260922",
|
||||
"expected": {
|
||||
"admin_backend.py": "977c524e10db2df8fafba2058dc30e5837521de604f2723a7db4b5e2ba5c3107",
|
||||
"archive_api.py": "0acb73850380a9f39e470aead6e92a124de63e4a1f0a8bb9a5d3f02ebfc84079",
|
||||
"zyt_order_client.py": "e56d6da4ba06006a752261a5ac167b4d885defed2ee5702ffd0c9ab252929a1a",
|
||||
"zyt_patient_client.py": "3462350e066314e62ba99ea79aea8725da4e1e236b71a4869f595b3e259b85ab"
|
||||
},
|
||||
"must_not_exist": []
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
python3 -c 'import json;from pathlib import Path;p=json.loads(Path("order-release-plan.json").read_text());assert p["schemaMigration"] is False'
|
||||
python3 order_server_guard.py baseline
|
||||
test ! -e source-before
|
||||
test ! -e preflight-complete
|
||||
if docker image inspect zyt/wecom-admin:before-order-hint-20260922 >/dev/null 2>&1; then echo 'Refuse to replace existing rollback tag' >&2; exit 1; fi
|
||||
mkdir -m 700 source-before
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import shutil, json
|
||||
r = Path('/home/ps/order-hint-20260922')
|
||||
p = json.loads((r / 'order-release-plan.json').read_text())
|
||||
for name in p['backendFiles']:
|
||||
shutil.copy2(Path('/opt/im-admin/wechat_rpa') / name, r / 'source-before' / name)
|
||||
shutil.copy2('/opt/im-admin/deploy/im-admin/compose.yaml', r / 'source-before/compose.yaml')
|
||||
PY
|
||||
docker tag zyt/wecom-admin:current zyt/wecom-admin:before-order-hint-20260922
|
||||
docker image inspect zyt/wecom-admin:current --format '{{.Id}}' > image-before.txt
|
||||
printf '%s\n' ready > preflight-complete
|
||||
echo "preflight complete; rollback image tagged before-order-hint-20260922 ($(cat image-before.txt))"
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
test -f preflight-complete
|
||||
test ! -e candidate-passed
|
||||
python3 order_server_guard.py baseline
|
||||
test "$(docker image inspect zyt/wecom-admin:before-order-hint-20260922 --format '{{.Id}}')" = "$(cat image-before.txt)"
|
||||
# Consistent read-only snapshot of the live database plus the encryption key; no schema change, backup is a safety net.
|
||||
docker exec -i im-admin-api-1 python - <<'PY' > backup-order.json
|
||||
from pathlib import Path
|
||||
import sqlite3, shutil, os, json
|
||||
folder = Path('/data/backups/order-hint-20260922'); folder.mkdir(mode=0o700)
|
||||
source = sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30)
|
||||
backup = sqlite3.connect(folder / 'backend.db')
|
||||
try:
|
||||
source.backup(backup, pages=0)
|
||||
finally:
|
||||
backup.close(); source.close()
|
||||
with sqlite3.connect('file:' + str(folder / 'backend.db') + '?mode=ro', uri=True) as check:
|
||||
assert check.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
os.chmod(folder / 'backend.db', 0o600)
|
||||
keys = list(Path('/data').glob('*.key')); assert keys, 'Encryption key backup missing'
|
||||
for p in keys:
|
||||
shutil.copy2(p, folder / p.name); os.chmod(folder / p.name, 0o600)
|
||||
print(json.dumps({'backup': str(folder), 'quick_check': 'ok', 'bytes': (folder / 'backend.db').stat().st_size, 'keyCount': len(keys)}))
|
||||
PY
|
||||
docker build --network=none --pull=false -f Dockerfile.order-overlay -t zyt/wecom-admin:order-hint-20260922 . > candidate-build.log 2>&1
|
||||
mapfile -t modules < <(python3 -c 'import json;print("\n".join(json.load(open("order-release-plan.json"))["serverTestModules"]))')
|
||||
test "${#modules[@]}" -gt 0
|
||||
docker run --rm --network=none --read-only --tmpfs /tmp:size=512m,mode=1777 --tmpfs /data:size=256m,mode=1777 \
|
||||
-v "$release/tests:/order-tests:ro" -e PYTHONPATH=/order-tests:/app/wechat_rpa \
|
||||
zyt/wecom-admin:order-hint-20260922 python -X utf8 -B -m unittest "${modules[@]}" -q > candidate-tests.log 2>&1
|
||||
tail -n 3 candidate-tests.log
|
||||
python3 order_server_guard.py candidate
|
||||
printf '%s\n' passed > candidate-passed
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
test -f candidate-passed
|
||||
test -f backup-order.json
|
||||
python3 order_server_guard.py baseline
|
||||
cd /opt/im-admin/deploy/im-admin
|
||||
docker compose config --quiet
|
||||
rollback_on_error() { rc=$?; trap - ERR; bash "$release/rollback-order.sh"; exit "$rc"; }
|
||||
trap rollback_on_error ERR
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import json, hashlib, os
|
||||
r = Path('/home/ps/order-hint-20260922'); target = Path('/opt/im-admin')
|
||||
reference = (target / 'wechat_rpa/archive_api.py').stat().st_mode & 0o777
|
||||
for row in json.loads((r / 'order-manifest.json').read_text()):
|
||||
if not row['path'].startswith('wechat_rpa/'):
|
||||
continue
|
||||
p = (target / row['path']).resolve(); assert p.is_relative_to(target)
|
||||
data = (r / 'payload' / row['path']).read_bytes(); assert hashlib.sha256(data).hexdigest() == row['sha256']
|
||||
tmp = p.with_name(p.name + '.order-mcp.tmp'); assert not tmp.exists()
|
||||
with tmp.open('xb') as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, p.stat().st_mode & 0o777 if p.exists() else reference); os.replace(tmp, p)
|
||||
PY
|
||||
docker compose stop -t 190 knowledge-worker
|
||||
docker compose stop -t 65 gateway
|
||||
docker tag zyt/wecom-admin:order-hint-20260922 zyt/wecom-admin:current
|
||||
docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker
|
||||
bash "$release/04-order-verify.sh"
|
||||
trap - ERR
|
||||
printf '%s\n' 'Order MCP proxy overlay deployed and verified.'
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd "$release"
|
||||
python3 order_server_guard.py deployed > deployed-order-verification.json
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18766/api/v2/health
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18770/health
|
||||
docker exec -i im-admin-api-1 python - <<'PY'
|
||||
import sqlite3, json
|
||||
with sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30) as c:
|
||||
assert c.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
print(json.dumps({'databaseQuickCheck': 'ok', 'patientDataRead': False}))
|
||||
PY
|
||||
cat deployed-order-verification.json
|
||||
@@ -0,0 +1,4 @@
|
||||
ARG BASE_IMAGE=zyt/wecom-admin:before-order-hint-20260922
|
||||
FROM ${BASE_IMAGE}
|
||||
COPY --chown=app:app payload/wechat_rpa/archive_api.py /app/wechat_rpa/archive_api.py
|
||||
WORKDIR /app/wechat_rpa
|
||||
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"path": "wechat_rpa/archive_api.py",
|
||||
"sha256": "fe789f749adb2b7aa7cef1551e76fc1fe3ecb967b4be192d45fad6571d0cf74f",
|
||||
"bytes": 62730
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_order_api.py",
|
||||
"sha256": "2b65a6eadac728603a45bf088d977e012c4a565b02ce8b878313d1b0027756e4",
|
||||
"bytes": 18611
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_patient_client.py",
|
||||
"sha256": "a3801fb7a69628aa4c9f396e2348236296b2306568d11cc04b95ff7aa7ff6fd3",
|
||||
"bytes": 4968
|
||||
},
|
||||
{
|
||||
"path": "tests/test_archive_api.py",
|
||||
"sha256": "9a9a59945a0a0e2c082ef1d2fe7800c269041469132e336e8766edc0f224ed06",
|
||||
"bytes": 51682
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"release": "order-hint-20260922",
|
||||
"candidateRoot": "C:/kefu/wechat_rpa",
|
||||
"windowsRoot": "C:/wechat_rpa",
|
||||
"backendFiles": [
|
||||
"archive_api.py"
|
||||
],
|
||||
"newBackendFiles": [],
|
||||
"serverTestModules": [
|
||||
"test_zyt_order_api",
|
||||
"test_zyt_patient_client",
|
||||
"test_archive_api"
|
||||
],
|
||||
"schemaMigration": false,
|
||||
"notes": "Zero-order hint wording only: tell the customer no order was found and verify manually; never ask for an order number."
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
"""Read-only baseline / candidate / deployed verification. Prints hashes and status only."""
|
||||
from pathlib import Path
|
||||
import argparse, hashlib, json, subprocess, urllib.request, urllib.error
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('mode', choices=['baseline', 'candidate', 'deployed'])
|
||||
args = parser.parse_args()
|
||||
RELEASE = 'order-hint-20260922'
|
||||
folder = Path(__file__).resolve().parent
|
||||
project = Path('/opt/im-admin')
|
||||
base = json.loads((folder / 'server-baseline-order.json').read_text())
|
||||
manifest = json.loads((folder / 'order-manifest.json').read_text())
|
||||
containers = ['im-admin-api-1', 'im-admin-gateway-1', 'im-admin-knowledge-worker-1']
|
||||
image = lambda ref: subprocess.check_output(['docker', 'image', 'inspect', ref, '--format', '{{.Id}}'], text=True).strip()
|
||||
sha = lambda data: hashlib.sha256(data).hexdigest()
|
||||
|
||||
# Files that must match on the host and inside the running container.
|
||||
expected = dict(base['expected'])
|
||||
if args.mode != 'baseline':
|
||||
for row in manifest:
|
||||
if row['path'].startswith('wechat_rpa/'):
|
||||
expected[Path(row['path']).name] = row['sha256']
|
||||
|
||||
# The payload itself must be intact.
|
||||
for row in manifest:
|
||||
path = folder / ('payload/' + row['path'] if row['path'].startswith('wechat_rpa/') else row['path'])
|
||||
assert path.resolve().is_relative_to(folder.resolve())
|
||||
assert path.stat().st_size == row['bytes'] and sha(path.read_bytes()) == row['sha256'], row['path']
|
||||
|
||||
current = image('zyt/wecom-admin:current')
|
||||
if args.mode == 'baseline':
|
||||
# Code drift is the real signal; the image id is recorded, not assumed.
|
||||
for container in containers:
|
||||
actual = subprocess.check_output(['docker', 'inspect', container, '--format', '{{.Image}}'], text=True).strip()
|
||||
assert actual == current, 'Running container is not on zyt/wecom-admin:current: ' + container
|
||||
for name in base.get('must_not_exist', []):
|
||||
assert not (project / 'wechat_rpa' / name).exists(), 'Unexpected existing file: ' + name
|
||||
|
||||
if args.mode != 'candidate':
|
||||
for name, wanted in expected.items():
|
||||
assert sha((project / 'wechat_rpa' / name).read_bytes()) == wanted, 'Host drift: ' + name
|
||||
code = ('from pathlib import Path;import hashlib,json,sys;names=json.load(sys.stdin);'
|
||||
'print(json.dumps({n:hashlib.sha256((Path("/app/wechat_rpa")/n).read_bytes()).hexdigest() for n in names}))')
|
||||
actual = json.loads(subprocess.check_output(
|
||||
['docker', 'exec', '-i', 'im-admin-api-1', 'python', '-c', code], input=json.dumps(list(expected)).encode()))
|
||||
assert actual == expected, 'Container code differs from expected'
|
||||
|
||||
if args.mode == 'deployed':
|
||||
wanted = image('zyt/wecom-admin:' + RELEASE)
|
||||
assert current == wanted
|
||||
for name in containers:
|
||||
raw = json.loads(subprocess.check_output(['docker', 'inspect', name]))[0]
|
||||
assert raw['Image'] == wanted and raw['State']['Running'] and raw['RestartCount'] == 0, name
|
||||
assert raw['State'].get('Health', {}).get('Status', 'not_configured') in ('healthy', 'not_configured'), name
|
||||
for url in ['http://127.0.0.1:18766/api/v2/health', 'http://127.0.0.1:18770/health']:
|
||||
with urllib.request.urlopen(url, timeout=15) as response:
|
||||
assert response.status == 200
|
||||
# New order routes must exist and must reject anonymous reads. No real patient is queried.
|
||||
for path in ['/api/v2/archive/desktop/patient-orders/summary', '/api/v2/archive/desktop/patient-orders',
|
||||
'/api/v2/archive/desktop/patient-orders/1/tracking']:
|
||||
try:
|
||||
urllib.request.urlopen('http://127.0.0.1:18766' + path
|
||||
+ '?external_account_id=synthetic&conversation_external_id=synthetic', timeout=15)
|
||||
except urllib.error.HTTPError as exc:
|
||||
assert exc.code in (401, 403), (path, exc.code)
|
||||
else:
|
||||
raise AssertionError('Order API accessible without authentication: ' + path)
|
||||
|
||||
print(json.dumps({'mode': args.mode, 'image': current, 'files': len(expected), 'status': 'passed', 'patientDataRead': False}))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-hint-20260922
|
||||
release=/home/ps/order-hint-20260922
|
||||
cd /opt/im-admin/deploy/im-admin
|
||||
test -d "$release/source-before"
|
||||
test "$(docker image inspect zyt/wecom-admin:before-order-hint-20260922 --format '{{.Id}}')" = "$(cat "$release/image-before.txt")"
|
||||
docker compose stop -t 190 knowledge-worker
|
||||
docker compose stop -t 65 gateway
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import hashlib, json, os
|
||||
r = Path('/home/ps/order-hint-20260922')
|
||||
base = json.loads((r / 'server-baseline-order.json').read_text())
|
||||
plan = json.loads((r / 'order-release-plan.json').read_text())
|
||||
for name in plan['backendFiles']:
|
||||
data = (r / 'source-before' / name).read_bytes(); assert hashlib.sha256(data).hexdigest() == base['expected'][name]
|
||||
target = Path('/opt/im-admin/wechat_rpa') / name; tmp = target.with_name(name + '.rollback-order.tmp')
|
||||
with tmp.open('xb') as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, target.stat().st_mode & 0o777); os.replace(tmp, target)
|
||||
for name in plan['newBackendFiles']:
|
||||
target = Path('/opt/im-admin/wechat_rpa') / name
|
||||
if target.exists():
|
||||
target.unlink()
|
||||
PY
|
||||
docker tag zyt/wecom-admin:before-order-hint-20260922 zyt/wecom-admin:current
|
||||
docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18766/api/v2/health
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18770/health
|
||||
printf '%s\n' 'Previous image and source files restored; live database retained (no schema migration).'
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"host": "192.168.110.111",
|
||||
"user": "ps",
|
||||
"project": "/opt/im-admin",
|
||||
"compose": "/opt/im-admin/deploy/im-admin",
|
||||
"image_hint": "sha256:6cb6a2d5f7ba94b11b3cf478a0937dc1aeded8d8fa2b4ba9d903cccfbf326815",
|
||||
"checked_at": "2026-09-22",
|
||||
"source": "deployed payload of order-mcp-20260922",
|
||||
"expected": {
|
||||
"admin_backend.py": "977c524e10db2df8fafba2058dc30e5837521de604f2723a7db4b5e2ba5c3107",
|
||||
"archive_api.py": "0acb73850380a9f39e470aead6e92a124de63e4a1f0a8bb9a5d3f02ebfc84079",
|
||||
"zyt_order_client.py": "e56d6da4ba06006a752261a5ac167b4d885defed2ee5702ffd0c9ab252929a1a",
|
||||
"zyt_patient_client.py": "3462350e066314e62ba99ea79aea8725da4e1e236b71a4869f595b3e259b85ab"
|
||||
},
|
||||
"must_not_exist": []
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,328 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Patient-order proxy security checks using persisted conversation bindings."""
|
||||
|
||||
from unittest import TestCase, main, mock
|
||||
|
||||
import test_archive_api as archive_tests
|
||||
|
||||
|
||||
class ZytOrderApiTest(TestCase):
|
||||
# Reuse fixture helpers without inheriting and re-running the archive suite.
|
||||
setUp = archive_tests.ArchiveApiTest.setUp
|
||||
tearDown = archive_tests.ArchiveApiTest.tearDown
|
||||
login = archive_tests.ArchiveApiTest.login
|
||||
desktop_login = archive_tests.ArchiveApiTest.desktop_login
|
||||
sample_payload = staticmethod(archive_tests.ArchiveApiTest.sample_payload)
|
||||
search_zyt_patients = staticmethod(archive_tests.ArchiveApiTest.search_zyt_patients)
|
||||
|
||||
@staticmethod
|
||||
def verify_zyt(token):
|
||||
identity = archive_tests.ArchiveApiTest.verify_zyt(token)
|
||||
if token == "zyt-user-list-only":
|
||||
identity["permissions"].append("firstvisit.myPatient/orders")
|
||||
elif token != "zyt-no-patient":
|
||||
identity["permissions"] += [
|
||||
"firstvisit.myPatient/orders", "firstvisit.myPatient/orderDetail",
|
||||
"tcm.prescriptionOrder/detail", "tcm.prescriptionOrder/logisticsTrace",
|
||||
]
|
||||
return identity
|
||||
|
||||
def prepare_conversation(self, *, bind=True):
|
||||
session = self.desktop_login()
|
||||
payload = self.sample_payload()
|
||||
imported = self.client.post(
|
||||
"/api/v2/archive/desktop/imports/messages",
|
||||
headers=session["headers"], json=payload,
|
||||
)
|
||||
self.assertEqual(imported.status_code, 200, imported.text)
|
||||
params = {
|
||||
"external_account_id": payload["source_account"]["external_account_id"],
|
||||
"conversation_external_id": payload["messages"][0]["conversation"]["external_id"],
|
||||
}
|
||||
context = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-context",
|
||||
headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(context.status_code, 200, context.text)
|
||||
person_id = context.json()["person"]["id"]
|
||||
params["person_id"] = person_id
|
||||
binding = None
|
||||
if bind:
|
||||
searched = self.client.get(
|
||||
"/api/v2/archive/desktop/patients/search",
|
||||
headers=session["headers"], params={"keyword": "张三"},
|
||||
)
|
||||
self.assertEqual(searched.status_code, 200, searched.text)
|
||||
response = self.client.put(
|
||||
"/api/v2/archive/desktop/patient-binding",
|
||||
headers=session["headers"],
|
||||
json={**params, "patient_id": 9001, "diagnosis_id": 9101},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
binding = response.json()["binding"]
|
||||
return session, params, binding
|
||||
|
||||
@staticmethod
|
||||
def sample_order(**overrides):
|
||||
return {
|
||||
"id": 321, "order_no": "ZYT202609220321", "diagnosis_id": 9101,
|
||||
"create_time": "2026-09-22 10:20:00", "fulfillment_status": 5,
|
||||
"prescription_audit_status": 1, "payment_slip_audit_status": 1,
|
||||
"express_company": "顺丰", "tracking_number": "SF1234567899",
|
||||
"recipient_name": "张三", "recipient_phone": "13800138000",
|
||||
"recipient_address": "不应向模型公开的住址", "prescription": {"private": True},
|
||||
**overrides,
|
||||
}
|
||||
|
||||
def order_paths(self):
|
||||
return (
|
||||
"/api/v2/archive/desktop/patient-orders",
|
||||
"/api/v2/archive/desktop/patient-orders/321",
|
||||
"/api/v2/archive/desktop/patient-orders/321/tracking",
|
||||
"/api/v2/archive/desktop/patient-orders/321/audit-status",
|
||||
)
|
||||
|
||||
def test_unbound_conversation_never_queries_orders(self):
|
||||
session, params, _ = self.prepare_conversation(bind=False)
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_required")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_order_from_other_diagnosis_is_rejected_before_tracking(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order(diagnosis_id=9999)
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 404, response.text)
|
||||
self.assertNotIn("ZYT202609220321", response.text)
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_persisted_forged_diagnosis_binding_never_queries_orders(self):
|
||||
session, params, binding = self.prepare_conversation()
|
||||
with self.database.connect() as db:
|
||||
db.execute(
|
||||
"UPDATE archive_patient_binding SET diagnosis_id=? WHERE id=?",
|
||||
(9999, binding["id"]),
|
||||
)
|
||||
db.commit()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_invalid")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_other_tenant_cannot_reuse_conversation_or_person_binding(self):
|
||||
_, params, _ = self.prepare_conversation()
|
||||
other = self.desktop_login("zyt-user-2", "desktop-device-02")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=other["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_required")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_missing_order_permission_blocks_before_upstream_query(self):
|
||||
session = self.desktop_login("zyt-no-patient")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params={
|
||||
"external_account_id": "wxwork-account-01",
|
||||
"conversation_external_id": "S:external-user-01",
|
||||
})
|
||||
self.assertEqual(response.status_code, 403, response.text)
|
||||
client.assert_not_called()
|
||||
|
||||
def test_list_filters_other_patient_and_masks_private_fields(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(), self.sample_order(id=322, diagnosis_id=9999)],
|
||||
"total": 2,
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual([item["order_id"] for item in result["items"]], [321])
|
||||
self.assertEqual(result["total"], 1)
|
||||
self.assertEqual(result["items"][0]["tracking_number_masked"], "SF****7899")
|
||||
self.assertEqual(client.return_value.list_orders.call_args.kwargs["diagnosis_id"], 9101)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
self.assertNotIn("recipient_address", response.text)
|
||||
self.assertNotIn("private", response.text)
|
||||
|
||||
def test_allowed_detail_contains_only_sanitized_order_facts(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
response = self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
order = response.json()["order"]
|
||||
self.assertEqual(order["order_id"], 321)
|
||||
self.assertEqual(order["tracking_number_masked"], "SF****7899")
|
||||
self.assertEqual(order["fulfillment_status"], "已发货")
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("recipient_address", response.text)
|
||||
client.return_value.get_order_detail.assert_called_once_with(321)
|
||||
|
||||
def test_single_order_list_brings_tracking_inline(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {"items": [self.sample_order()], "total": 1}
|
||||
client.return_value.get_tracking.return_value = {
|
||||
"state_text": "运输中",
|
||||
"traces": [{"accept_time": "2026-09-22 09:42:00", "remark": "快件已到达中转站"}],
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual(result["order_count"], 1)
|
||||
self.assertFalse(result["selection_required"])
|
||||
self.assertEqual(result["single_order_id"], 321)
|
||||
self.assertEqual(result["latest_tracking"]["status"], "运输中")
|
||||
self.assertEqual(result["latest_tracking"]["description"], "快件已到达中转站")
|
||||
self.assertEqual(client.return_value.get_tracking.call_args.kwargs["phone_tail"], "8000")
|
||||
|
||||
def test_multiple_orders_require_customer_selection_and_skip_tracking(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(), self.sample_order(id=322, order_no="ZYT202609100322")],
|
||||
"total": 2,
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual(result["order_count"], 2)
|
||||
self.assertTrue(result["selection_required"])
|
||||
self.assertEqual(result["single_order_id"], 0)
|
||||
self.assertIsNone(result["latest_tracking"])
|
||||
self.assertIn("确认", result["hint"])
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_single_order_without_tracking_number_reports_missing(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(tracking_number="", fulfillment_status=2)], "total": 1,
|
||||
}
|
||||
client.return_value.get_order_detail.return_value = self.sample_order(tracking_number="", fulfillment_status=2)
|
||||
listed = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(listed.status_code, 200, listed.text)
|
||||
self.assertIsNone(listed.json()["latest_tracking"])
|
||||
self.assertEqual(listed.json()["tracking_error"]["code"], "tracking_number_missing")
|
||||
tracked = self.client.get(self.order_paths()[2], headers=session["headers"], params=params)
|
||||
self.assertEqual(tracked.status_code, 409, tracked.text)
|
||||
self.assertEqual(tracked.json()["detail"]["code"], "tracking_number_missing")
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_tracking_provider_failure_never_returns_a_status(self):
|
||||
from zyt_order_client import ZytOrderError
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
client.return_value.get_tracking.side_effect = ZytOrderError("快递100 暂不可用")
|
||||
response = self.client.get(self.order_paths()[2], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 502, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "tracking_unavailable")
|
||||
self.assertNotIn("运输中", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
|
||||
def test_missing_order_returns_not_found_code(self):
|
||||
from zyt_order_client import ZytOrderNotFound
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.side_effect = ZytOrderNotFound("订单不存在")
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 404, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "order_not_found")
|
||||
|
||||
def test_list_only_permission_cannot_read_detail_or_tracking(self):
|
||||
_, params, _ = self.prepare_conversation()
|
||||
limited = self.desktop_login("zyt-user-list-only")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {"items": [self.sample_order()], "total": 1}
|
||||
listed = self.client.get(self.order_paths()[0], headers=limited["headers"], params=params)
|
||||
self.assertEqual(listed.status_code, 200, listed.text)
|
||||
# Without the ZYT logistics permission the single-order shortcut must not query tracking.
|
||||
self.assertIsNone(listed.json()["latest_tracking"])
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=limited["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 403, response.text)
|
||||
client.return_value.get_order_detail.assert_not_called()
|
||||
|
||||
def test_summary_for_unbound_conversation_explains_without_querying(self):
|
||||
session, params, _ = self.prepare_conversation(bind=False)
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
summary = response.json()
|
||||
self.assertFalse(summary["capability"]["enabled"])
|
||||
self.assertFalse(summary["capability"]["bound"])
|
||||
self.assertEqual(summary["capability"]["code"], "patient_binding_required")
|
||||
self.assertEqual(summary["recent_orders"], [])
|
||||
client.assert_not_called()
|
||||
|
||||
def test_summary_for_bound_conversation_returns_orders_tracking_and_logs(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [
|
||||
self.sample_order(id=322, order_no="ZYT202609200322", tracking_number="", fulfillment_status=2),
|
||||
self.sample_order(),
|
||||
self.sample_order(id=300, diagnosis_id=9999),
|
||||
],
|
||||
"total": 3,
|
||||
}
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
client.return_value.get_tracking.return_value = {"state_text": "派送中", "traces": []}
|
||||
detail = self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
self.assertEqual(detail.status_code, 200, detail.text)
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
summary = response.json()
|
||||
self.assertTrue(summary["capability"]["enabled"])
|
||||
self.assertEqual([item["order_id"] for item in summary["recent_orders"]], [322, 321])
|
||||
self.assertEqual(summary["latest_tracking"]["status"], "派送中")
|
||||
self.assertEqual(summary["latest_tracking"]["order_id"], 321)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
labels = [entry["label"] for entry in summary["logs"]]
|
||||
self.assertIn("查询订单详情", labels)
|
||||
self.assertIn("刷新订单概览", labels)
|
||||
self.assertEqual(client.return_value.get_tracking.call_args.args[0], 321)
|
||||
|
||||
def test_summary_logs_are_scoped_to_the_conversation(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
other = dict(params, conversation_external_id="S:someone-else")
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=other,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
self.assertEqual(response.json()["logs"], [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from unittest import TestCase, main, mock
|
||||
|
||||
from zyt_patient_client import ZytPatientClient, ZytPatientError
|
||||
|
||||
|
||||
class _Response:
|
||||
def __init__(self, payload):
|
||||
self.payload = payload
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_args):
|
||||
return False
|
||||
|
||||
def read(self):
|
||||
return json.dumps(self.payload, ensure_ascii=False).encode("utf-8")
|
||||
|
||||
|
||||
class ZytPatientClientTest(TestCase):
|
||||
def test_search_deduplicates_diagnoses_and_masks_phone(self):
|
||||
response = _Response(
|
||||
{
|
||||
"code": 1,
|
||||
"data": {
|
||||
"lists": [
|
||||
{
|
||||
"id": 12,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
"age": 35,
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
},
|
||||
],
|
||||
"count": 2,
|
||||
},
|
||||
}
|
||||
)
|
||||
with mock.patch("urllib.request.urlopen", return_value=response) as opened:
|
||||
result = ZytPatientClient(
|
||||
"https://admin.example.com", "secret-token"
|
||||
).search_patients("张三")
|
||||
self.assertEqual(len(result["items"]), 1)
|
||||
self.assertEqual(result["items"][0]["diagnosis_id"], 12)
|
||||
self.assertEqual(result["items"][0]["phone_masked"], "138****8000")
|
||||
request = opened.call_args.args[0]
|
||||
self.assertEqual(request.headers["Token"], "secret-token")
|
||||
self.assertIn("/adminapi/tcm.diagnosis/lists?", request.full_url)
|
||||
|
||||
def test_exact_patient_lookup_uses_the_scoped_diagnosis_list(self):
|
||||
response = _Response(
|
||||
{
|
||||
"code": 1,
|
||||
"data": {
|
||||
"lists": [
|
||||
{
|
||||
"id": 12,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
}
|
||||
],
|
||||
"count": 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
with mock.patch("urllib.request.urlopen", return_value=response) as opened:
|
||||
patient = ZytPatientClient(
|
||||
"https://admin.example.com", "secret-token"
|
||||
).get_patient(8)
|
||||
self.assertIsNotNone(patient)
|
||||
self.assertEqual(patient["patient_id"], 8)
|
||||
self.assertIn("patient_id=8", opened.call_args.args[0].full_url)
|
||||
|
||||
|
||||
def test_diagnosis_validation_keeps_historical_rows_for_the_same_patient(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [
|
||||
{"id": 12, "patient_id": 8, "patient_name": "张三"},
|
||||
{"id": 10, "patient_id": 8, "patient_name": "张三"},
|
||||
], "count": 2,
|
||||
}) as called:
|
||||
diagnosis = client.get_patient_diagnosis(8, 10)
|
||||
self.assertEqual(diagnosis["diagnosis_id"], 10)
|
||||
self.assertEqual(diagnosis["patient_id"], 8)
|
||||
self.assertEqual(called.call_args.args[1], {"patient_id": 8, "page_no": 1, "page_size": 50})
|
||||
|
||||
def test_diagnosis_validation_rejects_wrong_patient_even_if_filter_ignored(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [{"id": 10, "patient_id": 9}], "count": 1,
|
||||
}):
|
||||
self.assertIsNone(client.get_patient_diagnosis(8, 10))
|
||||
|
||||
def test_diagnosis_validation_reads_later_pages(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
pages = [
|
||||
{"lists": [{"id": n, "patient_id": 8} for n in range(100, 150)], "count": 51},
|
||||
{"lists": [{"id": 10, "patient_id": 8}], "count": 51},
|
||||
]
|
||||
with mock.patch.object(client, "_get", side_effect=pages) as called:
|
||||
self.assertEqual(client.get_patient_diagnosis(8, 10)["diagnosis_id"], 10)
|
||||
self.assertEqual(called.call_args.args[1]["page_no"], 2)
|
||||
|
||||
def test_diagnosis_validation_fails_explicitly_when_bounded_scan_is_truncated(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [{"id": 12, "patient_id": 8}], "count": 1001,
|
||||
}) as called:
|
||||
with self.assertRaisesRegex(ZytPatientError, "超过核验范围"):
|
||||
client.get_patient_diagnosis(8, 10)
|
||||
self.assertEqual(called.call_count, 20)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,328 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Patient-order proxy security checks using persisted conversation bindings."""
|
||||
|
||||
from unittest import TestCase, main, mock
|
||||
|
||||
import test_archive_api as archive_tests
|
||||
|
||||
|
||||
class ZytOrderApiTest(TestCase):
|
||||
# Reuse fixture helpers without inheriting and re-running the archive suite.
|
||||
setUp = archive_tests.ArchiveApiTest.setUp
|
||||
tearDown = archive_tests.ArchiveApiTest.tearDown
|
||||
login = archive_tests.ArchiveApiTest.login
|
||||
desktop_login = archive_tests.ArchiveApiTest.desktop_login
|
||||
sample_payload = staticmethod(archive_tests.ArchiveApiTest.sample_payload)
|
||||
search_zyt_patients = staticmethod(archive_tests.ArchiveApiTest.search_zyt_patients)
|
||||
|
||||
@staticmethod
|
||||
def verify_zyt(token):
|
||||
identity = archive_tests.ArchiveApiTest.verify_zyt(token)
|
||||
if token == "zyt-user-list-only":
|
||||
identity["permissions"].append("firstvisit.myPatient/orders")
|
||||
elif token != "zyt-no-patient":
|
||||
identity["permissions"] += [
|
||||
"firstvisit.myPatient/orders", "firstvisit.myPatient/orderDetail",
|
||||
"tcm.prescriptionOrder/detail", "tcm.prescriptionOrder/logisticsTrace",
|
||||
]
|
||||
return identity
|
||||
|
||||
def prepare_conversation(self, *, bind=True):
|
||||
session = self.desktop_login()
|
||||
payload = self.sample_payload()
|
||||
imported = self.client.post(
|
||||
"/api/v2/archive/desktop/imports/messages",
|
||||
headers=session["headers"], json=payload,
|
||||
)
|
||||
self.assertEqual(imported.status_code, 200, imported.text)
|
||||
params = {
|
||||
"external_account_id": payload["source_account"]["external_account_id"],
|
||||
"conversation_external_id": payload["messages"][0]["conversation"]["external_id"],
|
||||
}
|
||||
context = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-context",
|
||||
headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(context.status_code, 200, context.text)
|
||||
person_id = context.json()["person"]["id"]
|
||||
params["person_id"] = person_id
|
||||
binding = None
|
||||
if bind:
|
||||
searched = self.client.get(
|
||||
"/api/v2/archive/desktop/patients/search",
|
||||
headers=session["headers"], params={"keyword": "张三"},
|
||||
)
|
||||
self.assertEqual(searched.status_code, 200, searched.text)
|
||||
response = self.client.put(
|
||||
"/api/v2/archive/desktop/patient-binding",
|
||||
headers=session["headers"],
|
||||
json={**params, "patient_id": 9001, "diagnosis_id": 9101},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
binding = response.json()["binding"]
|
||||
return session, params, binding
|
||||
|
||||
@staticmethod
|
||||
def sample_order(**overrides):
|
||||
return {
|
||||
"id": 321, "order_no": "ZYT202609220321", "diagnosis_id": 9101,
|
||||
"create_time": "2026-09-22 10:20:00", "fulfillment_status": 5,
|
||||
"prescription_audit_status": 1, "payment_slip_audit_status": 1,
|
||||
"express_company": "顺丰", "tracking_number": "SF1234567899",
|
||||
"recipient_name": "张三", "recipient_phone": "13800138000",
|
||||
"recipient_address": "不应向模型公开的住址", "prescription": {"private": True},
|
||||
**overrides,
|
||||
}
|
||||
|
||||
def order_paths(self):
|
||||
return (
|
||||
"/api/v2/archive/desktop/patient-orders",
|
||||
"/api/v2/archive/desktop/patient-orders/321",
|
||||
"/api/v2/archive/desktop/patient-orders/321/tracking",
|
||||
"/api/v2/archive/desktop/patient-orders/321/audit-status",
|
||||
)
|
||||
|
||||
def test_unbound_conversation_never_queries_orders(self):
|
||||
session, params, _ = self.prepare_conversation(bind=False)
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_required")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_order_from_other_diagnosis_is_rejected_before_tracking(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order(diagnosis_id=9999)
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 404, response.text)
|
||||
self.assertNotIn("ZYT202609220321", response.text)
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_persisted_forged_diagnosis_binding_never_queries_orders(self):
|
||||
session, params, binding = self.prepare_conversation()
|
||||
with self.database.connect() as db:
|
||||
db.execute(
|
||||
"UPDATE archive_patient_binding SET diagnosis_id=? WHERE id=?",
|
||||
(9999, binding["id"]),
|
||||
)
|
||||
db.commit()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_invalid")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_other_tenant_cannot_reuse_conversation_or_person_binding(self):
|
||||
_, params, _ = self.prepare_conversation()
|
||||
other = self.desktop_login("zyt-user-2", "desktop-device-02")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=other["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 409, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "patient_binding_required")
|
||||
client.assert_not_called()
|
||||
|
||||
def test_missing_order_permission_blocks_before_upstream_query(self):
|
||||
session = self.desktop_login("zyt-no-patient")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
for path in self.order_paths():
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params={
|
||||
"external_account_id": "wxwork-account-01",
|
||||
"conversation_external_id": "S:external-user-01",
|
||||
})
|
||||
self.assertEqual(response.status_code, 403, response.text)
|
||||
client.assert_not_called()
|
||||
|
||||
def test_list_filters_other_patient_and_masks_private_fields(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(), self.sample_order(id=322, diagnosis_id=9999)],
|
||||
"total": 2,
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual([item["order_id"] for item in result["items"]], [321])
|
||||
self.assertEqual(result["total"], 1)
|
||||
self.assertEqual(result["items"][0]["tracking_number_masked"], "SF****7899")
|
||||
self.assertEqual(client.return_value.list_orders.call_args.kwargs["diagnosis_id"], 9101)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
self.assertNotIn("recipient_address", response.text)
|
||||
self.assertNotIn("private", response.text)
|
||||
|
||||
def test_allowed_detail_contains_only_sanitized_order_facts(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
response = self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
order = response.json()["order"]
|
||||
self.assertEqual(order["order_id"], 321)
|
||||
self.assertEqual(order["tracking_number_masked"], "SF****7899")
|
||||
self.assertEqual(order["fulfillment_status"], "已发货")
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("recipient_address", response.text)
|
||||
client.return_value.get_order_detail.assert_called_once_with(321)
|
||||
|
||||
def test_single_order_list_brings_tracking_inline(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {"items": [self.sample_order()], "total": 1}
|
||||
client.return_value.get_tracking.return_value = {
|
||||
"state_text": "运输中",
|
||||
"traces": [{"accept_time": "2026-09-22 09:42:00", "remark": "快件已到达中转站"}],
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual(result["order_count"], 1)
|
||||
self.assertFalse(result["selection_required"])
|
||||
self.assertEqual(result["single_order_id"], 321)
|
||||
self.assertEqual(result["latest_tracking"]["status"], "运输中")
|
||||
self.assertEqual(result["latest_tracking"]["description"], "快件已到达中转站")
|
||||
self.assertEqual(client.return_value.get_tracking.call_args.kwargs["phone_tail"], "8000")
|
||||
|
||||
def test_multiple_orders_require_customer_selection_and_skip_tracking(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(), self.sample_order(id=322, order_no="ZYT202609100322")],
|
||||
"total": 2,
|
||||
}
|
||||
response = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
result = response.json()
|
||||
self.assertEqual(result["order_count"], 2)
|
||||
self.assertTrue(result["selection_required"])
|
||||
self.assertEqual(result["single_order_id"], 0)
|
||||
self.assertIsNone(result["latest_tracking"])
|
||||
self.assertIn("确认", result["hint"])
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_single_order_without_tracking_number_reports_missing(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [self.sample_order(tracking_number="", fulfillment_status=2)], "total": 1,
|
||||
}
|
||||
client.return_value.get_order_detail.return_value = self.sample_order(tracking_number="", fulfillment_status=2)
|
||||
listed = self.client.get(self.order_paths()[0], headers=session["headers"], params=params)
|
||||
self.assertEqual(listed.status_code, 200, listed.text)
|
||||
self.assertIsNone(listed.json()["latest_tracking"])
|
||||
self.assertEqual(listed.json()["tracking_error"]["code"], "tracking_number_missing")
|
||||
tracked = self.client.get(self.order_paths()[2], headers=session["headers"], params=params)
|
||||
self.assertEqual(tracked.status_code, 409, tracked.text)
|
||||
self.assertEqual(tracked.json()["detail"]["code"], "tracking_number_missing")
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
|
||||
def test_tracking_provider_failure_never_returns_a_status(self):
|
||||
from zyt_order_client import ZytOrderError
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
client.return_value.get_tracking.side_effect = ZytOrderError("快递100 暂不可用")
|
||||
response = self.client.get(self.order_paths()[2], headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 502, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "tracking_unavailable")
|
||||
self.assertNotIn("运输中", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
|
||||
def test_missing_order_returns_not_found_code(self):
|
||||
from zyt_order_client import ZytOrderNotFound
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.side_effect = ZytOrderNotFound("订单不存在")
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=session["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 404, response.text)
|
||||
self.assertEqual(response.json()["detail"]["code"], "order_not_found")
|
||||
|
||||
def test_list_only_permission_cannot_read_detail_or_tracking(self):
|
||||
_, params, _ = self.prepare_conversation()
|
||||
limited = self.desktop_login("zyt-user-list-only")
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {"items": [self.sample_order()], "total": 1}
|
||||
listed = self.client.get(self.order_paths()[0], headers=limited["headers"], params=params)
|
||||
self.assertEqual(listed.status_code, 200, listed.text)
|
||||
# Without the ZYT logistics permission the single-order shortcut must not query tracking.
|
||||
self.assertIsNone(listed.json()["latest_tracking"])
|
||||
client.return_value.get_tracking.assert_not_called()
|
||||
for path in self.order_paths()[1:]:
|
||||
with self.subTest(path=path):
|
||||
response = self.client.get(path, headers=limited["headers"], params=params)
|
||||
self.assertEqual(response.status_code, 403, response.text)
|
||||
client.return_value.get_order_detail.assert_not_called()
|
||||
|
||||
def test_summary_for_unbound_conversation_explains_without_querying(self):
|
||||
session, params, _ = self.prepare_conversation(bind=False)
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
summary = response.json()
|
||||
self.assertFalse(summary["capability"]["enabled"])
|
||||
self.assertFalse(summary["capability"]["bound"])
|
||||
self.assertEqual(summary["capability"]["code"], "patient_binding_required")
|
||||
self.assertEqual(summary["recent_orders"], [])
|
||||
client.assert_not_called()
|
||||
|
||||
def test_summary_for_bound_conversation_returns_orders_tracking_and_logs(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.list_orders.return_value = {
|
||||
"items": [
|
||||
self.sample_order(id=322, order_no="ZYT202609200322", tracking_number="", fulfillment_status=2),
|
||||
self.sample_order(),
|
||||
self.sample_order(id=300, diagnosis_id=9999),
|
||||
],
|
||||
"total": 3,
|
||||
}
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
client.return_value.get_tracking.return_value = {"state_text": "派送中", "traces": []}
|
||||
detail = self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
self.assertEqual(detail.status_code, 200, detail.text)
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=params,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
summary = response.json()
|
||||
self.assertTrue(summary["capability"]["enabled"])
|
||||
self.assertEqual([item["order_id"] for item in summary["recent_orders"]], [322, 321])
|
||||
self.assertEqual(summary["latest_tracking"]["status"], "派送中")
|
||||
self.assertEqual(summary["latest_tracking"]["order_id"], 321)
|
||||
self.assertNotIn("13800138000", response.text)
|
||||
self.assertNotIn("SF1234567899", response.text)
|
||||
labels = [entry["label"] for entry in summary["logs"]]
|
||||
self.assertIn("查询订单详情", labels)
|
||||
self.assertIn("刷新订单概览", labels)
|
||||
self.assertEqual(client.return_value.get_tracking.call_args.args[0], 321)
|
||||
|
||||
def test_summary_logs_are_scoped_to_the_conversation(self):
|
||||
session, params, _ = self.prepare_conversation()
|
||||
with mock.patch("archive_api.ZytOrderClient") as client:
|
||||
client.return_value.get_order_detail.return_value = self.sample_order()
|
||||
self.client.get(self.order_paths()[1], headers=session["headers"], params=params)
|
||||
other = dict(params, conversation_external_id="S:someone-else")
|
||||
response = self.client.get(
|
||||
"/api/v2/archive/desktop/patient-orders/summary", headers=session["headers"], params=other,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
self.assertEqual(response.json()["logs"], [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from unittest import TestCase, main, mock
|
||||
|
||||
from zyt_patient_client import ZytPatientClient, ZytPatientError
|
||||
|
||||
|
||||
class _Response:
|
||||
def __init__(self, payload):
|
||||
self.payload = payload
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *_args):
|
||||
return False
|
||||
|
||||
def read(self):
|
||||
return json.dumps(self.payload, ensure_ascii=False).encode("utf-8")
|
||||
|
||||
|
||||
class ZytPatientClientTest(TestCase):
|
||||
def test_search_deduplicates_diagnoses_and_masks_phone(self):
|
||||
response = _Response(
|
||||
{
|
||||
"code": 1,
|
||||
"data": {
|
||||
"lists": [
|
||||
{
|
||||
"id": 12,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
"age": 35,
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
},
|
||||
],
|
||||
"count": 2,
|
||||
},
|
||||
}
|
||||
)
|
||||
with mock.patch("urllib.request.urlopen", return_value=response) as opened:
|
||||
result = ZytPatientClient(
|
||||
"https://admin.example.com", "secret-token"
|
||||
).search_patients("张三")
|
||||
self.assertEqual(len(result["items"]), 1)
|
||||
self.assertEqual(result["items"][0]["diagnosis_id"], 12)
|
||||
self.assertEqual(result["items"][0]["phone_masked"], "138****8000")
|
||||
request = opened.call_args.args[0]
|
||||
self.assertEqual(request.headers["Token"], "secret-token")
|
||||
self.assertIn("/adminapi/tcm.diagnosis/lists?", request.full_url)
|
||||
|
||||
def test_exact_patient_lookup_uses_the_scoped_diagnosis_list(self):
|
||||
response = _Response(
|
||||
{
|
||||
"code": 1,
|
||||
"data": {
|
||||
"lists": [
|
||||
{
|
||||
"id": 12,
|
||||
"patient_id": 8,
|
||||
"patient_name": "张三",
|
||||
"phone": "13800138000",
|
||||
}
|
||||
],
|
||||
"count": 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
with mock.patch("urllib.request.urlopen", return_value=response) as opened:
|
||||
patient = ZytPatientClient(
|
||||
"https://admin.example.com", "secret-token"
|
||||
).get_patient(8)
|
||||
self.assertIsNotNone(patient)
|
||||
self.assertEqual(patient["patient_id"], 8)
|
||||
self.assertIn("patient_id=8", opened.call_args.args[0].full_url)
|
||||
|
||||
|
||||
def test_diagnosis_validation_keeps_historical_rows_for_the_same_patient(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [
|
||||
{"id": 12, "patient_id": 8, "patient_name": "张三"},
|
||||
{"id": 10, "patient_id": 8, "patient_name": "张三"},
|
||||
], "count": 2,
|
||||
}) as called:
|
||||
diagnosis = client.get_patient_diagnosis(8, 10)
|
||||
self.assertEqual(diagnosis["diagnosis_id"], 10)
|
||||
self.assertEqual(diagnosis["patient_id"], 8)
|
||||
self.assertEqual(called.call_args.args[1], {"patient_id": 8, "page_no": 1, "page_size": 50})
|
||||
|
||||
def test_diagnosis_validation_rejects_wrong_patient_even_if_filter_ignored(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [{"id": 10, "patient_id": 9}], "count": 1,
|
||||
}):
|
||||
self.assertIsNone(client.get_patient_diagnosis(8, 10))
|
||||
|
||||
def test_diagnosis_validation_reads_later_pages(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
pages = [
|
||||
{"lists": [{"id": n, "patient_id": 8} for n in range(100, 150)], "count": 51},
|
||||
{"lists": [{"id": 10, "patient_id": 8}], "count": 51},
|
||||
]
|
||||
with mock.patch.object(client, "_get", side_effect=pages) as called:
|
||||
self.assertEqual(client.get_patient_diagnosis(8, 10)["diagnosis_id"], 10)
|
||||
self.assertEqual(called.call_args.args[1]["page_no"], 2)
|
||||
|
||||
def test_diagnosis_validation_fails_explicitly_when_bounded_scan_is_truncated(self):
|
||||
client = ZytPatientClient("https://admin.example.com", "secret-token")
|
||||
with mock.patch.object(client, "_get", return_value={
|
||||
"lists": [{"id": 12, "patient_id": 8}], "count": 1001,
|
||||
}) as called:
|
||||
with self.assertRaisesRegex(ZytPatientError, "超过核验范围"):
|
||||
client.get_patient_diagnosis(8, 10)
|
||||
self.assertEqual(called.call_count, 20)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-mcp-20260922
|
||||
release=/home/ps/order-mcp-20260922
|
||||
cd "$release"
|
||||
python3 -c 'import json;from pathlib import Path;p=json.loads(Path("order-release-plan.json").read_text());assert p["schemaMigration"] is False'
|
||||
python3 order_server_guard.py baseline
|
||||
test ! -e source-before
|
||||
test ! -e preflight-complete
|
||||
if docker image inspect zyt/wecom-admin:before-order-mcp-20260922 >/dev/null 2>&1; then echo 'Refuse to replace existing rollback tag' >&2; exit 1; fi
|
||||
mkdir -m 700 source-before
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import shutil, json
|
||||
r = Path('/home/ps/order-mcp-20260922')
|
||||
p = json.loads((r / 'order-release-plan.json').read_text())
|
||||
for name in p['backendFiles']:
|
||||
shutil.copy2(Path('/opt/im-admin/wechat_rpa') / name, r / 'source-before' / name)
|
||||
shutil.copy2('/opt/im-admin/deploy/im-admin/compose.yaml', r / 'source-before/compose.yaml')
|
||||
PY
|
||||
docker tag zyt/wecom-admin:current zyt/wecom-admin:before-order-mcp-20260922
|
||||
docker image inspect zyt/wecom-admin:current --format '{{.Id}}' > image-before.txt
|
||||
printf '%s\n' ready > preflight-complete
|
||||
echo "preflight complete; rollback image tagged before-order-mcp-20260922 ($(cat image-before.txt))"
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-mcp-20260922
|
||||
release=/home/ps/order-mcp-20260922
|
||||
cd "$release"
|
||||
test -f preflight-complete
|
||||
test ! -e candidate-passed
|
||||
python3 order_server_guard.py baseline
|
||||
test "$(docker image inspect zyt/wecom-admin:before-order-mcp-20260922 --format '{{.Id}}')" = "$(cat image-before.txt)"
|
||||
# Consistent read-only snapshot of the live database plus the encryption key; no schema change, backup is a safety net.
|
||||
docker exec -i im-admin-api-1 python - <<'PY' > backup-order.json
|
||||
from pathlib import Path
|
||||
import sqlite3, shutil, os, json
|
||||
folder = Path('/data/backups/order-mcp-20260922'); folder.mkdir(mode=0o700)
|
||||
source = sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30)
|
||||
backup = sqlite3.connect(folder / 'backend.db')
|
||||
try:
|
||||
source.backup(backup, pages=0)
|
||||
finally:
|
||||
backup.close(); source.close()
|
||||
with sqlite3.connect('file:' + str(folder / 'backend.db') + '?mode=ro', uri=True) as check:
|
||||
assert check.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
os.chmod(folder / 'backend.db', 0o600)
|
||||
keys = list(Path('/data').glob('*.key')); assert keys, 'Encryption key backup missing'
|
||||
for p in keys:
|
||||
shutil.copy2(p, folder / p.name); os.chmod(folder / p.name, 0o600)
|
||||
print(json.dumps({'backup': str(folder), 'quick_check': 'ok', 'bytes': (folder / 'backend.db').stat().st_size, 'keyCount': len(keys)}))
|
||||
PY
|
||||
docker build --network=none --pull=false -f Dockerfile.order-overlay -t zyt/wecom-admin:order-mcp-20260922 . > candidate-build.log 2>&1
|
||||
mapfile -t modules < <(python3 -c 'import json;print("\n".join(json.load(open("order-release-plan.json"))["serverTestModules"]))')
|
||||
test "${#modules[@]}" -gt 0
|
||||
docker run --rm --network=none --read-only --tmpfs /tmp:size=512m,mode=1777 --tmpfs /data:size=256m,mode=1777 \
|
||||
-v "$release/tests:/order-tests:ro" -e PYTHONPATH=/order-tests:/app/wechat_rpa \
|
||||
zyt/wecom-admin:order-mcp-20260922 python -X utf8 -B -m unittest "${modules[@]}" -q > candidate-tests.log 2>&1
|
||||
tail -n 3 candidate-tests.log
|
||||
python3 order_server_guard.py candidate
|
||||
printf '%s\n' passed > candidate-passed
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-mcp-20260922
|
||||
release=/home/ps/order-mcp-20260922
|
||||
cd "$release"
|
||||
test -f candidate-passed
|
||||
test -f backup-order.json
|
||||
python3 order_server_guard.py baseline
|
||||
cd /opt/im-admin/deploy/im-admin
|
||||
docker compose config --quiet
|
||||
rollback_on_error() { rc=$?; trap - ERR; bash "$release/rollback-order.sh"; exit "$rc"; }
|
||||
trap rollback_on_error ERR
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
import json, hashlib, os
|
||||
r = Path('/home/ps/order-mcp-20260922'); target = Path('/opt/im-admin')
|
||||
reference = (target / 'wechat_rpa/archive_api.py').stat().st_mode & 0o777
|
||||
for row in json.loads((r / 'order-manifest.json').read_text()):
|
||||
if not row['path'].startswith('wechat_rpa/'):
|
||||
continue
|
||||
p = (target / row['path']).resolve(); assert p.is_relative_to(target)
|
||||
data = (r / 'payload' / row['path']).read_bytes(); assert hashlib.sha256(data).hexdigest() == row['sha256']
|
||||
tmp = p.with_name(p.name + '.order-mcp.tmp'); assert not tmp.exists()
|
||||
with tmp.open('xb') as f:
|
||||
f.write(data)
|
||||
os.chmod(tmp, p.stat().st_mode & 0o777 if p.exists() else reference); os.replace(tmp, p)
|
||||
PY
|
||||
docker compose stop -t 190 knowledge-worker
|
||||
docker compose stop -t 65 gateway
|
||||
docker tag zyt/wecom-admin:order-mcp-20260922 zyt/wecom-admin:current
|
||||
docker compose up -d --no-build --wait --wait-timeout 180 api gateway knowledge-worker
|
||||
bash "$release/04-order-verify.sh"
|
||||
trap - ERR
|
||||
printf '%s\n' 'Order MCP proxy overlay deployed and verified.'
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
test "${ORDER_RELEASE_APPROVED:-}" = order-mcp-20260922
|
||||
release=/home/ps/order-mcp-20260922
|
||||
cd "$release"
|
||||
python3 order_server_guard.py deployed > deployed-order-verification.json
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18766/api/v2/health
|
||||
curl -fsS -o /dev/null http://127.0.0.1:18770/health
|
||||
docker exec -i im-admin-api-1 python - <<'PY'
|
||||
import sqlite3, json
|
||||
with sqlite3.connect('file:/data/backend.db?mode=ro', uri=True, timeout=30) as c:
|
||||
assert c.execute('PRAGMA quick_check').fetchone()[0] == 'ok'
|
||||
print(json.dumps({'databaseQuickCheck': 'ok', 'patientDataRead': False}))
|
||||
PY
|
||||
cat deployed-order-verification.json
|
||||
@@ -0,0 +1,38 @@
|
||||
# 订单 MCP 代理接口上线包(order-mcp-20260922)
|
||||
|
||||
状态:本地已准备并验证,**尚未上传、尚未部署**(自动模式禁止对生产服务器执行 ssh/scp)。
|
||||
|
||||
- 服务器:`ps@192.168.110.111`,项目 `/opt/im-admin`,compose 目录 `/opt/im-admin/deploy/im-admin`。
|
||||
- 发布包:`order-server-bundle.tar.gz`,77,900 字节,SHA-256 `c70e37b1714dc284d5d86e7a1e6c49f82975a70fc63a2cfd5fed1c7fe033294a`。
|
||||
- 生产文件(4 个):`archive_api.py`、`admin_backend.py`、`zyt_patient_client.py`(替换),`zyt_order_client.py`(新增)。无表结构变更。
|
||||
- 基线:`C:/kefu/wechat_rpa` 提交 280a49a,三份替换文件的哈希与 patient-session-20260918 上线后的哈希一致;预检脚本会再次核对宿主和容器内文件哈希,任何漂移即停止。
|
||||
- 本地验证:候选代码 176 项测试通过(test_zyt_order_api、test_zyt_patient_client、test_archive_api、test_zyt_session_recovery、test_admin_api)。
|
||||
|
||||
## 上传
|
||||
|
||||
```bash
|
||||
ssh ps@192.168.110.111 'mkdir -m 700 /home/ps/order-mcp-20260922'
|
||||
scp C:/kefu/deploy/order-mcp-20260922/order-server-bundle.tar.gz ps@192.168.110.111:/home/ps/order-mcp-20260922/
|
||||
ssh ps@192.168.110.111 'cd /home/ps/order-mcp-20260922 && echo "c70e37b1714dc284d5d86e7a1e6c49f82975a70fc63a2cfd5fed1c7fe033294a order-server-bundle.tar.gz" | sha256sum -c - && tar -xzf order-server-bundle.tar.gz'
|
||||
```
|
||||
|
||||
## 部署(在服务器上依次执行)
|
||||
|
||||
```bash
|
||||
export ORDER_RELEASE_APPROVED=order-mcp-20260922
|
||||
bash /home/ps/order-mcp-20260922/01-order-preflight.sh # 基线核对、备份源文件、打回滚镜像标签
|
||||
bash /home/ps/order-mcp-20260922/02-order-backup-build.sh # 数据库一致性备份 + 构建候选镜像 + 离线跑测试
|
||||
bash /home/ps/order-mcp-20260922/03-order-deploy.sh # 替换文件、切换镜像、重启 api/gateway/knowledge-worker、验证
|
||||
```
|
||||
|
||||
03 失败会自动调用回滚。手动回滚:
|
||||
|
||||
```bash
|
||||
ORDER_RELEASE_APPROVED=order-mcp-20260922 bash /home/ps/order-mcp-20260922/rollback-order.sh
|
||||
```
|
||||
|
||||
## 上线后
|
||||
|
||||
- 桌面端要用本次 `C:/wechat_rpa` 代码重新打包(订单 MCP、意图识别、事实校验、订单面板都在客户端)。
|
||||
- 用一个已绑定患者的会话打开“微信消息库”,确认“订单查询”面板显示“已启用”。
|
||||
- 服务器上的 `/home/ps/order-mcp-20260922/deployed-order-verification.json` 记录最终校验结果。
|
||||
@@ -0,0 +1,7 @@
|
||||
ARG BASE_IMAGE=zyt/wecom-admin:before-order-mcp-20260922
|
||||
FROM ${BASE_IMAGE}
|
||||
COPY --chown=app:app payload/wechat_rpa/archive_api.py /app/wechat_rpa/archive_api.py
|
||||
COPY --chown=app:app payload/wechat_rpa/admin_backend.py /app/wechat_rpa/admin_backend.py
|
||||
COPY --chown=app:app payload/wechat_rpa/zyt_patient_client.py /app/wechat_rpa/zyt_patient_client.py
|
||||
COPY --chown=app:app payload/wechat_rpa/zyt_order_client.py /app/wechat_rpa/zyt_order_client.py
|
||||
WORKDIR /app/wechat_rpa
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,907 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""企业微信聊天归档 API。
|
||||
|
||||
路由独立注册在 ``/api/v2/archive`` 下,不改动现有模型、用户和桌面端同步接口。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
|
||||
from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, Request
|
||||
from pydantic import BaseModel, Field
|
||||
from starlette.responses import FileResponse, RedirectResponse
|
||||
|
||||
from archive_store import ALL_TENANTS, ArchiveStore
|
||||
from zyt_patient_client import (
|
||||
ZytPatientClient, ZytPatientError, ZytPatientSessionExpired, ZytPatientPermissionDenied,
|
||||
)
|
||||
|
||||
|
||||
ZYT_PATIENT_LIST_PERMISSION = "tcm.diagnosis/lists"
|
||||
|
||||
|
||||
class StorageBody(BaseModel):
|
||||
bucket: str = ""
|
||||
region: str = ""
|
||||
custom_domain: str = ""
|
||||
media_prefix: str = "archive/media"
|
||||
export_prefix: str = "archive/exports"
|
||||
release_prefix: str = "desktop/releases"
|
||||
encryption_mode: str = "AES256"
|
||||
secret_id: str = ""
|
||||
secret_key: str = ""
|
||||
enabled: bool = False
|
||||
|
||||
|
||||
class MediaPrepareBody(BaseModel):
|
||||
sha256: str
|
||||
size_bytes: int
|
||||
mime_type: str = "application/octet-stream"
|
||||
original_filename: str = "file"
|
||||
|
||||
|
||||
class MultipartPartBody(BaseModel):
|
||||
part_number: int = Field(ge=1, le=10000)
|
||||
etag: str = Field(min_length=1, max_length=512)
|
||||
|
||||
|
||||
class MediaMultipartCompleteBody(BaseModel):
|
||||
upload_id: str = Field(min_length=1, max_length=2048)
|
||||
parts: list[MultipartPartBody] = Field(min_length=1, max_length=10000)
|
||||
|
||||
|
||||
class ImportBody(BaseModel):
|
||||
source_account: dict[str, Any]
|
||||
messages: list[dict[str, Any]] = Field(min_length=1, max_length=5000)
|
||||
batch_id: str = ""
|
||||
source_table: str = "message_table"
|
||||
checkpoint: Any = None
|
||||
|
||||
|
||||
class MetadataBody(BaseModel):
|
||||
source_account: dict[str, Any]
|
||||
people: list[dict[str, Any]] = Field(default_factory=list, max_length=5000)
|
||||
conversations: list[dict[str, Any]] = Field(default_factory=list, max_length=5000)
|
||||
|
||||
|
||||
class DesktopCheckpointBody(BaseModel):
|
||||
source_account: dict[str, Any]
|
||||
source_table: str = "message_table"
|
||||
checkpoint: dict[str, Any]
|
||||
|
||||
|
||||
class MediaAccessBody(BaseModel):
|
||||
media_ids: list[str] = Field(min_length=1, max_length=200)
|
||||
expires: int = Field(default=300, ge=60, le=900)
|
||||
|
||||
|
||||
class ExportBody(BaseModel):
|
||||
formats: list[str] = Field(default_factory=lambda: ["sql", "xlsx"])
|
||||
filters: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class IdentityBody(BaseModel):
|
||||
identity_type: str
|
||||
scope_id: str = ""
|
||||
external_id: str
|
||||
verified: bool = True
|
||||
|
||||
|
||||
class PatientBindingBody(BaseModel):
|
||||
patient_id: int = Field(gt=0)
|
||||
diagnosis_id: int = Field(default=0, ge=0)
|
||||
relation_type: str = Field(default="self", min_length=2, max_length=16)
|
||||
|
||||
|
||||
class DesktopPatientBindingBody(PatientBindingBody):
|
||||
external_account_id: str = Field(min_length=1, max_length=191)
|
||||
conversation_external_id: str = Field(min_length=1, max_length=512)
|
||||
person_id: str = Field(default="", max_length=64)
|
||||
|
||||
|
||||
def _http_error(exc: Exception) -> HTTPException:
|
||||
if isinstance(exc, HTTPException):
|
||||
return exc
|
||||
if isinstance(exc, KeyError):
|
||||
return HTTPException(status_code=404, detail=str(exc).strip("'"))
|
||||
if isinstance(exc, ValueError):
|
||||
return HTTPException(status_code=400, detail=str(exc))
|
||||
if isinstance(exc, ZytPatientSessionExpired):
|
||||
return HTTPException(status_code=409, detail={
|
||||
"code": "zyt_session_expired",
|
||||
"message": "ZYT 患者查询登录已过期,请重新验证账号。",
|
||||
})
|
||||
if isinstance(exc, ZytPatientPermissionDenied):
|
||||
return HTTPException(status_code=403, detail=str(exc))
|
||||
if isinstance(exc, ZytPatientError):
|
||||
return HTTPException(status_code=502, detail=str(exc))
|
||||
if isinstance(exc, RuntimeError):
|
||||
return HTTPException(status_code=409, detail=str(exc))
|
||||
return HTTPException(status_code=502, detail=f"外部存储操作失败:{exc}")
|
||||
|
||||
|
||||
def register_archive_routes(
|
||||
app: FastAPI,
|
||||
database: Any,
|
||||
current: Callable[..., Any],
|
||||
require: Callable[..., Any],
|
||||
client_ip: Callable[[Request], str],
|
||||
current_desktop: Callable[..., Any],
|
||||
# 返回值有两种形状:一个租户,或者一组租户(管理员选「全部」且只被授权到
|
||||
# 若干客户端账号时)。两种都由 `archive_store.tenant_scope` 统一翻译。
|
||||
resolve_admin_tenant: Callable[[Any, int | None], "str | list[str]"],
|
||||
zyt_api_url: Callable[[], str] | None = None,
|
||||
zyt_patient_searcher: Callable[[str, str, int, int], dict[str, Any]] | None = None,
|
||||
) -> ArchiveStore:
|
||||
"""将聊天归档路由附加到现有 FastAPI 应用。"""
|
||||
|
||||
store = ArchiveStore(database)
|
||||
store.initialize()
|
||||
app.state.archive_store = store
|
||||
|
||||
def single_tenant(value: Any) -> str:
|
||||
"""写路径要的那**一个**租户。
|
||||
|
||||
看数据可以跨账号(「全部」),但绑患者、发导出任务不行:这条记录要记在
|
||||
谁名下,得有个确切答案。这里把它挡在最前面并说清楚该怎么办——否则会一路
|
||||
走到 `safe_scope`,报一句"租户只能包含字母、数字、下划线和连字符",
|
||||
对着界面上的下拉框完全看不懂。
|
||||
"""
|
||||
if isinstance(value, str) and value != ALL_TENANTS:
|
||||
return value
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="这一步要先在右上角选择具体的客户端账号,「全部」下无法确定归属",
|
||||
)
|
||||
export_slot = asyncio.Lock()
|
||||
|
||||
async def run_export(job_id: str) -> None:
|
||||
# Queued jobs wait asynchronously, never occupying the API worker pool.
|
||||
async with export_slot:
|
||||
await asyncio.to_thread(store.run_export_job, job_id)
|
||||
|
||||
|
||||
def _desktop_patient_access(account: Any) -> dict[str, Any]:
|
||||
try:
|
||||
raw_permissions = account["zyt_permissions_json"]
|
||||
except (KeyError, IndexError):
|
||||
raw_permissions = "[]"
|
||||
try:
|
||||
parsed_permissions = json.loads(str(raw_permissions or "[]"))
|
||||
except (TypeError, ValueError):
|
||||
parsed_permissions = []
|
||||
permissions = {
|
||||
str(item).strip().lower()
|
||||
for item in parsed_permissions
|
||||
if str(item).strip()
|
||||
} if isinstance(parsed_permissions, list) else set()
|
||||
try:
|
||||
is_root = bool(int(account["zyt_root"] or 0))
|
||||
except (KeyError, IndexError, TypeError, ValueError):
|
||||
is_root = False
|
||||
try:
|
||||
known = bool(int(account["zyt_permissions_known"] or 0))
|
||||
except (KeyError, IndexError, TypeError, ValueError):
|
||||
known = False
|
||||
allowed = is_root or "*" in permissions or ZYT_PATIENT_LIST_PERMISSION in permissions
|
||||
if allowed:
|
||||
reason = ""
|
||||
elif known:
|
||||
reason = "当前登录的 ZYT 账号没有患者列表权限"
|
||||
else:
|
||||
reason = "暂未取得当前 ZYT 账号的权限信息,请退出软件后重新登录"
|
||||
return {
|
||||
"can_search": allowed,
|
||||
"can_bind": allowed,
|
||||
"can_unbind": allowed,
|
||||
"is_root": is_root,
|
||||
"known": known,
|
||||
"required_permission": ZYT_PATIENT_LIST_PERMISSION,
|
||||
"reason": reason,
|
||||
}
|
||||
|
||||
def _require_desktop_patient_access(account: Any) -> dict[str, Any]:
|
||||
access = _desktop_patient_access(account)
|
||||
if not access["can_search"]:
|
||||
raise HTTPException(status_code=403, detail=str(access["reason"]))
|
||||
return access
|
||||
|
||||
def _context_with_access(
|
||||
context: dict[str, Any], access: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
result = dict(context)
|
||||
result["permissions"] = access
|
||||
return result
|
||||
|
||||
async def _search_patients_for_tenant(
|
||||
tenant: str, keyword: str, page_no: int, page_size: int
|
||||
) -> dict[str, Any]:
|
||||
token = await asyncio.to_thread(store.zyt_token, tenant)
|
||||
if zyt_patient_searcher is not None:
|
||||
result = await asyncio.to_thread(
|
||||
zyt_patient_searcher,
|
||||
token,
|
||||
str(keyword or ""),
|
||||
int(page_no),
|
||||
int(page_size),
|
||||
)
|
||||
else:
|
||||
if zyt_api_url is None:
|
||||
raise RuntimeError("ZYT 患者接口地址未配置")
|
||||
client = ZytPatientClient(zyt_api_url(), token)
|
||||
result = await asyncio.to_thread(
|
||||
client.search_patients,
|
||||
str(keyword or ""),
|
||||
page_no=int(page_no),
|
||||
page_size=int(page_size),
|
||||
)
|
||||
if not isinstance(result, dict):
|
||||
raise ZytPatientError("ZYT 患者查询结果格式不正确")
|
||||
items = await asyncio.to_thread(store.cache_patients, list(result.get("items") or []), tenant)
|
||||
return {
|
||||
"items": items,
|
||||
"total": int(result.get("total") or len(items)),
|
||||
"page_no": int(result.get("page_no") or page_no),
|
||||
"page_size": int(result.get("page_size") or page_size),
|
||||
}
|
||||
|
||||
async def _patient_visible_to_tenant(
|
||||
tenant: str, patient_id: int
|
||||
) -> dict[str, Any] | None:
|
||||
"""绑定前重新确认该患者仍在当前 ZYT 账号的数据范围内。"""
|
||||
|
||||
token = await asyncio.to_thread(store.zyt_token, tenant)
|
||||
if zyt_patient_searcher is not None:
|
||||
result = await asyncio.to_thread(
|
||||
zyt_patient_searcher, token, str(int(patient_id)), 1, 50
|
||||
)
|
||||
items = list(result.get("items") or []) if isinstance(result, dict) else []
|
||||
return next(
|
||||
(
|
||||
dict(item)
|
||||
for item in items
|
||||
if isinstance(item, dict)
|
||||
and int(item.get("patient_id") or 0) == int(patient_id)
|
||||
),
|
||||
None,
|
||||
)
|
||||
if zyt_api_url is None:
|
||||
raise RuntimeError("ZYT 患者接口地址未配置")
|
||||
client = ZytPatientClient(zyt_api_url(), token)
|
||||
return await asyncio.to_thread(client.get_patient, int(patient_id))
|
||||
|
||||
@app.get("/api/v2/archive/stats")
|
||||
def archive_stats(
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:read")),
|
||||
) -> dict[str, Any]:
|
||||
return store.stats(resolve_admin_tenant(principal, account_id))
|
||||
|
||||
@app.get("/api/v2/archive/conversations")
|
||||
def archive_conversations(
|
||||
limit: int = 50,
|
||||
cursor: str = "",
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:content:read")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return store.conversations(
|
||||
limit, cursor, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/conversations/{conversation_id}/messages")
|
||||
def archive_messages(
|
||||
conversation_id: str,
|
||||
limit: int = 100,
|
||||
cursor: str = "",
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:content:read")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return store.messages(
|
||||
conversation_id,
|
||||
limit,
|
||||
cursor,
|
||||
resolve_admin_tenant(principal, account_id),
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/imports/messages")
|
||||
def archive_import_messages(
|
||||
body: ImportBody,
|
||||
request: Request,
|
||||
principal: Any = Depends(require("im:import")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return store.import_messages(
|
||||
body.model_dump(), principal.id, client_ip(request)
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/imports/metadata")
|
||||
def archive_import_metadata(
|
||||
body: MetadataBody,
|
||||
request: Request,
|
||||
principal: Any = Depends(require("im:import")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return store.sync_metadata(
|
||||
body.model_dump(), principal.id, client_ip(request)
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/desktop/checkpoint")
|
||||
def desktop_archive_checkpoint(
|
||||
external_account_id: str,
|
||||
source_table: str = "message_table",
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
if not str(external_account_id or "").strip():
|
||||
raise HTTPException(status_code=400, detail="账号标识不能为空")
|
||||
return {
|
||||
"checkpoint": store.source_checkpoint(
|
||||
external_account_id, source_table, str(account["tenant_id"])
|
||||
)
|
||||
}
|
||||
|
||||
@app.post("/api/v2/archive/desktop/checkpoint")
|
||||
def desktop_archive_advance_checkpoint(
|
||||
body: DesktopCheckpointBody,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"checkpoint": store.advance_source_checkpoint(
|
||||
body.source_account,
|
||||
body.source_table,
|
||||
body.checkpoint,
|
||||
str(account["tenant_id"]),
|
||||
)
|
||||
}
|
||||
|
||||
@app.get("/api/v2/archive/desktop/pending-attachments")
|
||||
def desktop_pending_attachments(
|
||||
external_account_id: str,
|
||||
limit: int = 500,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
if not str(external_account_id or "").strip():
|
||||
raise HTTPException(status_code=400, detail="账号标识不能为空")
|
||||
return {
|
||||
"source_message_ids": store.claim_pending_attachment_source_ids(
|
||||
external_account_id, limit, str(account["tenant_id"])
|
||||
)
|
||||
}
|
||||
|
||||
@app.post("/api/v2/archive/desktop/imports/messages")
|
||||
def desktop_archive_import_messages(
|
||||
body: ImportBody,
|
||||
request: Request,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
values = body.model_dump()
|
||||
values["tenant_id"] = str(account["tenant_id"])
|
||||
return store.import_messages(values, None, client_ip(request))
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/desktop/imports/metadata")
|
||||
def desktop_archive_import_metadata(
|
||||
body: MetadataBody,
|
||||
request: Request,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
values = body.model_dump()
|
||||
values["tenant_id"] = str(account["tenant_id"])
|
||||
return store.sync_metadata(values, None, client_ip(request))
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/people")
|
||||
def archive_people(
|
||||
limit: int = 100,
|
||||
keyword: str = "",
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"items": store.people(
|
||||
limit, keyword, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
}
|
||||
|
||||
@app.get("/api/v2/archive/people/{person_id}")
|
||||
def archive_person(
|
||||
person_id: str,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"person": store.person_detail(
|
||||
person_id, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/people/{person_id}/identities")
|
||||
def bind_archive_identity(
|
||||
person_id: str,
|
||||
body: IdentityBody,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"person": store.bind_identity(
|
||||
person_id,
|
||||
body.model_dump(),
|
||||
principal.id,
|
||||
client_ip(request),
|
||||
single_tenant(resolve_admin_tenant(principal, account_id)),
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/patients/search")
|
||||
async def search_zyt_patients(
|
||||
keyword: str,
|
||||
page_no: int = 1,
|
||||
page_size: int = 20,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
tenant = single_tenant(
|
||||
await asyncio.to_thread(resolve_admin_tenant, principal, account_id)
|
||||
)
|
||||
try:
|
||||
return await _search_patients_for_tenant(
|
||||
tenant, keyword, page_no, page_size
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/desktop/patient-context")
|
||||
def desktop_patient_context(
|
||||
external_account_id: str,
|
||||
conversation_external_id: str,
|
||||
person_id: str = "",
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
access = _desktop_patient_access(account)
|
||||
if not access["can_search"]:
|
||||
return {
|
||||
"available": False,
|
||||
"reason": str(access["reason"]),
|
||||
"people": [],
|
||||
"patient_bindings": [],
|
||||
"permissions": access,
|
||||
}
|
||||
try:
|
||||
context = store.conversation_patient_context(
|
||||
external_account_id,
|
||||
conversation_external_id,
|
||||
str(account["tenant_id"]),
|
||||
person_id=person_id,
|
||||
)
|
||||
return _context_with_access(context, access)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/desktop/patients/search")
|
||||
async def desktop_search_zyt_patients(
|
||||
keyword: str,
|
||||
page_no: int = 1,
|
||||
page_size: int = 20,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
_require_desktop_patient_access(account)
|
||||
try:
|
||||
return await _search_patients_for_tenant(
|
||||
str(account["tenant_id"]), keyword, page_no, page_size
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.put("/api/v2/archive/desktop/patient-binding")
|
||||
async def desktop_bind_archive_patient(
|
||||
body: DesktopPatientBindingBody,
|
||||
request: Request,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
tenant = str(account["tenant_id"])
|
||||
access = _require_desktop_patient_access(account)
|
||||
try:
|
||||
visible_patient = await _patient_visible_to_tenant(tenant, body.patient_id)
|
||||
if visible_patient is None:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="当前 ZYT 账号无权访问该患者,不能建立绑定",
|
||||
)
|
||||
context = await asyncio.to_thread(store.conversation_patient_context,
|
||||
body.external_account_id,
|
||||
body.conversation_external_id,
|
||||
tenant,
|
||||
person_id=body.person_id,
|
||||
)
|
||||
person = context.get("person")
|
||||
if not isinstance(person, dict) or not person.get("id"):
|
||||
if context.get("requires_person_selection"):
|
||||
raise ValueError("群聊中有多个联系人,请先选择需要绑定的联系人")
|
||||
raise ValueError(str(context.get("reason") or "当前会话没有可绑定的联系人"))
|
||||
binding = await asyncio.to_thread(store.bind_patient,
|
||||
str(person["id"]),
|
||||
body.model_dump(),
|
||||
None,
|
||||
client_ip(request),
|
||||
tenant,
|
||||
)
|
||||
return {
|
||||
"binding": binding,
|
||||
"context": _context_with_access(
|
||||
await asyncio.to_thread(store.conversation_patient_context,
|
||||
body.external_account_id,
|
||||
body.conversation_external_id,
|
||||
tenant,
|
||||
person_id=str(person["id"]),
|
||||
),
|
||||
access,
|
||||
),
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.delete("/api/v2/archive/desktop/patient-binding")
|
||||
def desktop_unbind_archive_patient(
|
||||
request: Request,
|
||||
external_account_id: str,
|
||||
conversation_external_id: str,
|
||||
binding_id: str,
|
||||
person_id: str = "",
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
tenant = str(account["tenant_id"])
|
||||
access = _require_desktop_patient_access(account)
|
||||
try:
|
||||
context = store.conversation_patient_context(
|
||||
external_account_id,
|
||||
conversation_external_id,
|
||||
tenant,
|
||||
person_id=person_id,
|
||||
)
|
||||
person = context.get("person")
|
||||
if not isinstance(person, dict) or not person.get("id"):
|
||||
raise ValueError("当前会话没有选中可解除绑定的联系人")
|
||||
store.unbind_patient(
|
||||
str(person["id"]), binding_id, None, client_ip(request), tenant
|
||||
)
|
||||
return {
|
||||
"context": _context_with_access(
|
||||
store.conversation_patient_context(
|
||||
external_account_id,
|
||||
conversation_external_id,
|
||||
tenant,
|
||||
person_id=str(person["id"]),
|
||||
),
|
||||
access,
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.put("/api/v2/archive/people/{person_id}/patient-bindings")
|
||||
def bind_archive_patient(
|
||||
person_id: str,
|
||||
body: PatientBindingBody,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
tenant = single_tenant(resolve_admin_tenant(principal, account_id))
|
||||
try:
|
||||
binding = store.bind_patient(
|
||||
person_id,
|
||||
body.model_dump(),
|
||||
principal.id,
|
||||
client_ip(request),
|
||||
tenant,
|
||||
)
|
||||
return {
|
||||
"binding": binding,
|
||||
"person": store.person_detail(person_id, tenant),
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.delete(
|
||||
"/api/v2/archive/people/{person_id}/patient-bindings/{binding_id}"
|
||||
)
|
||||
def unbind_archive_patient(
|
||||
person_id: str,
|
||||
binding_id: str,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:identity:write")),
|
||||
) -> dict[str, Any]:
|
||||
tenant = single_tenant(resolve_admin_tenant(principal, account_id))
|
||||
try:
|
||||
store.unbind_patient(
|
||||
person_id,
|
||||
binding_id,
|
||||
principal.id,
|
||||
client_ip(request),
|
||||
tenant,
|
||||
)
|
||||
return {"person": store.person_detail(person_id, tenant)}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/storage")
|
||||
def archive_storage(
|
||||
_: Any = Depends(require("im:storage:write")),
|
||||
) -> dict[str, Any]:
|
||||
return {"storage": store.storage_config()}
|
||||
|
||||
@app.put("/api/v2/archive/storage")
|
||||
def save_archive_storage(
|
||||
body: StorageBody,
|
||||
request: Request,
|
||||
principal: Any = Depends(require("im:storage:write")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"storage": store.save_storage_config(
|
||||
body.model_dump(), principal.id, client_ip(request)
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/storage/test")
|
||||
def test_archive_storage(
|
||||
request: Request,
|
||||
principal: Any = Depends(require("im:storage:write")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
result = store.test_storage()
|
||||
database.audit(
|
||||
principal.id,
|
||||
"archive.storage.test",
|
||||
f"ok={int(bool(result.get('ok')))} bucket={result.get('bucket', '')}",
|
||||
client_ip(request),
|
||||
)
|
||||
return {"result": result}
|
||||
except Exception as exc:
|
||||
database.audit(
|
||||
principal.id,
|
||||
"archive.storage.test",
|
||||
f"ok=0 error={str(exc)[:500]}",
|
||||
client_ip(request),
|
||||
)
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/media")
|
||||
def archive_media(
|
||||
limit: int = 100,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:content:read")),
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"items": store.media_items(
|
||||
limit, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
}
|
||||
|
||||
@app.post("/api/v2/archive/media/access-urls")
|
||||
def archive_media_access_urls(
|
||||
body: MediaAccessBody,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:content:read")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
items = store.media_download_urls(
|
||||
body.media_ids,
|
||||
body.expires,
|
||||
resolve_admin_tenant(principal, account_id),
|
||||
)
|
||||
database.audit(
|
||||
principal.id,
|
||||
"archive.media.access",
|
||||
f"count={len(items)}",
|
||||
client_ip(request),
|
||||
)
|
||||
return {"items": items}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/media/prepare")
|
||||
def prepare_archive_media(
|
||||
body: MediaPrepareBody,
|
||||
_: Any = Depends(require("im:import")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return store.prepare_media(body.model_dump())
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/desktop/media/prepare")
|
||||
def desktop_prepare_archive_media(
|
||||
body: MediaPrepareBody,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
values = body.model_dump()
|
||||
values["tenant_id"] = str(account["tenant_id"])
|
||||
return store.prepare_media(values)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/media/{media_id}/complete")
|
||||
def complete_archive_media(
|
||||
media_id: str,
|
||||
_: Any = Depends(require("im:import")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {"media": store.complete_media(media_id)}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/media/{media_id}/multipart-complete")
|
||||
def complete_archive_multipart_media(
|
||||
media_id: str,
|
||||
body: MediaMultipartCompleteBody,
|
||||
_: Any = Depends(require("im:import")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"media": store.complete_multipart_media(
|
||||
media_id,
|
||||
body.upload_id,
|
||||
[part.model_dump() for part in body.parts],
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/desktop/media/{media_id}/complete")
|
||||
def desktop_complete_archive_media(
|
||||
media_id: str,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"media": store.complete_media(media_id, str(account["tenant_id"]))
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/desktop/media/{media_id}/multipart-complete")
|
||||
def desktop_complete_archive_multipart_media(
|
||||
media_id: str,
|
||||
body: MediaMultipartCompleteBody,
|
||||
account: Any = Depends(current_desktop),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"media": store.complete_multipart_media(
|
||||
media_id,
|
||||
body.upload_id,
|
||||
[part.model_dump() for part in body.parts],
|
||||
str(account["tenant_id"]),
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/media/{media_id}/view")
|
||||
def view_archive_media(
|
||||
media_id: str,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:content:read")),
|
||||
) -> RedirectResponse:
|
||||
try:
|
||||
url = store.media_download_url(
|
||||
media_id, tenant_id=resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
database.audit(
|
||||
principal.id, "archive.media.view", f"media={media_id}", client_ip(request)
|
||||
)
|
||||
return RedirectResponse(url=url, status_code=307)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.post("/api/v2/archive/exports")
|
||||
def create_archive_export(
|
||||
body: ExportBody,
|
||||
request: Request,
|
||||
background: BackgroundTasks,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:export")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
job = store.create_export_job(
|
||||
body.formats,
|
||||
body.filters,
|
||||
principal.id,
|
||||
client_ip(request),
|
||||
single_tenant(resolve_admin_tenant(principal, account_id)),
|
||||
)
|
||||
background.add_task(run_export, job["id"])
|
||||
return {"job": job}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/exports")
|
||||
def archive_exports(
|
||||
limit: int = 100,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:export")),
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"jobs": store.export_jobs(
|
||||
limit, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
}
|
||||
|
||||
@app.get("/api/v2/archive/exports/{job_id}")
|
||||
def archive_export(
|
||||
job_id: str,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:export")),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
return {
|
||||
"job": store.export_job(
|
||||
job_id, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
}
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
@app.get("/api/v2/archive/export-files/{file_id}/download")
|
||||
def download_archive_export(
|
||||
file_id: str,
|
||||
request: Request,
|
||||
account_id: int | None = None,
|
||||
principal: Any = Depends(require("im:export")),
|
||||
):
|
||||
try:
|
||||
item = store.export_file(
|
||||
file_id, resolve_admin_tenant(principal, account_id)
|
||||
)
|
||||
database.audit(
|
||||
principal.id,
|
||||
"archive.export.download",
|
||||
f"file={file_id} job={item['job_id']}",
|
||||
client_ip(request),
|
||||
)
|
||||
if item["storage_status"] == "cos":
|
||||
return RedirectResponse(
|
||||
url=store.export_download_url(file_id), status_code=307
|
||||
)
|
||||
path = Path(item["local_path"]).resolve()
|
||||
root = store.export_root.resolve()
|
||||
if not path.is_relative_to(root) or not path.is_file():
|
||||
raise KeyError("导出文件已不在本机")
|
||||
return FileResponse(
|
||||
path, filename=item["file_name"], media_type="application/octet-stream"
|
||||
)
|
||||
except Exception as exc:
|
||||
raise _http_error(exc) from exc
|
||||
|
||||
return store
|
||||
@@ -0,0 +1,193 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""ZYT 患者只读 API 适配器。
|
||||
|
||||
这个模块只调用 ZYT 已有的管理端查询接口,不要求 ZYT 增加路由、字段或数据表。
|
||||
调用方传入桌面端已经取得的 ZYT token;本模块不会持久化账号密码。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import socket
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from typing import Any
|
||||
|
||||
|
||||
class ZytPatientError(RuntimeError):
|
||||
"""ZYT 患者查询失败。"""
|
||||
|
||||
|
||||
class ZytPatientSessionExpired(ZytPatientError):
|
||||
"""The upstream patient session needs reauthentication, not desktop logout."""
|
||||
|
||||
|
||||
class ZytPatientPermissionDenied(ZytPatientError):
|
||||
"""The authenticated ZYT account cannot query patients."""
|
||||
|
||||
|
||||
def _session_expired_message(message: str) -> bool:
|
||||
normalized = str(message or "").lower().replace(" ", "")
|
||||
return any(part in normalized for part in (
|
||||
"登录超时", "登录已失效", "登录失效", "登录已过期", "登录过期",
|
||||
"请重新登录", "请先登录", "token过期", "token已过期", "token失效",
|
||||
"token已失效", "tokenexpired", "unauthorized",
|
||||
))
|
||||
|
||||
|
||||
def mask_mobile(value: Any) -> str:
|
||||
text = str(value or "").strip()
|
||||
if len(text) >= 7:
|
||||
return f"{text[:3]}****{text[-4:]}"
|
||||
if len(text) >= 3:
|
||||
return f"{text[:1]}***{text[-1:]}"
|
||||
return "***" if text else ""
|
||||
|
||||
|
||||
class ZytPatientClient:
|
||||
def __init__(self, api_url: str, token: str, *, timeout: float = 10.0):
|
||||
self.api_url = str(api_url or "").strip().rstrip("/")
|
||||
self.token = str(token or "").strip()
|
||||
self.timeout = max(2.0, min(float(timeout), 30.0))
|
||||
parsed = urllib.parse.urlparse(self.api_url)
|
||||
if parsed.scheme not in {"http", "https"} or not parsed.netloc or parsed.username:
|
||||
raise ZytPatientError("ZYT 患者接口地址配置不正确")
|
||||
if not self.token:
|
||||
raise ZytPatientSessionExpired("ZYT 患者查询会话缺失,请重新验证账号")
|
||||
|
||||
def _get(self, path: str, params: dict[str, Any]) -> Any:
|
||||
query = urllib.parse.urlencode(
|
||||
{key: value for key, value in params.items() if value not in (None, "")}
|
||||
)
|
||||
url = f"{self.api_url}{path}"
|
||||
if query:
|
||||
url = f"{url}?{query}"
|
||||
request = urllib.request.Request(
|
||||
url,
|
||||
headers={
|
||||
"Accept": "application/json",
|
||||
"User-Agent": "WeCom-RPA-Patient-Bridge/1.0",
|
||||
# ZYT 管理端中间件读取 token 头,不使用 Bearer。
|
||||
"token": self.token,
|
||||
},
|
||||
method="GET",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=self.timeout) as response:
|
||||
payload = json.loads(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as exc:
|
||||
if exc.code == 401:
|
||||
raise ZytPatientSessionExpired("ZYT 患者查询登录已过期,请重新验证账号") from exc
|
||||
if exc.code == 403:
|
||||
raise ZytPatientPermissionDenied("当前 ZYT 账号没有患者查询权限") from exc
|
||||
raise ZytPatientError(f"ZYT 患者接口请求失败(HTTP {exc.code})") from exc
|
||||
except (urllib.error.URLError, TimeoutError, socket.timeout) as exc:
|
||||
raise ZytPatientError(
|
||||
f"无法连接 ZYT 患者接口:{getattr(exc, 'reason', exc)}"
|
||||
) from exc
|
||||
except (ValueError, TypeError, UnicodeDecodeError) as exc:
|
||||
raise ZytPatientError("ZYT 患者接口返回了无效数据") from exc
|
||||
if not isinstance(payload, dict) or str(payload.get("code")) != "1":
|
||||
message = str(payload.get("msg") or "").strip() if isinstance(payload, dict) else ""
|
||||
if "权限" in message or "无权" in message:
|
||||
raise ZytPatientPermissionDenied(message)
|
||||
if (isinstance(payload, dict) and str(payload.get("code")) == "-1") or _session_expired_message(message):
|
||||
raise ZytPatientSessionExpired(message or "ZYT 患者查询会话已失效")
|
||||
raise ZytPatientError(message or "ZYT 患者查询失败")
|
||||
return payload.get("data")
|
||||
|
||||
@staticmethod
|
||||
def _list_payload(data: Any) -> tuple[list[dict[str, Any]], int]:
|
||||
if isinstance(data, list):
|
||||
return [dict(item) for item in data if isinstance(item, dict)], len(data)
|
||||
if not isinstance(data, dict):
|
||||
return [], 0
|
||||
raw = data.get("lists")
|
||||
if not isinstance(raw, list):
|
||||
raw = data.get("items")
|
||||
if not isinstance(raw, list):
|
||||
raw = data.get("data")
|
||||
rows = [dict(item) for item in raw if isinstance(item, dict)] if isinstance(raw, list) else []
|
||||
total = data.get("count", data.get("total", len(rows)))
|
||||
try:
|
||||
total_value = max(0, int(total))
|
||||
except (TypeError, ValueError):
|
||||
total_value = len(rows)
|
||||
return rows, total_value
|
||||
|
||||
def search_patients(
|
||||
self, keyword: str, *, page_no: int = 1, page_size: int = 20
|
||||
) -> dict[str, Any]:
|
||||
keyword = str(keyword or "").strip()
|
||||
if not keyword:
|
||||
raise ValueError("请输入患者姓名、手机号或患者编号")
|
||||
if len(keyword) > 64:
|
||||
raise ValueError("患者搜索关键词不能超过 64 个字符")
|
||||
page_no = max(1, int(page_no))
|
||||
page_size = max(1, min(int(page_size), 50))
|
||||
data = self._get(
|
||||
"/adminapi/tcm.diagnosis/lists",
|
||||
{"keyword": keyword, "page_no": page_no, "page_size": page_size},
|
||||
)
|
||||
rows, total = self._list_payload(data)
|
||||
|
||||
# 诊单列表中同一患者可能出现多次。保留接口返回顺序中的第一条(通常是最新诊单)。
|
||||
patients: list[dict[str, Any]] = []
|
||||
seen: set[int] = set()
|
||||
for row in rows:
|
||||
try:
|
||||
diagnosis_id = int(row.get("id") or 0)
|
||||
patient_id = int(row.get("patient_id") or diagnosis_id)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if patient_id <= 0 or patient_id in seen:
|
||||
continue
|
||||
seen.add(patient_id)
|
||||
patients.append(
|
||||
{
|
||||
"patient_id": patient_id,
|
||||
"diagnosis_id": max(0, diagnosis_id),
|
||||
"patient_name": str(row.get("patient_name") or "").strip(),
|
||||
"phone_masked": mask_mobile(row.get("phone")),
|
||||
"gender": row.get("gender"),
|
||||
"age": row.get("age"),
|
||||
"source_update_time": str(row.get("update_time") or ""),
|
||||
}
|
||||
)
|
||||
return {
|
||||
"items": patients,
|
||||
"total": total,
|
||||
"page_no": page_no,
|
||||
"page_size": page_size,
|
||||
}
|
||||
|
||||
def get_patient(self, patient_id: int) -> dict[str, Any] | None:
|
||||
"""按患者主键精确读取,并继续复用 ZYT 列表的数据权限过滤。"""
|
||||
|
||||
patient_id = int(patient_id)
|
||||
if patient_id <= 0:
|
||||
raise ValueError("患者编号不正确")
|
||||
data = self._get(
|
||||
"/adminapi/tcm.diagnosis/lists",
|
||||
{"patient_id": patient_id, "page_no": 1, "page_size": 20},
|
||||
)
|
||||
rows, _total = self._list_payload(data)
|
||||
for row in rows:
|
||||
try:
|
||||
diagnosis_id = int(row.get("id") or 0)
|
||||
resolved_patient_id = int(row.get("patient_id") or diagnosis_id)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if resolved_patient_id != patient_id:
|
||||
continue
|
||||
return {
|
||||
"patient_id": resolved_patient_id,
|
||||
"diagnosis_id": max(0, diagnosis_id),
|
||||
"patient_name": str(row.get("patient_name") or "").strip(),
|
||||
"phone_masked": mask_mobile(row.get("phone")),
|
||||
"gender": row.get("gender"),
|
||||
"age": row.get("age"),
|
||||
"source_update_time": str(row.get("update_time") or ""),
|
||||
}
|
||||
return None
|
||||
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"path": "wechat_rpa/admin_backend.py",
|
||||
"sha256": "977c524e10db2df8fafba2058dc30e5837521de604f2723a7db4b5e2ba5c3107",
|
||||
"bytes": 161057
|
||||
},
|
||||
{
|
||||
"path": "wechat_rpa/archive_api.py",
|
||||
"sha256": "0acb73850380a9f39e470aead6e92a124de63e4a1f0a8bb9a5d3f02ebfc84079",
|
||||
"bytes": 62658
|
||||
},
|
||||
{
|
||||
"path": "wechat_rpa/zyt_order_client.py",
|
||||
"sha256": "e56d6da4ba06006a752261a5ac167b4d885defed2ee5702ffd0c9ab252929a1a",
|
||||
"bytes": 11974
|
||||
},
|
||||
{
|
||||
"path": "wechat_rpa/zyt_patient_client.py",
|
||||
"sha256": "3462350e066314e62ba99ea79aea8725da4e1e236b71a4869f595b3e259b85ab",
|
||||
"bytes": 10311
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_order_api.py",
|
||||
"sha256": "2b65a6eadac728603a45bf088d977e012c4a565b02ce8b878313d1b0027756e4",
|
||||
"bytes": 18611
|
||||
},
|
||||
{
|
||||
"path": "tests/test_zyt_patient_client.py",
|
||||
"sha256": "a3801fb7a69628aa4c9f396e2348236296b2306568d11cc04b95ff7aa7ff6fd3",
|
||||
"bytes": 4968
|
||||
},
|
||||
{
|
||||
"path": "tests/test_archive_api.py",
|
||||
"sha256": "9a9a59945a0a0e2c082ef1d2fe7800c269041469132e336e8766edc0f224ed06",
|
||||
"bytes": 51682
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"release": "order-mcp-20260922",
|
||||
"candidateRoot": "C:/kefu/wechat_rpa",
|
||||
"windowsRoot": "C:/wechat_rpa",
|
||||
"backendFiles": [
|
||||
"archive_api.py",
|
||||
"admin_backend.py",
|
||||
"zyt_patient_client.py"
|
||||
],
|
||||
"newBackendFiles": [
|
||||
"zyt_order_client.py"
|
||||
],
|
||||
"serverTestModules": [
|
||||
"test_zyt_order_api",
|
||||
"test_zyt_patient_client",
|
||||
"test_archive_api"
|
||||
],
|
||||
"schemaMigration": false,
|
||||
"notes": "Read-only patient order proxy for the desktop order MCP. No table changes; audit_log gains new action names only."
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
"""Read-only baseline / candidate / deployed verification. Prints hashes and status only."""
|
||||
from pathlib import Path
|
||||
import argparse, hashlib, json, subprocess, urllib.request, urllib.error
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('mode', choices=['baseline', 'candidate', 'deployed'])
|
||||
args = parser.parse_args()
|
||||
RELEASE = 'order-mcp-20260922'
|
||||
folder = Path(__file__).resolve().parent
|
||||
project = Path('/opt/im-admin')
|
||||
base = json.loads((folder / 'server-baseline-order.json').read_text())
|
||||
manifest = json.loads((folder / 'order-manifest.json').read_text())
|
||||
containers = ['im-admin-api-1', 'im-admin-gateway-1', 'im-admin-knowledge-worker-1']
|
||||
image = lambda ref: subprocess.check_output(['docker', 'image', 'inspect', ref, '--format', '{{.Id}}'], text=True).strip()
|
||||
sha = lambda data: hashlib.sha256(data).hexdigest()
|
||||
|
||||
# Files that must match on the host and inside the running container.
|
||||
expected = dict(base['expected'])
|
||||
if args.mode != 'baseline':
|
||||
for row in manifest:
|
||||
if row['path'].startswith('wechat_rpa/'):
|
||||
expected[Path(row['path']).name] = row['sha256']
|
||||
|
||||
# The payload itself must be intact.
|
||||
for row in manifest:
|
||||
path = folder / ('payload/' + row['path'] if row['path'].startswith('wechat_rpa/') else row['path'])
|
||||
assert path.resolve().is_relative_to(folder.resolve())
|
||||
assert path.stat().st_size == row['bytes'] and sha(path.read_bytes()) == row['sha256'], row['path']
|
||||
|
||||
current = image('zyt/wecom-admin:current')
|
||||
if args.mode == 'baseline':
|
||||
# Code drift is the real signal; the image id is recorded, not assumed.
|
||||
for container in containers:
|
||||
actual = subprocess.check_output(['docker', 'inspect', container, '--format', '{{.Image}}'], text=True).strip()
|
||||
assert actual == current, 'Running container is not on zyt/wecom-admin:current: ' + container
|
||||
for name in base.get('must_not_exist', []):
|
||||
assert not (project / 'wechat_rpa' / name).exists(), 'Unexpected existing file: ' + name
|
||||
|
||||
if args.mode != 'candidate':
|
||||
for name, wanted in expected.items():
|
||||
assert sha((project / 'wechat_rpa' / name).read_bytes()) == wanted, 'Host drift: ' + name
|
||||
code = ('from pathlib import Path;import hashlib,json,sys;names=json.load(sys.stdin);'
|
||||
'print(json.dumps({n:hashlib.sha256((Path("/app/wechat_rpa")/n).read_bytes()).hexdigest() for n in names}))')
|
||||
actual = json.loads(subprocess.check_output(
|
||||
['docker', 'exec', '-i', 'im-admin-api-1', 'python', '-c', code], input=json.dumps(list(expected)).encode()))
|
||||
assert actual == expected, 'Container code differs from expected'
|
||||
|
||||
if args.mode == 'deployed':
|
||||
wanted = image('zyt/wecom-admin:' + RELEASE)
|
||||
assert current == wanted
|
||||
for name in containers:
|
||||
raw = json.loads(subprocess.check_output(['docker', 'inspect', name]))[0]
|
||||
assert raw['Image'] == wanted and raw['State']['Running'] and raw['RestartCount'] == 0, name
|
||||
assert raw['State'].get('Health', {}).get('Status', 'not_configured') in ('healthy', 'not_configured'), name
|
||||
for url in ['http://127.0.0.1:18766/api/v2/health', 'http://127.0.0.1:18770/health']:
|
||||
with urllib.request.urlopen(url, timeout=15) as response:
|
||||
assert response.status == 200
|
||||
# New order routes must exist and must reject anonymous reads. No real patient is queried.
|
||||
for path in ['/api/v2/archive/desktop/patient-orders/summary', '/api/v2/archive/desktop/patient-orders',
|
||||
'/api/v2/archive/desktop/patient-orders/1/tracking']:
|
||||
try:
|
||||
urllib.request.urlopen('http://127.0.0.1:18766' + path
|
||||
+ '?external_account_id=synthetic&conversation_external_id=synthetic', timeout=15)
|
||||
except urllib.error.HTTPError as exc:
|
||||
assert exc.code in (401, 403), (path, exc.code)
|
||||
else:
|
||||
raise AssertionError('Order API accessible without authentication: ' + path)
|
||||
|
||||
print(json.dumps({'mode': args.mode, 'image': current, 'files': len(expected), 'status': 'passed', 'patientDataRead': False}))
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user