mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-12 18:18:10 -10:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbc255813d | ||
|
|
c8be6163e5 | ||
|
|
911e70dfdb | ||
|
|
55ca20bc85 | ||
|
|
622a493078 |
No files matched your search
@@ -1313,7 +1313,7 @@ jobs:
|
||||
# Main-only GitHub Actions cache backend; see the Safety gate job.
|
||||
if: needs.changes.outputs.heavy == 'true' && (matrix.os != 'ubuntu-latest' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request') && github.ref == 'refs/heads/main'
|
||||
- name: Enable sccache
|
||||
if: needs.changes.outputs.heavy == 'true' && (matrix.os != 'ubuntu-latest' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request') && steps.sccache.outcome == 'success'
|
||||
if: needs.changes.outputs.heavy == 'true' && (matrix.os != 'ubuntu-latest' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request') && steps.sccache.outcome == 'success' && matrix.os != 'windows-latest'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "SCCACHE_GHA_ENABLED=true" >> "${GITHUB_ENV}"
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
id: sccache
|
||||
continue-on-error: true
|
||||
- name: Enable sccache
|
||||
if: steps.sccache.outcome == 'success'
|
||||
if: steps.sccache.outcome == 'success' && runner.os != 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
{
|
||||
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
id: sccache
|
||||
continue-on-error: true
|
||||
- name: Enable sccache
|
||||
if: steps.sccache.outcome == 'success'
|
||||
if: steps.sccache.outcome == 'success' && runner.os != 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
{
|
||||
|
||||
Generated
-1
@@ -1179,7 +1179,6 @@ dependencies = [
|
||||
"agent-client-protocol",
|
||||
"agent-client-protocol-schema",
|
||||
"anyhow",
|
||||
"arboard",
|
||||
"async-stream",
|
||||
"async-trait",
|
||||
"axum",
|
||||
|
||||
@@ -219,9 +219,6 @@ libc = "0.2"
|
||||
windows-sys = { version = "0.61.2", features = ["Wdk_Storage_FileSystem", "Win32_System_IO", "Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Security_Isolation", "Win32_Storage_FileSystem", "Win32_System_LibraryLoader", "Win32_System_Pipes", "Win32_System_Threading", "Win32_System_SystemServices", "Win32_System_WindowsProgramming"] }
|
||||
|
||||
|
||||
[target.'cfg(any(target_os = "macos", target_os = "windows", all(target_os = "linux", not(target_env = "ohos"))))'.dependencies]
|
||||
arboard = { version = "3.4", features = ["wayland-data-control"] }
|
||||
|
||||
[target.'cfg(not(target_env = "ohos"))'.dependencies]
|
||||
portable-pty = "0.9"
|
||||
|
||||
|
||||
@@ -51,6 +51,13 @@ fn resolve(
|
||||
directory
|
||||
.parent()
|
||||
.ok_or("test deps directory has no parent")?
|
||||
} else if directory.ends_with("out") {
|
||||
directory
|
||||
.ancestors()
|
||||
.skip(1)
|
||||
.find(|ancestor| ancestor.ends_with("build"))
|
||||
.and_then(Path::parent)
|
||||
.unwrap_or(directory)
|
||||
} else {
|
||||
directory
|
||||
};
|
||||
@@ -200,4 +207,27 @@ mod tests {
|
||||
assert_eq!(resolve(None, None, &test, &target).unwrap(), canonical);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn per_unit_build_layout_resolves_the_final_target_and_cross_profile() {
|
||||
let root = tempfile::TempDir::new().unwrap();
|
||||
let target = root.path().join("final target");
|
||||
for triple in [None, Some("aarch64-unknown-linux-gnu")] {
|
||||
let final_profile = match triple {
|
||||
Some(triple) => target.join(triple).join("debug"),
|
||||
None => target.join("debug"),
|
||||
};
|
||||
std::fs::create_dir_all(&final_profile).unwrap();
|
||||
let canonical =
|
||||
final_profile.join(format!("codewhale{}", std::env::consts::EXE_SUFFIX));
|
||||
std::fs::write(&canonical, b"canonical").unwrap();
|
||||
let test = final_profile
|
||||
.join("build")
|
||||
.join("codewhale-tui")
|
||||
.join("0123456789abcdef")
|
||||
.join("out")
|
||||
.join("integration-hash");
|
||||
assert_eq!(resolve(None, None, &test, &target).unwrap(), canonical);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,6 +172,15 @@ exports; the x64 profile now allows 471 pairs and the ARM64 profile 473. The
|
||||
same limit applies: the candidate still has to pass the import check against
|
||||
its final executable bytes, and neither addition is a 14393 or installer run.
|
||||
|
||||
Release candidate run 43320217667, built after the stable toolchain moved to
|
||||
Rust 1.100.0, stopped the check on two more kernel32.dll pairs,
|
||||
`GetLogicalDrives` and `QueryDosDeviceW`, which the Rust 1.100.0 standard
|
||||
library's Windows file system code imports. Probe run 43330905781 (Windows 11
|
||||
ARM64 build 26200.9725) resolved all 449 imports of that candidate's ARM64
|
||||
executables. For x64 the 2 pairs are documented Microsoft API contracts
|
||||
(Windows XP minimum on each function's reference page); the x64 profile now
|
||||
allows 473 pairs and the ARM64 profile 475, with the same limits as above.
|
||||
|
||||
At this snapshot, startup/installation of the final release bytes on an actual
|
||||
1607 machine and the candidate's generated uninstaller were still unqualified.
|
||||
The final frozen source, release import dumps, archive/native/npm installation,
|
||||
|
||||
@@ -132,6 +132,8 @@ x64 没有导出探测,因此这 12 对作为低于 14393 下限的微软文
|
||||
x64 的这 3 对作为微软文档 API 契约记录(各函数参考页的最低客户端为 Windows XP),与 #6953 报告者实测导出分开标注;x64 允许列表现为 471 对,ARM64 为 473 对。
|
||||
限制不变:候选仍须以最终可执行文件通过导入检查,两项新增都不是 14393 或安装器运行。
|
||||
|
||||
候选运行 43320217667 在稳定工具链升级到 Rust 1.100.0 后,又在 kernel32.dll 的 `GetLogicalDrives` 与 `QueryDosDeviceW` 两对上停止;它们来自 Rust 1.100.0 标准库的 Windows 文件系统代码。探测运行 43330905781(Windows 11 ARM64 build 26200.9725)解析了该候选 ARM64 可执行文件的全部 449 个导入。x64 的这 2 对作为微软文档 API 契约记录(各函数参考页的最低客户端为 Windows XP);x64 允许列表现为 473 对,ARM64 为 475 对,限制同上。
|
||||
|
||||
此快照中,最终发布文件在真实 1607 上启动/安装及候选程序生成的卸载器仍未验收。
|
||||
最终冻结源码、发布导入记录、各安装途径、打包/原生应用崩溃恢复和最低 OS 回执应
|
||||
进入发布验收记录,见[英文发布检查单](../RELEASE_CHECKLIST.md)。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"osArchitecture": "x64",
|
||||
"qualification": {
|
||||
"result": "PASS",
|
||||
"kind": "reporter exact-OS export resolution plus 15 documented Microsoft named API minima",
|
||||
"kind": "reporter exact-OS export resolution plus 17 documented Microsoft named API minima",
|
||||
"evidence": {
|
||||
"issue": "https://github.com/codewhale-hq/Codewhale/issues/6953",
|
||||
"binary": "https://github.com/codewhale-hq/Codewhale/releases/download/v0.10.1/codewhale-windows-x64.exe",
|
||||
@@ -16,7 +16,7 @@
|
||||
"previous_sha256": "f7b35a1e928f67884637f36b01fc72854f50690130f191bac3bcf62ece3c1d84"
|
||||
},
|
||||
"runtimeAcceptance": "Final 0.10.2 release bytes on 14393 not run",
|
||||
"qualifiedPairs": 471,
|
||||
"qualifiedPairs": 473,
|
||||
"namedApiContracts": [
|
||||
{
|
||||
"dll": "advapi32.dll",
|
||||
@@ -107,6 +107,18 @@
|
||||
"symbol": "GetSidSubAuthorityCount",
|
||||
"minimumClient": "Windows XP",
|
||||
"source": "https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-getsidsubauthoritycount"
|
||||
},
|
||||
{
|
||||
"dll": "kernel32.dll",
|
||||
"symbol": "GetLogicalDrives",
|
||||
"minimumClient": "Windows XP",
|
||||
"source": "https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getlogicaldrives"
|
||||
},
|
||||
{
|
||||
"dll": "kernel32.dll",
|
||||
"symbol": "QueryDosDeviceW",
|
||||
"minimumClient": "Windows XP",
|
||||
"source": "https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-querydosdevicew"
|
||||
}
|
||||
],
|
||||
"namedApiContractEvidence": {
|
||||
@@ -128,6 +140,17 @@
|
||||
"advapi32.dll!GetSidSubAuthorityCount"
|
||||
],
|
||||
"scope": "Three pairs from crates/config private_directory.rs; documentation-backed static contracts, same limits as above"
|
||||
},
|
||||
{
|
||||
"candidateRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43320217667",
|
||||
"source": "b97e38645f13f9f5828fd8a013f414955f46d528",
|
||||
"binarySha256": "b9abea95d29ed0c6caae1373675f7e45e6fe6099b15dae9a99ac64f170263681",
|
||||
"importReceiptSha256": "9bfddf3ed0633d23184b402cb02a880306847a6de43116bd1fabd19bea764544",
|
||||
"pairs": [
|
||||
"kernel32.dll!GetLogicalDrives",
|
||||
"kernel32.dll!QueryDosDeviceW"
|
||||
],
|
||||
"scope": "Two pairs that the Rust 1.100.0 standard library's Windows file system code imports (the toolchain, not a Codewhale call site); documentation-backed static contracts, same limits as above"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -421,6 +444,7 @@
|
||||
"GetFullPathNameA",
|
||||
"GetFullPathNameW",
|
||||
"GetLastError",
|
||||
"GetLogicalDrives",
|
||||
"GetModuleFileNameW",
|
||||
"GetModuleHandleA",
|
||||
"GetModuleHandleExA",
|
||||
@@ -487,6 +511,7 @@
|
||||
"PostQueuedCompletionStatus",
|
||||
"Process32FirstW",
|
||||
"Process32NextW",
|
||||
"QueryDosDeviceW",
|
||||
"QueryInformationJobObject",
|
||||
"QueryPerformanceCounter",
|
||||
"QueryPerformanceFrequency",
|
||||
@@ -666,25 +691,25 @@
|
||||
"qualification": {
|
||||
"result": "PASS",
|
||||
"kind": "exact native system export resolution",
|
||||
"time": "2026-11-12T10:08:11.6545236Z",
|
||||
"time": "2026-11-12T23:41:18.0140691Z",
|
||||
"osVersion": "10.0.26200.0",
|
||||
"osBuild": "26200.9725",
|
||||
"processArchitecture": "ARM64",
|
||||
"runner": "GitHub-hosted windows-11-arm; its registry ProductName reads \"Windows 10 Enterprise\", as Windows 11 reports it",
|
||||
"source": "f5a3dda9755170aeafecd0841347a5578a540290",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/f5a3dda9755170aeafecd0841347a5578a540290",
|
||||
"binarySha256": "c8c6f97d0ccf20e392b2457cb970187e79a29caa28d091dbfefe3a1393b99040",
|
||||
"source": "b97e38645f13f9f5828fd8a013f414955f46d528",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/b97e38645f13f9f5828fd8a013f414955f46d528",
|
||||
"binarySha256": "4d7dfba5955681c0e0d7cb6076a7e1e2ecf253711dcfb2931618ee97ccfdb470",
|
||||
"binaries": [
|
||||
"codewhale-windows-arm64.exe",
|
||||
"codew-windows-arm64.exe",
|
||||
"codewhale-tui-windows-arm64.exe"
|
||||
],
|
||||
"resolved": 447,
|
||||
"resolved": 449,
|
||||
"unresolved": 0,
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43186389246",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43197611105",
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43320217667",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43330905781",
|
||||
"probeWorkflow": ".github/workflows/windows-arm64-export-probe.yml",
|
||||
"profile": "dist, built by release-artifacts.yml (windows-arm64 job) in release candidate run 43186389246",
|
||||
"profile": "dist, built by release-artifacts.yml (windows-arm64 job) in release candidate run 43320217667",
|
||||
"runtimeAcceptance": "Static export resolution only; this probe did not launch the release executables. The only ARM64 runtime acceptance is the cf7199b52e debug application run of 2026-10-13; the packaged release and older OS builds are unproven",
|
||||
"exportProbeMethod": "ARM64 process: LoadLibraryExW per imported DLL with LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000800), then GetProcAddress for every imported symbol; module path and SHA256 recorded",
|
||||
"scope": "System-context export resolution only; no Authenticode check, oldest supported OS, or ordinary-user install inference",
|
||||
@@ -718,25 +743,25 @@
|
||||
"supersedes": {
|
||||
"result": "PASS",
|
||||
"kind": "exact native system export resolution",
|
||||
"time": "2026-11-07T16:01:13.7658879Z",
|
||||
"time": "2026-11-12T10:08:11.6545236Z",
|
||||
"osVersion": "10.0.26200.0",
|
||||
"osBuild": "26200.9725",
|
||||
"processArchitecture": "ARM64",
|
||||
"runner": "GitHub-hosted windows-11-arm; its registry ProductName reads \"Windows 10 Enterprise\", as Windows 11 reports it",
|
||||
"source": "549ff01ebb78856408164058fcb52db1e639ee0d",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/549ff01ebb78856408164058fcb52db1e639ee0d",
|
||||
"binarySha256": "38558ab2b4dc54590503543a0a584c5a82da6f078dd616b5b68e301bf09621b0",
|
||||
"source": "f5a3dda9755170aeafecd0841347a5578a540290",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/f5a3dda9755170aeafecd0841347a5578a540290",
|
||||
"binarySha256": "c8c6f97d0ccf20e392b2457cb970187e79a29caa28d091dbfefe3a1393b99040",
|
||||
"binaries": [
|
||||
"codewhale-windows-arm64.exe",
|
||||
"codew-windows-arm64.exe",
|
||||
"codewhale-tui-windows-arm64.exe"
|
||||
],
|
||||
"resolved": 444,
|
||||
"resolved": 447,
|
||||
"unresolved": 0,
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/42381818665",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/42389141087",
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43186389246",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/43197611105",
|
||||
"probeWorkflow": ".github/workflows/windows-arm64-export-probe.yml",
|
||||
"profile": "dist, built by release-artifacts.yml (windows-arm64 job) in release candidate run 42381818665",
|
||||
"profile": "dist, built by release-artifacts.yml (windows-arm64 job) in release candidate run 43186389246",
|
||||
"runtimeAcceptance": "Static export resolution only; this probe did not launch the release executables. The only ARM64 runtime acceptance is the cf7199b52e debug application run of 2026-10-13; the packaged release and older OS builds are unproven",
|
||||
"exportProbeMethod": "ARM64 process: LoadLibraryExW per imported DLL with LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000800), then GetProcAddress for every imported symbol; module path and SHA256 recorded",
|
||||
"scope": "System-context export resolution only; no Authenticode check, oldest supported OS, or ordinary-user install inference",
|
||||
@@ -770,66 +795,119 @@
|
||||
"supersedes": {
|
||||
"result": "PASS",
|
||||
"kind": "exact native system export resolution",
|
||||
"time": "2026-10-16T10:57:53.0754367Z",
|
||||
"time": "2026-11-07T16:01:13.7658879Z",
|
||||
"osVersion": "10.0.26200.0",
|
||||
"osBuild": "26200.9457",
|
||||
"osBuild": "26200.9725",
|
||||
"processArchitecture": "ARM64",
|
||||
"runner": "GitHub-hosted windows-11-arm; its registry ProductName reads \"Windows 10 Enterprise\", as Windows 11 reports it",
|
||||
"source": "db34bc8949a5b5e7e6fd5a88cb67e998011ad9df",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/db34bc8949a5b5e7e6fd5a88cb67e998011ad9df",
|
||||
"binarySha256": "a9a2a521d8d0c971b9d49c2c463cdb49d0c7a4eb700b73e6fed2c743e688eebb",
|
||||
"source": "549ff01ebb78856408164058fcb52db1e639ee0d",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/549ff01ebb78856408164058fcb52db1e639ee0d",
|
||||
"binarySha256": "38558ab2b4dc54590503543a0a584c5a82da6f078dd616b5b68e301bf09621b0",
|
||||
"binaries": [
|
||||
"codewhale-windows-arm64.exe",
|
||||
"codew-windows-arm64.exe",
|
||||
"codewhale-tui-windows-arm64.exe"
|
||||
],
|
||||
"resolved": 445,
|
||||
"resolved": 444,
|
||||
"unresolved": 0,
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/38867608774",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/38890634267",
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/42381818665",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/42389141087",
|
||||
"probeWorkflow": ".github/workflows/windows-arm64-export-probe.yml",
|
||||
"profile": "release, built by release-artifacts.yml (windows-arm64 job) in release candidate run 38867608774",
|
||||
"profile": "dist, built by release-artifacts.yml (windows-arm64 job) in release candidate run 42381818665",
|
||||
"runtimeAcceptance": "Static export resolution only; this probe did not launch the release executables. The only ARM64 runtime acceptance is the cf7199b52e debug application run of 2026-10-13; the packaged release and older OS builds are unproven",
|
||||
"exportProbeMethod": "ARM64 process: LoadLibraryExW per imported DLL with LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000800), then GetProcAddress for every imported symbol; module path and SHA256 recorded",
|
||||
"scope": "System-context export resolution only; no Authenticode check, oldest supported OS, or ordinary-user install inference",
|
||||
"systemModuleHashes": {
|
||||
"advapi32.dll": "021452c20f89c50d64c304391ec18169f95a9fa14762f76cfd2dded627dbf0bb",
|
||||
"api-ms-win-core-synch-l1-2-0.dll": "26be64c26bac33368a650372cb5fb1e3235f1bd7883471bd3291dbf6372ae274",
|
||||
"api-ms-win-crt-convert-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-heap-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-locale-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-math-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-runtime-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-stdio-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-string-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-time-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-utility-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"bcrypt.dll": "12e3562488e5ca3a26884408d99d81898237c8ca3c5c3c9e40ca6b8f5ed361cd",
|
||||
"bcryptprimitives.dll": "d3da1097e9e1fc16c910350e40c4405ef52f36f134f9bf165fbe02194c1eaa82",
|
||||
"combase.dll": "850b43094ae61a5d3b8f40f0cddf89b4a90190bf5fc57c5242e0bf5b06644b2f",
|
||||
"crypt32.dll": "e3e800f1905658674ce4af1d3efb31d722b9255aaae4fa46c54302d329ba4ab6",
|
||||
"kernel32.dll": "6a7bd4daff9c0c4cc8b9478ecd9828c3f19be257a4a18db9559cae929197fffa",
|
||||
"ntdll.dll": "60ef561645b50dce71ad0919dbbef3ad334a0489432cde718e75b73b558c7997",
|
||||
"oleaut32.dll": "5ebb761b3f96b227006e79d6a92cf5d98ac5a5fd3c136d35dd05391bed867753",
|
||||
"shell32.dll": "ef0fbd71a46fe4b35bff893ea65241cd08ea5231de704c106e39920c03698fe9",
|
||||
"shlwapi.dll": "67f713491bc18614d6ea29b920e3c609cabf9eecf054990e030476a2e9f76a2c",
|
||||
"user32.dll": "f2fc06e7e5016a15ad7f7f4ee250154b7d41d0a0706bf14927a3bbd4c42727dd",
|
||||
"userenv.dll": "18bd1660ab7cacd90789f1bebe35bc6a5730b1e75e5582f53575473fae3db530",
|
||||
"advapi32.dll": "31a87f532c0e99521de26fb25d1ec33cfbb92359952580c88350891602b6cf35",
|
||||
"api-ms-win-core-synch-l1-2-0.dll": "06bf19bcd0b4af9e78c46fc81fe8fb1bf950fb5f295d44de889c5028129b5b56",
|
||||
"api-ms-win-crt-convert-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-heap-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-locale-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-math-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-runtime-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-stdio-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-string-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-time-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"api-ms-win-crt-utility-l1-1-0.dll": "e59858bf4245cb0889d8da773612b75d58ac716be5d6bb801e1b39594dccfc6d",
|
||||
"bcrypt.dll": "2a016e6f29683a7e6be564424d286d0885ff4846fff87cefab4d4e5df47a8d4a",
|
||||
"bcryptprimitives.dll": "6626bf08ddb38e3c37804d7a000c9684977fb0f5f7ab8eb1c0a91a654ec975fc",
|
||||
"combase.dll": "6082ef654c1a0978e127a1e045cb3078b1e80f8f7108b5c6cb4bc601c69b7f51",
|
||||
"crypt32.dll": "3f53b3351e75cb8847b87ce40349d48279cdddab4b19c4c6c9ad38eef6aa6baf",
|
||||
"kernel32.dll": "905c5e00f64ddf9e3439a617b25d4dd1bd0fe54143ade689422b89ccb324ba3a",
|
||||
"ntdll.dll": "0a7201420df35a67e76aa2f2f4adb793b0c0b4fbc927d7da112268a7beb74930",
|
||||
"oleaut32.dll": "61cd70f21624866fb46102644d5af24563a30c85921ed8deed89139cab340f0b",
|
||||
"shell32.dll": "b9a118ff822ab1e950c7a1009de223ecfea5d5f0a23b8a969d58ff19ce28d9cf",
|
||||
"shlwapi.dll": "b4df8c76ea7999912ddf12ba026c5f4a55b683fe9234878f506080575481779a",
|
||||
"user32.dll": "b95f8cce02f51a7cbf77f17582ad3eee8abc577c324963d0026e8dbb977fa097",
|
||||
"userenv.dll": "e9b94fa6123048d535265214322a6a09e450dd85941292bf5258bf39d5b86f9e",
|
||||
"vcruntime140.dll": "3c56f4167e2b3d8e6338497731e6aae8cd7ec46bd6789f9423a8d9cf9a630310",
|
||||
"winmm.dll": "2ebb728e5c510492df8fde4ec81b8a8554f2f33d1686b837d22c962b7d2fa9b7",
|
||||
"ws2_32.dll": "e1266872f796f68b4be9c20640ca940a7a96e1ba98c741d472ae305fccf87ca9"
|
||||
"winmm.dll": "4fd628e0a495b1fa7e7653b562a4f5484592c9cfe733184f9808dfce18e26680",
|
||||
"ws2_32.dll": "d10c37755ef07b55829406cfaa22c623ae6f86cce5a5fed42d77d75c29ae824a"
|
||||
},
|
||||
"supersedes": {
|
||||
"time": "2026-10-13T10:43:07.5742747Z",
|
||||
"osVersion": "10.0.26300",
|
||||
"osBuild": "26300",
|
||||
"source": "cf7199b52ecb9147e4670ae7874924ffc30a6a67",
|
||||
"binarySha256": "ca51f91562a0569ee43855715856e1cfee74e8a834bd6206183a3175373fdb2d",
|
||||
"resolved": 453,
|
||||
"result": "PASS",
|
||||
"kind": "exact native system export resolution",
|
||||
"time": "2026-10-16T10:57:53.0754367Z",
|
||||
"osVersion": "10.0.26200.0",
|
||||
"osBuild": "26200.9457",
|
||||
"processArchitecture": "ARM64",
|
||||
"runner": "GitHub-hosted windows-11-arm; its registry ProductName reads \"Windows 10 Enterprise\", as Windows 11 reports it",
|
||||
"source": "db34bc8949a5b5e7e6fd5a88cb67e998011ad9df",
|
||||
"sourceUrl": "https://github.com/codewhale-hq/Codewhale/commit/db34bc8949a5b5e7e6fd5a88cb67e998011ad9df",
|
||||
"binarySha256": "a9a2a521d8d0c971b9d49c2c463cdb49d0c7a4eb700b73e6fed2c743e688eebb",
|
||||
"binaries": [
|
||||
"codewhale-windows-arm64.exe",
|
||||
"codew-windows-arm64.exe",
|
||||
"codewhale-tui-windows-arm64.exe"
|
||||
],
|
||||
"resolved": 445,
|
||||
"unresolved": 0,
|
||||
"buildCommand": "cargo build --locked --target aarch64-pc-windows-msvc -p codewhale-cli --bin codewhale",
|
||||
"profile": "debug, default features",
|
||||
"runtimeAcceptance": "Only cf7199b52e ARM64 debug application acceptance; final packaged release and older OS unproven"
|
||||
"buildRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/38867608774",
|
||||
"probeRun": "https://github.com/codewhale-hq/Codewhale/actions/runs/38890634267",
|
||||
"probeWorkflow": ".github/workflows/windows-arm64-export-probe.yml",
|
||||
"profile": "release, built by release-artifacts.yml (windows-arm64 job) in release candidate run 38867608774",
|
||||
"runtimeAcceptance": "Static export resolution only; this probe did not launch the release executables. The only ARM64 runtime acceptance is the cf7199b52e debug application run of 2026-10-13; the packaged release and older OS builds are unproven",
|
||||
"exportProbeMethod": "ARM64 process: LoadLibraryExW per imported DLL with LOAD_LIBRARY_SEARCH_SYSTEM32 (0x00000800), then GetProcAddress for every imported symbol; module path and SHA256 recorded",
|
||||
"scope": "System-context export resolution only; no Authenticode check, oldest supported OS, or ordinary-user install inference",
|
||||
"systemModuleHashes": {
|
||||
"advapi32.dll": "021452c20f89c50d64c304391ec18169f95a9fa14762f76cfd2dded627dbf0bb",
|
||||
"api-ms-win-core-synch-l1-2-0.dll": "26be64c26bac33368a650372cb5fb1e3235f1bd7883471bd3291dbf6372ae274",
|
||||
"api-ms-win-crt-convert-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-heap-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-locale-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-math-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-runtime-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-stdio-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-string-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-time-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"api-ms-win-crt-utility-l1-1-0.dll": "529e795875178b906ea8758abc8de5c28339f336b3e7a121d7778ae040908de9",
|
||||
"bcrypt.dll": "12e3562488e5ca3a26884408d99d81898237c8ca3c5c3c9e40ca6b8f5ed361cd",
|
||||
"bcryptprimitives.dll": "d3da1097e9e1fc16c910350e40c4405ef52f36f134f9bf165fbe02194c1eaa82",
|
||||
"combase.dll": "850b43094ae61a5d3b8f40f0cddf89b4a90190bf5fc57c5242e0bf5b06644b2f",
|
||||
"crypt32.dll": "e3e800f1905658674ce4af1d3efb31d722b9255aaae4fa46c54302d329ba4ab6",
|
||||
"kernel32.dll": "6a7bd4daff9c0c4cc8b9478ecd9828c3f19be257a4a18db9559cae929197fffa",
|
||||
"ntdll.dll": "60ef561645b50dce71ad0919dbbef3ad334a0489432cde718e75b73b558c7997",
|
||||
"oleaut32.dll": "5ebb761b3f96b227006e79d6a92cf5d98ac5a5fd3c136d35dd05391bed867753",
|
||||
"shell32.dll": "ef0fbd71a46fe4b35bff893ea65241cd08ea5231de704c106e39920c03698fe9",
|
||||
"shlwapi.dll": "67f713491bc18614d6ea29b920e3c609cabf9eecf054990e030476a2e9f76a2c",
|
||||
"user32.dll": "f2fc06e7e5016a15ad7f7f4ee250154b7d41d0a0706bf14927a3bbd4c42727dd",
|
||||
"userenv.dll": "18bd1660ab7cacd90789f1bebe35bc6a5730b1e75e5582f53575473fae3db530",
|
||||
"vcruntime140.dll": "3c56f4167e2b3d8e6338497731e6aae8cd7ec46bd6789f9423a8d9cf9a630310",
|
||||
"winmm.dll": "2ebb728e5c510492df8fde4ec81b8a8554f2f33d1686b837d22c962b7d2fa9b7",
|
||||
"ws2_32.dll": "e1266872f796f68b4be9c20640ca940a7a96e1ba98c741d472ae305fccf87ca9"
|
||||
},
|
||||
"supersedes": {
|
||||
"time": "2026-10-13T10:43:07.5742747Z",
|
||||
"osVersion": "10.0.26300",
|
||||
"osBuild": "26300",
|
||||
"source": "cf7199b52ecb9147e4670ae7874924ffc30a6a67",
|
||||
"binarySha256": "ca51f91562a0569ee43855715856e1cfee74e8a834bd6206183a3175373fdb2d",
|
||||
"resolved": 453,
|
||||
"unresolved": 0,
|
||||
"buildCommand": "cargo build --locked --target aarch64-pc-windows-msvc -p codewhale-cli --bin codewhale",
|
||||
"profile": "debug, default features",
|
||||
"runtimeAcceptance": "Only cf7199b52e ARM64 debug application acceptance; final packaged release and older OS unproven"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1122,6 +1200,7 @@
|
||||
"GetFullPathNameA",
|
||||
"GetFullPathNameW",
|
||||
"GetLastError",
|
||||
"GetLogicalDrives",
|
||||
"GetModuleFileNameW",
|
||||
"GetModuleHandleA",
|
||||
"GetModuleHandleExA",
|
||||
@@ -1190,6 +1269,7 @@
|
||||
"PostQueuedCompletionStatus",
|
||||
"Process32FirstW",
|
||||
"Process32NextW",
|
||||
"QueryDosDeviceW",
|
||||
"QueryInformationJobObject",
|
||||
"QueryPerformanceCounter",
|
||||
"QueryPerformanceFrequency",
|
||||
|
||||
+10
@@ -2,6 +2,16 @@
|
||||
|
||||
## Unreleased — 0.2.0
|
||||
|
||||
- Add data displays: `DataSparkline`, `DataBars` and `DataTrend` (a braille
|
||||
line chart). The words carry every value; the ink draws in from a caller
|
||||
progress (`MotionStep::drawn`) and is at its end state under reduced or
|
||||
still motion. Bars glide from their previous values.
|
||||
- Add `DataDisplay`, the same displays as JSON an agent can send:
|
||||
`DataDisplay::from_json` validates it (finite numbers, at most 1024 points
|
||||
or 24 bars, labels up to 120 characters), `describe` says the same facts as
|
||||
plain text, and `DATA_DISPLAY_SCHEMA` is its tool schema. Try
|
||||
`cargo run --example data`.
|
||||
|
||||
- Reexport the shared avatar contract from Codewhale Protocol. Rendering and
|
||||
artwork stay in this library. Protocol 0.10.3 registry proof must precede
|
||||
this package publication.
|
||||
|
||||
+1
@@ -57,6 +57,7 @@ Gallery names are the exact names accepted by the gallery example; the
|
||||
| Engine `agent_roster.rs::render_agent_roster`, `widgets/workflow_panel.rs::row_receipt_text`, `gate_receipts.rs`; GPUI `usage.rs::TurnRow`, `workbar.rs::Readout`, `working_context.rs::ExecutionReceipt` | `Receipt`, `ReceiptTable`, `ReceiptValue`, `Cost`, formatting helpers | Primitive/composite | `receipt-row`, `receipt-table`, `receipt-table-compact`, `receipt-table-minimal`, `receipt-table-clipped` |
|
||||
| Engine `diff_render.rs::BoundedDiffRender`, `render_diff_bounded`, `history/file_mutation.rs`; GPUI `review.rs::DiffRowKind`, `workspace/render/review.rs::ReviewRows` | `Diff`, `DiffLine`, `DiffKind`, `DiffGutter`, `DiffHighlight`, `parse_unified` | Primitive | `diff`, `diff-wrapped`, `diff-no-numbers`, `diff-highlighted`, `review-scene` |
|
||||
| Engine `widgets/workflow_panel.rs::WorkflowPanel`, `WorkflowPanelRow`, `history/checklist.rs`; GPUI `plans.rs`, `workspace/render/workers.rs` | `WorkflowTree`, `TreeNode`, `TreeState`, `CountBar` | Primitive/composite | `workflow-tree`, `workflow-tree-selected`, `workflow-tree-clipped`, `workflow-tree-long`, `count-bars` |
|
||||
| Kit-native; data from the host or an agent's JSON (CW-8202) | `DataSparkline`, `DataBars`, `DataBarItem`, `DataTrend`, `DataDisplay`, `DataDisplayView`, `DataWords`, `DATA_DISPLAY_SCHEMA`, `MotionStep::drawn` | Primitive | `data-sparkline`, `data-bars`, `data-bars-growing`, `data-trend`, `data-trend-drawing`, `data-from-agent` |
|
||||
| Engine `approval/view.rs::ApprovalView`, `approval/elevation.rs::ElevationView`, `auto_review.rs`; GPUI `workspace/render/conversation.rs::Workspace::render_attention`, `workspace/render/review.rs::Workspace::render_restore_confirmation` | `ApprovalCard`, `ApprovalSubject`, `ApprovalState`, `ApprovalChoice`, `ApprovalPaint`, `DecisionBand`, `DecisionBandPlan`, `DecisionBandAction`, `DecisionBandSave`, `ReviewVerdict`, `ReviewAggregate` | Composite | `approval-command`, `approval-outside`, `approval-patch`, `approval-elevation`, `approval-clipped`, `approval-spoofed`, `approval-native-band`, `approval-native-band-collapsed`, `review-verdicts`, `review-aggregate` |
|
||||
| GPUI `workspace/render/conversation.rs::Workspace::render_attention`, `workspace/render/files.rs::Workspace::render_artifact_column` | `AttentionQueue`, `AttentionItem`, `ArtifactShelf`, `Artifact` | Composite | `attention-queue`, `attention-focused`, `attention-narrow`, `attention-empty`, `artifact`, `artifact-shelf`, `artifact-narrow`, `artifact-unknown`, `artifact-empty` |
|
||||
| Engine `views/mod.rs::ConfigView`, `ConfigRow`, `ConfigView::render_setting_detail`; GPUI `settings.rs::Spec`, `Applies`, `workspace/settings/mod.rs::Settings` | `SettingRow`, `SettingDetail`, `SettingWords` | Composite | `setting-row`, `setting-detail` |
|
||||
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
//! Live data displays: `cargo run --example data`.
|
||||
//!
|
||||
//! A sparkline takes a new value every 400 ms, the trend draws in, and the
|
||||
//! bars glide to new values every three seconds. r replays, m switches
|
||||
//! between full and reduced motion, q or Escape exits.
|
||||
//!
|
||||
//! `--json FILE` shows one agent-sent [`DataDisplay`] instead.
|
||||
//! `--text` prints the final frame and each display's plain description.
|
||||
//! `--svg DIR` writes frames at fixed draw-in points.
|
||||
|
||||
use std::{
|
||||
io,
|
||||
path::PathBuf,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use codewhale_ratatui::{
|
||||
DataBarItem, DataDisplay, DataWords, MotionEasing, MotionMode, MotionPolicy, MotionStep,
|
||||
MotionTiming, Paint, Role, Theme,
|
||||
testing::{self, Profile},
|
||||
};
|
||||
use crossterm::{
|
||||
event::{self, Event, KeyCode, KeyEventKind},
|
||||
execute,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
|
||||
};
|
||||
use ratatui::{Terminal, backend::CrosstermBackend, buffer::Buffer, layout::Rect};
|
||||
|
||||
const TICK: Duration = Duration::from_millis(400);
|
||||
const RESHUFFLE: Duration = Duration::from_secs(3);
|
||||
const DRAW_IN: MotionTiming =
|
||||
MotionTiming::space(Duration::from_millis(1_400), MotionEasing::EaseOut);
|
||||
const GLIDE: MotionTiming = MotionTiming::PANEL;
|
||||
|
||||
struct Noise(u64);
|
||||
|
||||
impl Noise {
|
||||
fn next(&mut self) -> f64 {
|
||||
self.0 = self
|
||||
.0
|
||||
.wrapping_mul(6_364_136_223_846_793_005)
|
||||
.wrapping_add(1);
|
||||
(self.0 >> 33) as f64 / f64::from(1u32 << 31)
|
||||
}
|
||||
}
|
||||
|
||||
struct Board {
|
||||
noise: Noise,
|
||||
requests: Vec<f64>,
|
||||
latency: Vec<f64>,
|
||||
bars: DataDisplay,
|
||||
bars_before: DataDisplay,
|
||||
draw: MotionStep,
|
||||
glide: MotionStep,
|
||||
agent: Option<DataDisplay>,
|
||||
}
|
||||
|
||||
fn crate_bars(noise: &mut Noise) -> DataDisplay {
|
||||
DataDisplay::Bars {
|
||||
label: "Tests by crate".into(),
|
||||
unit: "tests".into(),
|
||||
items: ["engine", "tui", "runtime", "protocol", "config"]
|
||||
.into_iter()
|
||||
.map(|name| DataBarItem::new(name, (40.0 + noise.next() * 400.0).round()))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Board {
|
||||
fn new(agent: Option<DataDisplay>) -> Self {
|
||||
let mut noise = Noise(7);
|
||||
let latency = (0..96)
|
||||
.map(|i| 80.0 + 45.0 * (f64::from(i) / 9.0).sin() + noise.next() * 30.0)
|
||||
.collect();
|
||||
let requests = (0..40).map(|_| 20.0 + noise.next() * 60.0).collect();
|
||||
let bars = crate_bars(&mut noise);
|
||||
Self {
|
||||
noise,
|
||||
requests,
|
||||
latency,
|
||||
bars_before: DataDisplay::Bars {
|
||||
label: String::new(),
|
||||
unit: String::new(),
|
||||
items: Vec::new(),
|
||||
},
|
||||
bars,
|
||||
draw: MotionStep::at_rest(0.0),
|
||||
glide: MotionStep::at_rest(1.0),
|
||||
agent,
|
||||
}
|
||||
}
|
||||
|
||||
fn replay(&mut self, now: Instant, policy: MotionPolicy) {
|
||||
self.draw = MotionStep::at_rest(0.0);
|
||||
self.draw.go(1.0, now, DRAW_IN, policy);
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
let last = self.requests.last().copied().unwrap_or(50.0);
|
||||
let next = (last + (self.noise.next() - 0.5) * 30.0).clamp(5.0, 120.0);
|
||||
self.requests.push(next.round());
|
||||
if self.requests.len() > 200 {
|
||||
self.requests.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
fn reshuffle(&mut self, now: Instant, policy: MotionPolicy) {
|
||||
self.bars_before = std::mem::replace(&mut self.bars, crate_bars(&mut self.noise));
|
||||
self.glide = MotionStep::at_rest(0.0);
|
||||
self.glide.go(1.0, now, GLIDE, policy);
|
||||
}
|
||||
|
||||
fn paint(&self, area: Rect, buf: &mut Buffer, theme: &Theme, draw: f32, glide: f32) {
|
||||
buf.set_style(area, theme.bg(Role::Background));
|
||||
let inner = Rect::new(
|
||||
area.x + 2,
|
||||
area.y + 1,
|
||||
area.width.saturating_sub(4),
|
||||
area.height.saturating_sub(2),
|
||||
);
|
||||
if let Some(agent) = &self.agent {
|
||||
agent.view().drawn(draw).paint(inner, buf, theme);
|
||||
return;
|
||||
}
|
||||
let row =
|
||||
|y: u16, h: u16| Rect::new(inner.x, inner.y + y, inner.width, h).intersection(inner);
|
||||
let requests = DataDisplay::Sparkline {
|
||||
label: "Requests".into(),
|
||||
unit: "rpm".into(),
|
||||
values: self.requests.clone(),
|
||||
};
|
||||
let latency = DataDisplay::Trend {
|
||||
label: "Latency".into(),
|
||||
unit: "ms".into(),
|
||||
values: self.latency.clone(),
|
||||
rows: Some(9),
|
||||
};
|
||||
requests.view().drawn(draw).paint(row(0, 1), buf, theme);
|
||||
latency.view().drawn(draw).paint(row(2, 9), buf, theme);
|
||||
self.bars
|
||||
.view()
|
||||
.from(&self.bars_before)
|
||||
.drawn(glide.min(draw))
|
||||
.paint(row(12, 6), buf, theme);
|
||||
}
|
||||
|
||||
fn displays(&self) -> Vec<DataDisplay> {
|
||||
if let Some(agent) = &self.agent {
|
||||
return vec![agent.clone()];
|
||||
}
|
||||
vec![
|
||||
DataDisplay::Sparkline {
|
||||
label: "Requests".into(),
|
||||
unit: "rpm".into(),
|
||||
values: self.requests.clone(),
|
||||
},
|
||||
DataDisplay::Trend {
|
||||
label: "Latency".into(),
|
||||
unit: "ms".into(),
|
||||
values: self.latency.clone(),
|
||||
rows: Some(9),
|
||||
},
|
||||
self.bars.clone(),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||
let value = |flag: &str| {
|
||||
args.iter()
|
||||
.position(|a| a == flag)
|
||||
.and_then(|i| args.get(i + 1))
|
||||
.cloned()
|
||||
};
|
||||
let agent = match value("--json") {
|
||||
Some(path) => {
|
||||
let json = std::fs::read_to_string(&path)?;
|
||||
match DataDisplay::from_json(&json) {
|
||||
Ok(shown) => Some(shown),
|
||||
Err(e) => {
|
||||
eprintln!("{path}: {e}");
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let board = Board::new(agent);
|
||||
|
||||
if args.iter().any(|a| a == "--text") {
|
||||
let buf = testing::render(84, 20, |area, buf| {
|
||||
board.paint(area, buf, &Profile::DarkTrue.theme(), 1.0, 1.0);
|
||||
});
|
||||
println!("{}", testing::text(&buf));
|
||||
for shown in board.displays() {
|
||||
println!("{}", shown.describe(&DataWords::default()));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(dir) = value("--svg") {
|
||||
let dir = PathBuf::from(dir);
|
||||
std::fs::create_dir_all(&dir)?;
|
||||
let theme = Profile::DarkTrue.theme();
|
||||
for (i, at) in [0.2_f32, 0.5, 0.8, 1.0].into_iter().enumerate() {
|
||||
let buf = testing::render(84, 20, |area, buf| board.paint(area, buf, &theme, at, at));
|
||||
let path = dir.join(format!("data-{i}.svg"));
|
||||
std::fs::write(&path, testing::svg(&buf, &theme))?;
|
||||
println!("{}", path.display());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
run(board)
|
||||
}
|
||||
|
||||
fn run(mut board: Board) -> io::Result<()> {
|
||||
enable_raw_mode()?;
|
||||
let mut out = io::stdout();
|
||||
execute!(out, EnterAlternateScreen)?;
|
||||
let mut terminal = Terminal::new(CrosstermBackend::new(out))?;
|
||||
let theme = Theme::detect().tui();
|
||||
let mut mode = MotionMode::Full;
|
||||
let mut policy = MotionPolicy::new(mode, &theme);
|
||||
let start = Instant::now();
|
||||
board.replay(start, policy);
|
||||
let (mut next_tick, mut next_shuffle) = (start + TICK, start + RESHUFFLE);
|
||||
|
||||
let result = loop {
|
||||
let now = Instant::now();
|
||||
if now >= next_tick {
|
||||
board.tick();
|
||||
next_tick = now + TICK;
|
||||
}
|
||||
if now >= next_shuffle {
|
||||
board.reshuffle(now, policy);
|
||||
next_shuffle = now + RESHUFFLE;
|
||||
}
|
||||
let (draw, glide) = (
|
||||
board.draw.drawn(now, policy),
|
||||
board.glide.drawn(now, policy),
|
||||
);
|
||||
terminal.draw(|f| board.paint(f.area(), f.buffer_mut(), &theme, draw, glide))?;
|
||||
|
||||
let due = [
|
||||
board.draw.next_frame_at(now, policy),
|
||||
board.glide.next_frame_at(now, policy),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.chain([next_tick, next_shuffle])
|
||||
.min()
|
||||
.unwrap_or(next_tick);
|
||||
if event::poll(due.saturating_duration_since(Instant::now()))?
|
||||
&& let Event::Key(key) = event::read()?
|
||||
&& key.kind != KeyEventKind::Release
|
||||
{
|
||||
match key.code {
|
||||
KeyCode::Char('q') | KeyCode::Esc => break Ok(()),
|
||||
KeyCode::Char('r') => board.replay(Instant::now(), policy),
|
||||
KeyCode::Char('m') => {
|
||||
mode = if mode == MotionMode::Full {
|
||||
MotionMode::Reduced
|
||||
} else {
|
||||
MotionMode::Full
|
||||
};
|
||||
policy = MotionPolicy::new(mode, &theme);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
disable_raw_mode()?;
|
||||
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
|
||||
result
|
||||
}
|
||||
+1261
File diff suppressed because it is too large.
Load diff
@@ -59,10 +59,12 @@ pub use tabs::*;
|
||||
pub use toggle::*;
|
||||
|
||||
// Package Display.
|
||||
mod chart;
|
||||
mod diff;
|
||||
mod progress;
|
||||
mod receipt;
|
||||
mod tree;
|
||||
pub use chart::*;
|
||||
pub use diff::*;
|
||||
pub use progress::*;
|
||||
pub use receipt::*;
|
||||
|
||||
@@ -366,6 +366,14 @@ impl MotionStep {
|
||||
}
|
||||
}
|
||||
|
||||
/// Progress for a draw-in, in `0..=1`: eased where `policy` lets space
|
||||
/// move, the target where it does not. Feed it to a data display's
|
||||
/// `drawn`.
|
||||
#[must_use]
|
||||
pub fn drawn(&self, now: Instant, policy: MotionPolicy) -> f32 {
|
||||
self.shown(now, policy, MotionChannel::Space)
|
||||
}
|
||||
|
||||
/// A column between `from` and `to`: slide a marker, nudge a panel.
|
||||
#[must_use]
|
||||
pub fn offset(&self, now: Instant, policy: MotionPolicy, from: u16, to: u16) -> u16 {
|
||||
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
---
|
||||
source: src/components/chart.rs
|
||||
assertion_line: 1242
|
||||
expression: "testing::snapshot(12, |area, buf, theme|\n{\n let row = |y: u16, h: u16|\n { Rect::new(area.x, area.y + y, area.width, h).intersection(area) };\n DataSparkline::new(\"Requests\",\n &values).unit(\"rpm\").paint(row(0, 1), buf, theme);\n DataBars::new(\"Tokens by model\",\n &items).unit(\"tokens\").paint(row(2, 5), buf, theme);\n DataTrend::new(\"Latency\",\n &values).unit(\"ms\").rows(5).paint(row(7, 5), buf, theme);\n})"
|
||||
---
|
||||
== dark-truecolor · 40x12
|
||||
Requests ▁▃▅▄▅▆▇███▆▅▄▃▂▁ now 45.6 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████ 12.4k tokens
|
||||
sonnet ███████████▌ 7900 tokens
|
||||
haiku ████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms
|
||||
69.7 ms │ ⡠⠒⠑⠒⠒⠢⣀ ⡀⡠⠔⠉⠉⢢⡀
|
||||
│⢀⠔⠁ ⢇ ⢀⠔⠉ ⠈⠑⢄
|
||||
│⠁ ⠑⠢⡀ ⡠⠊
|
||||
17.2 ms │ ⠈⠱⣀⣀⠤⠊⠊
|
||||
---
|
||||
r0 c0..8 fg=Foreground bg=Background bold
|
||||
r0 c8..10 bg=Background
|
||||
r0 c10..26 fg=Accent bg=Background
|
||||
r0 c26..28 bg=Background
|
||||
r0 c28..32 fg=Muted bg=Background
|
||||
r0 c32..40 fg=Foreground bg=Background
|
||||
r1 c0..40 bg=Background
|
||||
r2 c0..15 fg=Foreground bg=Background bold
|
||||
r2 c15..40 bg=Background
|
||||
r3 c0..6 fg=Foreground bg=Background
|
||||
r3 c6..8 bg=Background
|
||||
r3 c8..26 fg=Accent bg=Background
|
||||
r3 c26..28 bg=Background
|
||||
r3 c28..40 fg=Muted bg=Background
|
||||
r4 c0..6 fg=Foreground bg=Background
|
||||
r4 c6..8 bg=Background
|
||||
r4 c8..20 fg=Accent bg=Background
|
||||
r4 c20..28 bg=Background
|
||||
r4 c28..39 fg=Muted bg=Background
|
||||
r4 c39..40 bg=Background
|
||||
r5 c0..6 fg=Foreground bg=Background
|
||||
r5 c6..8 bg=Background
|
||||
r5 c8..13 fg=Accent bg=Background
|
||||
r5 c13..28 bg=Background
|
||||
r5 c28..39 fg=Muted bg=Background
|
||||
r5 c39..40 bg=Background
|
||||
r6 c0..6 fg=Foreground bg=Background
|
||||
r6 c6..28 bg=Background
|
||||
r6 c28..36 fg=Muted bg=Background
|
||||
r6 c36..40 bg=Background
|
||||
r7 c0..7 fg=Foreground bg=Background bold
|
||||
r7 c7..9 bg=Background
|
||||
r7 c9..13 fg=Muted bg=Background
|
||||
r7 c13..20 fg=Foreground bg=Background
|
||||
r7 c20..40 bg=Background
|
||||
r8 c0..8 fg=Muted bg=Background
|
||||
r8 c8..9 fg=Dim bg=Background
|
||||
r8 c9..11 bg=Background
|
||||
r8 c11..18 fg=Accent bg=Background
|
||||
r8 c18..31 bg=Background
|
||||
r8 c31..38 fg=Accent bg=Background
|
||||
r8 c38..40 bg=Background
|
||||
r9 c0..8 fg=Muted bg=Background
|
||||
r9 c8..9 fg=Dim bg=Background
|
||||
r9 c9..12 fg=Accent bg=Background
|
||||
r9 c12..18 bg=Background
|
||||
r9 c18..19 fg=Accent bg=Background
|
||||
r9 c19..29 bg=Background
|
||||
r9 c29..32 fg=Accent bg=Background
|
||||
r9 c32..37 bg=Background
|
||||
r9 c37..40 fg=Accent bg=Background
|
||||
r10 c0..8 fg=Muted bg=Background
|
||||
r10 c8..9 fg=Dim bg=Background
|
||||
r10 c9..10 fg=Accent bg=Background
|
||||
r10 c10..19 bg=Background
|
||||
r10 c19..22 fg=Accent bg=Background
|
||||
r10 c22..28 bg=Background
|
||||
r10 c28..30 fg=Accent bg=Background
|
||||
r10 c30..40 bg=Background
|
||||
r11 c0..8 fg=Muted bg=Background
|
||||
r11 c8..9 fg=Dim bg=Background
|
||||
r11 c9..21 bg=Background
|
||||
r11 c21..28 fg=Accent bg=Background
|
||||
r11 c28..40 bg=Background
|
||||
|
||||
== dark-truecolor · 80x12
|
||||
Requests ▂▁▁▁▁▁▂▂▂▃▃▄▅▆▆▆▇▇████▇▇▆▆▅▅ now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████████████████████████████████████████████ 12.4k tokens
|
||||
sonnet █████████████████████████████████████ 7900 tokens
|
||||
haiku ██████████████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms │ ⣀⠤⠒⠊⠑⠒⠒⠒⠒⠒⠒⠢⠤⢄⣀ ⣀ ⣀⡠⠤⠒⠒⠉⠉⠉⠉⠢⢄⣀⣀
|
||||
│ ⣀⠤⠒⠉ ⠑⠤⣀ ⢀⡠⠒⠉ ⠉ ⠉⠑⠒⠤⣀
|
||||
│⠉ ⠉⠑⠒⠤⢄⣀ ⡠⠔⠊⠁
|
||||
17.2 ms │ ⠉⠑⢄⣀⣀⣀⣀⣀⠤⠤⠒⠊⠒⠊⠉
|
||||
---
|
||||
r0 c0..8 fg=Foreground bg=Background bold
|
||||
r0 c8..10 bg=Background
|
||||
r0 c10..38 fg=Accent bg=Background
|
||||
r0 c38..40 bg=Background
|
||||
r0 c40..44 fg=Muted bg=Background
|
||||
r0 c44..52 fg=Foreground bg=Background
|
||||
r0 c52..54 bg=Background
|
||||
r0 c54..58 fg=Muted bg=Background
|
||||
r0 c58..66 fg=Foreground bg=Background
|
||||
r0 c66..68 bg=Background
|
||||
r0 c68..72 fg=Muted bg=Background
|
||||
r0 c72..80 fg=Foreground bg=Background
|
||||
r1 c0..80 bg=Background
|
||||
r2 c0..15 fg=Foreground bg=Background bold
|
||||
r2 c15..80 bg=Background
|
||||
r3 c0..6 fg=Foreground bg=Background
|
||||
r3 c6..8 bg=Background
|
||||
r3 c8..66 fg=Accent bg=Background
|
||||
r3 c66..68 bg=Background
|
||||
r3 c68..80 fg=Muted bg=Background
|
||||
r4 c0..6 fg=Foreground bg=Background
|
||||
r4 c6..8 bg=Background
|
||||
r4 c8..45 fg=Accent bg=Background
|
||||
r4 c45..68 bg=Background
|
||||
r4 c68..79 fg=Muted bg=Background
|
||||
r4 c79..80 bg=Background
|
||||
r5 c0..6 fg=Foreground bg=Background
|
||||
r5 c6..8 bg=Background
|
||||
r5 c8..23 fg=Accent bg=Background
|
||||
r5 c23..68 bg=Background
|
||||
r5 c68..79 fg=Muted bg=Background
|
||||
r5 c79..80 bg=Background
|
||||
r6 c0..6 fg=Foreground bg=Background
|
||||
r6 c6..68 bg=Background
|
||||
r6 c68..76 fg=Muted bg=Background
|
||||
r6 c76..80 bg=Background
|
||||
r7 c0..7 fg=Foreground bg=Background bold
|
||||
r7 c7..9 bg=Background
|
||||
r7 c9..13 fg=Muted bg=Background
|
||||
r7 c13..20 fg=Foreground bg=Background
|
||||
r7 c20..22 bg=Background
|
||||
r7 c22..26 fg=Muted bg=Background
|
||||
r7 c26..33 fg=Foreground bg=Background
|
||||
r7 c33..35 bg=Background
|
||||
r7 c35..39 fg=Muted bg=Background
|
||||
r7 c39..46 fg=Foreground bg=Background
|
||||
r7 c46..80 bg=Background
|
||||
r8 c0..8 fg=Muted bg=Background
|
||||
r8 c8..9 fg=Dim bg=Background
|
||||
r8 c9..14 bg=Background
|
||||
r8 c14..29 fg=Accent bg=Background
|
||||
r8 c29..60 bg=Background
|
||||
r8 c60..61 fg=Accent bg=Background
|
||||
r8 c61..62 bg=Background
|
||||
r8 c62..75 fg=Accent bg=Background
|
||||
r8 c75..80 bg=Background
|
||||
r9 c0..8 fg=Muted bg=Background
|
||||
r9 c8..9 fg=Dim bg=Background
|
||||
r9 c9..10 bg=Background
|
||||
r9 c10..14 fg=Accent bg=Background
|
||||
r9 c14..29 bg=Background
|
||||
r9 c29..32 fg=Accent bg=Background
|
||||
r9 c32..56 bg=Background
|
||||
r9 c56..60 fg=Accent bg=Background
|
||||
r9 c60..61 bg=Background
|
||||
r9 c61..62 fg=Accent bg=Background
|
||||
r9 c62..75 bg=Background
|
||||
r9 c75..80 fg=Accent bg=Background
|
||||
r10 c0..8 fg=Muted bg=Background
|
||||
r10 c8..9 fg=Dim bg=Background
|
||||
r10 c9..10 fg=Accent bg=Background
|
||||
r10 c10..32 bg=Background
|
||||
r10 c32..38 fg=Accent bg=Background
|
||||
r10 c38..53 bg=Background
|
||||
r10 c53..57 fg=Accent bg=Background
|
||||
r10 c57..80 bg=Background
|
||||
r11 c0..8 fg=Muted bg=Background
|
||||
r11 c8..9 fg=Dim bg=Background
|
||||
r11 c9..38 bg=Background
|
||||
r11 c38..53 fg=Accent bg=Background
|
||||
r11 c53..80 bg=Background
|
||||
|
||||
== dark-truecolor · 120x12
|
||||
Requests ▄▅▆▆▇██▇██▇▇▇▇▅▅▄▄▃▃▂▁▁▁▁▁▂▂▂▃▃▄▅▆▆▆▇▇████▇▇▆▆▅▅ now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████████████████████████████████████████████████████████████████████████████████████ 12.4k tokens
|
||||
sonnet ██████████████████████████████████████████████████████████████▍ 7900 tokens
|
||||
haiku ████████████████████████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms │ ⢀⣀⠤⠤⠒⠒⠊⠉⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠢⠤⠤⠤⣀⣀ ⣀⡀ ⣀⣀⠤⠤⠒⠒⠒⠊⠉⠉⠉⠉⠉⠉⠒⠤⢄⣀⣀⣀
|
||||
│ ⢀⣀⠤⠔⠒⠉⠁ ⠉⠢⠤⣀⣀ ⣀⡠⠤⠒⠊⠉ ⠈⠉ ⠉⠉⠑⠒⠒⠤⠤⣀
|
||||
│⠉⠁ ⠉⠉⠒⠒⠢⠤⢄⣀⣀ ⢀⣀⠤⠔⠊⠉
|
||||
17.2 ms │ ⠉⠉⠑⠢⢄⣀⣀⣀⣀⣀⣀⣀⡠⠤⠤⠤⠒⠒⠊⠑⠒⠒⠉⠁
|
||||
---
|
||||
r0 c0..8 fg=Foreground bg=Background bold
|
||||
r0 c8..10 bg=Background
|
||||
r0 c10..58 fg=Accent bg=Background
|
||||
r0 c58..60 bg=Background
|
||||
r0 c60..64 fg=Muted bg=Background
|
||||
r0 c64..72 fg=Foreground bg=Background
|
||||
r0 c72..74 bg=Background
|
||||
r0 c74..78 fg=Muted bg=Background
|
||||
r0 c78..86 fg=Foreground bg=Background
|
||||
r0 c86..88 bg=Background
|
||||
r0 c88..92 fg=Muted bg=Background
|
||||
r0 c92..100 fg=Foreground bg=Background
|
||||
r0 c100..120 bg=Background
|
||||
r1 c0..120 bg=Background
|
||||
r2 c0..15 fg=Foreground bg=Background bold
|
||||
r2 c15..120 bg=Background
|
||||
r3 c0..6 fg=Foreground bg=Background
|
||||
r3 c6..8 bg=Background
|
||||
r3 c8..106 fg=Accent bg=Background
|
||||
r3 c106..108 bg=Background
|
||||
r3 c108..120 fg=Muted bg=Background
|
||||
r4 c0..6 fg=Foreground bg=Background
|
||||
r4 c6..8 bg=Background
|
||||
r4 c8..71 fg=Accent bg=Background
|
||||
r4 c71..108 bg=Background
|
||||
r4 c108..119 fg=Muted bg=Background
|
||||
r4 c119..120 bg=Background
|
||||
r5 c0..6 fg=Foreground bg=Background
|
||||
r5 c6..8 bg=Background
|
||||
r5 c8..33 fg=Accent bg=Background
|
||||
r5 c33..108 bg=Background
|
||||
r5 c108..119 fg=Muted bg=Background
|
||||
r5 c119..120 bg=Background
|
||||
r6 c0..6 fg=Foreground bg=Background
|
||||
r6 c6..108 bg=Background
|
||||
r6 c108..116 fg=Muted bg=Background
|
||||
r6 c116..120 bg=Background
|
||||
r7 c0..7 fg=Foreground bg=Background bold
|
||||
r7 c7..9 bg=Background
|
||||
r7 c9..13 fg=Muted bg=Background
|
||||
r7 c13..20 fg=Foreground bg=Background
|
||||
r7 c20..22 bg=Background
|
||||
r7 c22..26 fg=Muted bg=Background
|
||||
r7 c26..33 fg=Foreground bg=Background
|
||||
r7 c33..35 bg=Background
|
||||
r7 c35..39 fg=Muted bg=Background
|
||||
r7 c39..46 fg=Foreground bg=Background
|
||||
r7 c46..120 bg=Background
|
||||
r8 c0..8 fg=Muted bg=Background
|
||||
r8 c8..9 fg=Dim bg=Background
|
||||
r8 c9..16 bg=Background
|
||||
r8 c16..40 fg=Accent bg=Background
|
||||
r8 c40..89 bg=Background
|
||||
r8 c89..91 fg=Accent bg=Background
|
||||
r8 c91..92 bg=Background
|
||||
r8 c92..112 fg=Accent bg=Background
|
||||
r8 c112..120 bg=Background
|
||||
r9 c0..8 fg=Muted bg=Background
|
||||
r9 c8..9 fg=Dim bg=Background
|
||||
r9 c9..10 bg=Background
|
||||
r9 c10..17 fg=Accent bg=Background
|
||||
r9 c17..40 bg=Background
|
||||
r9 c40..45 fg=Accent bg=Background
|
||||
r9 c45..83 bg=Background
|
||||
r9 c83..89 fg=Accent bg=Background
|
||||
r9 c89..90 bg=Background
|
||||
r9 c90..92 fg=Accent bg=Background
|
||||
r9 c92..112 bg=Background
|
||||
r9 c112..120 fg=Accent bg=Background
|
||||
r10 c0..8 fg=Muted bg=Background
|
||||
r10 c8..9 fg=Dim bg=Background
|
||||
r10 c9..11 fg=Accent bg=Background
|
||||
r10 c11..45 bg=Background
|
||||
r10 c45..54 fg=Accent bg=Background
|
||||
r10 c54..77 bg=Background
|
||||
r10 c77..83 fg=Accent bg=Background
|
||||
r10 c83..120 bg=Background
|
||||
r11 c0..8 fg=Muted bg=Background
|
||||
r11 c8..9 fg=Dim bg=Background
|
||||
r11 c9..54 bg=Background
|
||||
r11 c54..78 fg=Accent bg=Background
|
||||
r11 c78..120 bg=Background
|
||||
|
||||
== no-color · 40x12
|
||||
Requests ▁▃▅▄▅▆▇███▆▅▄▃▂▁ now 45.6 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████ 12.4k tokens
|
||||
sonnet ███████████▌ 7900 tokens
|
||||
haiku ████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms
|
||||
69.7 ms │ ⡠⠒⠑⠒⠒⠢⣀ ⡀⡠⠔⠉⠉⢢⡀
|
||||
│⢀⠔⠁ ⢇ ⢀⠔⠉ ⠈⠑⢄
|
||||
│⠁ ⠑⠢⡀ ⡠⠊
|
||||
17.2 ms │ ⠈⠱⣀⣀⠤⠊⠊
|
||||
|
||||
== no-color · 80x12
|
||||
Requests ▂▁▁▁▁▁▂▂▂▃▃▄▅▆▆▆▇▇████▇▇▆▆▅▅ now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████████████████████████████████████████████ 12.4k tokens
|
||||
sonnet █████████████████████████████████████ 7900 tokens
|
||||
haiku ██████████████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms │ ⣀⠤⠒⠊⠑⠒⠒⠒⠒⠒⠒⠢⠤⢄⣀ ⣀ ⣀⡠⠤⠒⠒⠉⠉⠉⠉⠢⢄⣀⣀
|
||||
│ ⣀⠤⠒⠉ ⠑⠤⣀ ⢀⡠⠒⠉ ⠉ ⠉⠑⠒⠤⣀
|
||||
│⠉ ⠉⠑⠒⠤⢄⣀ ⡠⠔⠊⠁
|
||||
17.2 ms │ ⠉⠑⢄⣀⣀⣀⣀⣀⠤⠤⠒⠊⠒⠊⠉
|
||||
|
||||
== no-color · 120x12
|
||||
Requests ▄▅▆▆▇██▇██▇▇▇▇▅▅▄▄▃▃▂▁▁▁▁▁▂▂▂▃▃▄▅▆▆▆▇▇████▇▇▆▆▅▅ now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ██████████████████████████████████████████████████████████████████████████████████████████████████ 12.4k tokens
|
||||
sonnet ██████████████████████████████████████████████████████████████▍ 7900 tokens
|
||||
haiku ████████████████████████▌ 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms │ ⢀⣀⠤⠤⠒⠒⠊⠉⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠢⠤⠤⠤⣀⣀ ⣀⡀ ⣀⣀⠤⠤⠒⠒⠒⠊⠉⠉⠉⠉⠉⠉⠒⠤⢄⣀⣀⣀
|
||||
│ ⢀⣀⠤⠔⠒⠉⠁ ⠉⠢⠤⣀⣀ ⣀⡠⠤⠒⠊⠉ ⠈⠉ ⠉⠉⠑⠒⠒⠤⠤⣀
|
||||
│⠉⠁ ⠉⠉⠒⠒⠢⠤⢄⣀⣀ ⢀⣀⠤⠔⠊⠉
|
||||
17.2 ms │ ⠉⠉⠑⠢⢄⣀⣀⣀⣀⣀⣀⣀⡠⠤⠤⠤⠒⠒⠊⠑⠒⠒⠉⠁
|
||||
|
||||
== ascii · 40x12
|
||||
Requests _.---=####=--.__ now 45.6 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ################## 12.4k tokens
|
||||
sonnet ############ 7900 tokens
|
||||
haiku ##### 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms
|
||||
69.7 ms | ....... .....:.
|
||||
|... : ... ...
|
||||
|. ... ..
|
||||
17.2 ms | .:.....
|
||||
|
||||
== ascii · 80x12
|
||||
Requests _________..--===########==-- now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ########################################################## 12.4k tokens
|
||||
sonnet ##################################### 7900 tokens
|
||||
haiku ############### 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms | ............... . .............
|
||||
| .... ... .... . .....
|
||||
|. ...... ....
|
||||
17.2 ms | ...............
|
||||
|
||||
== ascii · 120x12
|
||||
Requests --==##########----.._________..--===########==-- now 45.6 rpm min 17.2 rpm max 69.7 rpm
|
||||
|
||||
Tokens by model
|
||||
opus ################################################################################################## 12.4k tokens
|
||||
sonnet ############################################################### 7900 tokens
|
||||
haiku ######################### 3100 tokens
|
||||
cache 0 tokens
|
||||
Latency now 45.6 ms min 17.2 ms max 69.7 ms
|
||||
69.7 ms | ........................ .. ....................
|
||||
| ....... ..... ...... .. ........
|
||||
|.. ......... ......
|
||||
17.2 ms | ........................
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
//! Gallery: data displays fully drawn, mid draw-in, empty and from agent JSON.
|
||||
|
||||
use ratatui::{buffer::Buffer, layout::Rect};
|
||||
|
||||
use super::Entry;
|
||||
use crate::{DataBarItem, DataBars, DataDisplay, DataSparkline, DataTrend, Paint, Theme};
|
||||
|
||||
fn series() -> Vec<f64> {
|
||||
(0..64)
|
||||
.map(|i| 120.0 + 60.0 * (f64::from(i) / 6.0).sin() + f64::from((i * 7) % 11) * 3.0)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn items() -> Vec<DataBarItem> {
|
||||
vec![
|
||||
DataBarItem::new("engine", 412.0),
|
||||
DataBarItem::new("tui", 268.0),
|
||||
DataBarItem::new("runtime", 131.0),
|
||||
DataBarItem::new("protocol", 44.0),
|
||||
]
|
||||
}
|
||||
|
||||
fn row(area: Rect, y: u16, h: u16) -> Rect {
|
||||
Rect::new(area.x, area.y.saturating_add(y), area.width, h).intersection(area)
|
||||
}
|
||||
|
||||
fn sparklines(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let values = series();
|
||||
DataSparkline::new("Requests", &values)
|
||||
.unit("rpm")
|
||||
.paint(row(area, 0, 1), buf, theme);
|
||||
DataSparkline::new("Requests", &values)
|
||||
.unit("rpm")
|
||||
.drawn(0.45)
|
||||
.paint(row(area, 1, 1), buf, theme);
|
||||
DataSparkline::new("Requests", &[]).paint(row(area, 2, 1), buf, theme);
|
||||
}
|
||||
|
||||
fn bars(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let items = items();
|
||||
DataBars::new("Tests by crate", &items).paint(row(area, 0, 5), buf, theme);
|
||||
}
|
||||
|
||||
fn bars_growing(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let items = items();
|
||||
DataBars::new("Tests by crate", &items)
|
||||
.previous(&[300.0, 300.0, 300.0, 300.0])
|
||||
.drawn(0.5)
|
||||
.paint(row(area, 0, 5), buf, theme);
|
||||
}
|
||||
|
||||
fn trend(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let values = series();
|
||||
DataTrend::new("Latency", &values)
|
||||
.unit("ms")
|
||||
.rows(7)
|
||||
.paint(area, buf, theme);
|
||||
}
|
||||
|
||||
fn trend_drawing(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let values = series();
|
||||
DataTrend::new("Latency", &values)
|
||||
.unit("ms")
|
||||
.rows(7)
|
||||
.drawn(0.6)
|
||||
.paint(area, buf, theme);
|
||||
}
|
||||
|
||||
fn from_agent(area: Rect, buf: &mut Buffer, theme: &Theme) {
|
||||
let shown = DataDisplay::from_json(
|
||||
r#"{"kind":"bars","label":"Tokens this turn","unit":"tokens",
|
||||
"items":[{"label":"read","value":18200},{"label":"wrote","value":2400},
|
||||
{"label":"cached","value":61000}]}"#,
|
||||
)
|
||||
.expect("gallery fixture is a valid data display");
|
||||
shown.view().paint(area, buf, theme);
|
||||
}
|
||||
|
||||
pub(crate) fn entries() -> Vec<Entry> {
|
||||
vec![
|
||||
Entry {
|
||||
name: "data-sparkline",
|
||||
width: 80,
|
||||
height: 3,
|
||||
draw: sparklines,
|
||||
},
|
||||
Entry {
|
||||
name: "data-bars",
|
||||
width: 60,
|
||||
height: 5,
|
||||
draw: bars,
|
||||
},
|
||||
Entry {
|
||||
name: "data-bars-growing",
|
||||
width: 60,
|
||||
height: 5,
|
||||
draw: bars_growing,
|
||||
},
|
||||
Entry {
|
||||
name: "data-trend",
|
||||
width: 72,
|
||||
height: 7,
|
||||
draw: trend,
|
||||
},
|
||||
Entry {
|
||||
name: "data-trend-drawing",
|
||||
width: 72,
|
||||
height: 7,
|
||||
draw: trend_drawing,
|
||||
},
|
||||
Entry {
|
||||
name: "data-from-agent",
|
||||
width: 60,
|
||||
height: 4,
|
||||
draw: from_agent,
|
||||
},
|
||||
]
|
||||
}
|
||||
+2
@@ -31,6 +31,7 @@ mod approval;
|
||||
mod artifacts;
|
||||
mod atmosphere;
|
||||
mod attention;
|
||||
mod chart;
|
||||
mod chrome;
|
||||
mod display;
|
||||
mod habitat;
|
||||
@@ -104,6 +105,7 @@ pub fn entries() -> Vec<Entry> {
|
||||
lists::entries(),
|
||||
chrome::entries(),
|
||||
display::entries(),
|
||||
chart::entries(),
|
||||
approval::entries(),
|
||||
motion::entries(),
|
||||
workspace::entries(),
|
||||
|
||||
Reference in new issue
Block a user