@wenathlan/saddle 1.8.18 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +1346 -0
- package/README.md +33 -12
- package/alternatives.ts +1218 -0
- package/biome.json +153 -0
- package/boards.json +1517 -0
- package/compute.ts +3144 -0
- package/cores.json +1801 -0
- package/dist/acquisition.d.ts +359 -0
- package/dist/acquisition.d.ts.map +1 -0
- package/dist/acquisition.js +629 -0
- package/dist/acquisition.js.map +1 -0
- package/dist/alternatives.d.ts +509 -0
- package/dist/alternatives.d.ts.map +1 -0
- package/dist/alternatives.js +951 -0
- package/dist/alternatives.js.map +1 -0
- package/dist/automation.d.ts +426 -0
- package/dist/automation.d.ts.map +1 -0
- package/dist/automation.js +561 -0
- package/dist/automation.js.map +1 -0
- package/dist/browser.d.ts +562 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +1057 -0
- package/dist/browser.js.map +1 -0
- package/dist/capacitor.config.d.ts +13 -0
- package/dist/capacitor.config.d.ts.map +1 -0
- package/dist/capacitor.config.js +26 -0
- package/dist/capacitor.config.js.map +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +111 -0
- package/dist/cli.js.map +1 -0
- package/dist/communication.d.ts +192 -0
- package/dist/communication.d.ts.map +1 -0
- package/dist/communication.js +418 -0
- package/dist/communication.js.map +1 -0
- package/dist/compute.d.ts +1161 -0
- package/dist/compute.d.ts.map +1 -0
- package/dist/compute.js +2273 -0
- package/dist/compute.js.map +1 -0
- package/dist/distribution.d.ts +529 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +811 -0
- package/dist/distribution.js.map +1 -0
- package/dist/execution.d.ts +530 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +761 -0
- package/dist/execution.js.map +1 -0
- package/dist/format.d.ts +19 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +60 -0
- package/dist/format.js.map +1 -0
- package/dist/foundation.d.ts +176 -0
- package/dist/foundation.d.ts.map +1 -0
- package/dist/foundation.js +309 -0
- package/dist/foundation.js.map +1 -0
- package/dist/index.d.ts +733 -123
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1018 -123
- package/dist/index.js.map +1 -1
- package/dist/integration.d.ts +236 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +236 -0
- package/dist/integration.js.map +1 -0
- package/dist/intelligence.d.ts +94 -0
- package/dist/intelligence.d.ts.map +1 -0
- package/dist/intelligence.js +145 -0
- package/dist/intelligence.js.map +1 -0
- package/dist/{isolation/contracts.d.ts → isolation.d.ts} +12 -1
- package/dist/isolation.d.ts.map +1 -0
- package/dist/{isolation/contracts.js → isolation.js} +13 -1
- package/dist/isolation.js.map +1 -0
- package/dist/media.d.ts +344 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +986 -0
- package/dist/media.js.map +1 -0
- package/dist/modes.d.ts +359 -0
- package/dist/modes.d.ts.map +1 -0
- package/dist/modes.js +134 -0
- package/dist/modes.js.map +1 -0
- package/dist/{library/public.d.ts → operations.d.ts} +15 -1
- package/dist/operations.d.ts.map +1 -0
- package/dist/{library/public.js → operations.js} +18 -7
- package/dist/operations.js.map +1 -0
- package/dist/orchestrator.d.ts +1339 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +4308 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/packager/targetcli.js +4 -22
- package/dist/performance.d.ts +416 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +827 -0
- package/dist/performance.js.map +1 -0
- package/dist/quantum.d.ts +810 -0
- package/dist/quantum.d.ts.map +1 -0
- package/dist/quantum.js +2073 -0
- package/dist/quantum.js.map +1 -0
- package/dist/render.d.ts +381 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +1073 -0
- package/dist/render.js.map +1 -0
- package/dist/scheduler.d.ts +596 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +1259 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/security.d.ts +501 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +1170 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/{server/node.js → server.js} +16 -2
- package/dist/server.js.map +1 -0
- package/dist/tiers.d.ts +1002 -0
- package/dist/tiers.d.ts.map +1 -0
- package/dist/tiers.js +2165 -0
- package/dist/tiers.js.map +1 -0
- package/dist/virtual.d.ts +641 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +1285 -0
- package/dist/virtual.js.map +1 -0
- package/dist/virtualcpu.d.ts +316 -0
- package/dist/virtualcpu.d.ts.map +1 -0
- package/dist/virtualcpu.js +1180 -0
- package/dist/virtualcpu.js.map +1 -0
- package/dist/virtualgpu.d.ts +345 -0
- package/dist/virtualgpu.d.ts.map +1 -0
- package/dist/virtualgpu.js +1000 -0
- package/dist/virtualgpu.js.map +1 -0
- package/dist/virtualization.d.ts +607 -0
- package/dist/virtualization.d.ts.map +1 -0
- package/dist/virtualization.js +1187 -0
- package/dist/virtualization.js.map +1 -0
- package/dist/virtualmemory.d.ts +818 -0
- package/dist/virtualmemory.d.ts.map +1 -0
- package/dist/virtualmemory.js +1796 -0
- package/dist/virtualmemory.js.map +1 -0
- package/dist/webscrape.d.ts +720 -0
- package/dist/webscrape.d.ts.map +1 -0
- package/dist/webscrape.js +2697 -0
- package/dist/webscrape.js.map +1 -0
- package/docker.config +769 -0
- package/docs/CONVERSA.txt +1523 -0
- package/docs/alternatives.md +499 -0
- package/docs/architecture-1.8.19.md +76 -0
- package/docs/architecture-1.8.19.mmd +33 -0
- package/docs/architecture-1.8.19.png +0 -0
- package/docs/architecture.md +355 -0
- package/docs/brancharchive-2026-08-18.md +18 -0
- package/docs/browser.md +7 -0
- package/docs/consolidation.md +70 -0
- package/docs/e2ugh-engine.md +528 -0
- package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
- package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
- package/docs/hardware.md +342 -0
- package/docs/optimization.md +126 -0
- package/docs/performance.md +499 -0
- package/docs/planning.1.8.18.md +94 -0
- package/docs/planning.1.8.19.md +49 -0
- package/docs/releasenotes-1.8.19.md +35 -0
- package/docs/research-1.8.19-virtual-browser.md +27 -0
- package/docs/security.md +454 -0
- package/docs/todo-1.8.18.md +12 -0
- package/docs/todo-1.8.19.md +241 -0
- package/docs/viability.md +777 -0
- package/docs/virtualization.md +335 -0
- package/docs/web-duplicatecleanup.md +9 -0
- package/docs/web-ideas.md +106 -0
- package/docs/workflowimprovements-2026-08-19.md +70 -0
- package/gpumonitor.cpp +1543 -0
- package/gpus.json +2408 -0
- package/index.ts +1478 -0
- package/media.ts +1337 -0
- package/mttg.config +1549 -0
- package/orchestrator.ts +5462 -0
- package/package.json +304 -56
- package/passage.config +1331 -0
- package/performance.ts +1049 -0
- package/processors.json +2217 -0
- package/qemu.config +1062 -0
- package/qemubridge.py +1340 -0
- package/quantum.ts +2393 -0
- package/render.ts +1325 -0
- package/scheduler.ts +1600 -0
- package/security.ts +1449 -0
- package/tiers.ts +2871 -0
- package/tsconfig.json +29 -0
- package/virtualcpu.ts +1273 -0
- package/virtualgpu.ts +1181 -0
- package/virtualhardware.c +1011 -0
- package/virtualhardware.json +739 -0
- package/virtualization.ts +1628 -0
- package/virtualizationcore.cpp +4635 -0
- package/virtualmemory.ts +2303 -0
- package/vm.config.json +1910 -0
- package/{extension → web/extension}/manifest.json +1 -1
- package/web/readme.md +382 -0
- package/web/tsconfig.json +25 -0
- package/dist/adapters/forge.d.ts +0 -17
- package/dist/adapters/forge.d.ts.map +0 -1
- package/dist/adapters/forge.js +0 -19
- package/dist/adapters/forge.js.map +0 -1
- package/dist/adapters/forgejo.d.ts +0 -49
- package/dist/adapters/forgejo.d.ts.map +0 -1
- package/dist/adapters/forgejo.js +0 -8
- package/dist/adapters/forgejo.js.map +0 -1
- package/dist/adapters/github.d.ts +0 -12
- package/dist/adapters/github.d.ts.map +0 -1
- package/dist/adapters/github.js +0 -20
- package/dist/adapters/github.js.map +0 -1
- package/dist/adapters/gitlab.d.ts +0 -17
- package/dist/adapters/gitlab.d.ts.map +0 -1
- package/dist/adapters/gitlab.js +0 -10
- package/dist/adapters/gitlab.js.map +0 -1
- package/dist/adapters/huggingface.d.ts +0 -17
- package/dist/adapters/huggingface.d.ts.map +0 -1
- package/dist/adapters/huggingface.js +0 -6
- package/dist/adapters/huggingface.js.map +0 -1
- package/dist/adapters/socket.d.ts +0 -11
- package/dist/adapters/socket.d.ts.map +0 -1
- package/dist/adapters/socket.js +0 -17
- package/dist/adapters/socket.js.map +0 -1
- package/dist/adapters/transport.d.ts +0 -7
- package/dist/adapters/transport.d.ts.map +0 -1
- package/dist/adapters/transport.js +0 -36
- package/dist/adapters/transport.js.map +0 -1
- package/dist/ai/chunk.d.ts +0 -2
- package/dist/ai/chunk.d.ts.map +0 -1
- package/dist/ai/chunk.js +0 -36
- package/dist/ai/chunk.js.map +0 -1
- package/dist/ai/llmstxt.d.ts +0 -6
- package/dist/ai/llmstxt.d.ts.map +0 -1
- package/dist/ai/llmstxt.js +0 -12
- package/dist/ai/llmstxt.js.map +0 -1
- package/dist/ai/provenance.d.ts +0 -22
- package/dist/ai/provenance.d.ts.map +0 -1
- package/dist/ai/provenance.js +0 -25
- package/dist/ai/provenance.js.map +0 -1
- package/dist/ai/rag.d.ts +0 -26
- package/dist/ai/rag.d.ts.map +0 -1
- package/dist/ai/rag.js +0 -22
- package/dist/ai/rag.js.map +0 -1
- package/dist/ai/tokens.d.ts +0 -15
- package/dist/ai/tokens.d.ts.map +0 -1
- package/dist/ai/tokens.js +0 -9
- package/dist/ai/tokens.js.map +0 -1
- package/dist/api/auth.d.ts +0 -16
- package/dist/api/auth.d.ts.map +0 -1
- package/dist/api/auth.js +0 -19
- package/dist/api/auth.js.map +0 -1
- package/dist/api/contracts.d.ts +0 -28
- package/dist/api/contracts.d.ts.map +0 -1
- package/dist/api/contracts.js +0 -14
- package/dist/api/contracts.js.map +0 -1
- package/dist/api/control.d.ts +0 -10
- package/dist/api/control.d.ts.map +0 -1
- package/dist/api/control.js +0 -35
- package/dist/api/control.js.map +0 -1
- package/dist/api/http.d.ts +0 -7
- package/dist/api/http.d.ts.map +0 -1
- package/dist/api/http.js +0 -12
- package/dist/api/http.js.map +0 -1
- package/dist/api/rate.d.ts +0 -28
- package/dist/api/rate.d.ts.map +0 -1
- package/dist/api/rate.js +0 -36
- package/dist/api/rate.js.map +0 -1
- package/dist/api/security.d.ts +0 -12
- package/dist/api/security.d.ts.map +0 -1
- package/dist/api/security.js +0 -56
- package/dist/api/security.js.map +0 -1
- package/dist/api/service.d.ts +0 -5
- package/dist/api/service.d.ts.map +0 -1
- package/dist/api/service.js +0 -70
- package/dist/api/service.js.map +0 -1
- package/dist/apps/registry.d.ts +0 -33
- package/dist/apps/registry.d.ts.map +0 -1
- package/dist/apps/registry.js +0 -24
- package/dist/apps/registry.js.map +0 -1
- package/dist/binary/archive.d.ts +0 -27
- package/dist/binary/archive.d.ts.map +0 -1
- package/dist/binary/archive.js +0 -46
- package/dist/binary/archive.js.map +0 -1
- package/dist/binary/build.d.ts +0 -29
- package/dist/binary/build.d.ts.map +0 -1
- package/dist/binary/build.js +0 -17
- package/dist/binary/build.js.map +0 -1
- package/dist/binary/transform.d.ts +0 -70
- package/dist/binary/transform.d.ts.map +0 -1
- package/dist/binary/transform.js +0 -105
- package/dist/binary/transform.js.map +0 -1
- package/dist/bot/adapter.d.ts +0 -5
- package/dist/bot/adapter.d.ts.map +0 -1
- package/dist/bot/adapter.js +0 -11
- package/dist/bot/adapter.js.map +0 -1
- package/dist/bot/bot.d.ts +0 -28
- package/dist/bot/bot.d.ts.map +0 -1
- package/dist/bot/bot.js +0 -52
- package/dist/bot/bot.js.map +0 -1
- package/dist/bot/commands.d.ts +0 -8
- package/dist/bot/commands.d.ts.map +0 -1
- package/dist/bot/commands.js +0 -19
- package/dist/bot/commands.js.map +0 -1
- package/dist/bot/permissions.d.ts +0 -13
- package/dist/bot/permissions.d.ts.map +0 -1
- package/dist/bot/permissions.js +0 -16
- package/dist/bot/permissions.js.map +0 -1
- package/dist/browser/actions.d.ts +0 -33
- package/dist/browser/actions.d.ts.map +0 -1
- package/dist/browser/actions.js +0 -44
- package/dist/browser/actions.js.map +0 -1
- package/dist/browser/agent.d.ts +0 -21
- package/dist/browser/agent.d.ts.map +0 -1
- package/dist/browser/agent.js +0 -13
- package/dist/browser/agent.js.map +0 -1
- package/dist/browser/context.d.ts +0 -43
- package/dist/browser/context.d.ts.map +0 -1
- package/dist/browser/context.js +0 -54
- package/dist/browser/context.js.map +0 -1
- package/dist/browser/fingerprint.d.ts +0 -4
- package/dist/browser/fingerprint.d.ts.map +0 -1
- package/dist/browser/fingerprint.js +0 -12
- package/dist/browser/fingerprint.js.map +0 -1
- package/dist/browser/index.d.ts +0 -11
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/browser/index.js +0 -11
- package/dist/browser/index.js.map +0 -1
- package/dist/browser/playwright.d.ts +0 -11
- package/dist/browser/playwright.d.ts.map +0 -1
- package/dist/browser/playwright.js +0 -24
- package/dist/browser/playwright.js.map +0 -1
- package/dist/browser/recorder.d.ts +0 -21
- package/dist/browser/recorder.d.ts.map +0 -1
- package/dist/browser/recorder.js +0 -58
- package/dist/browser/recorder.js.map +0 -1
- package/dist/browser/session.d.ts +0 -14
- package/dist/browser/session.d.ts.map +0 -1
- package/dist/browser/session.js +0 -21
- package/dist/browser/session.js.map +0 -1
- package/dist/browser/snapshot.d.ts +0 -69
- package/dist/browser/snapshot.d.ts.map +0 -1
- package/dist/browser/snapshot.js +0 -133
- package/dist/browser/snapshot.js.map +0 -1
- package/dist/captcha/contract.d.ts +0 -35
- package/dist/captcha/contract.d.ts.map +0 -1
- package/dist/captcha/contract.js +0 -17
- package/dist/captcha/contract.js.map +0 -1
- package/dist/captcha/evidence.d.ts +0 -10
- package/dist/captcha/evidence.d.ts.map +0 -1
- package/dist/captcha/evidence.js +0 -9
- package/dist/captcha/evidence.js.map +0 -1
- package/dist/captcha/guard.d.ts +0 -23
- package/dist/captcha/guard.d.ts.map +0 -1
- package/dist/captcha/guard.js +0 -12
- package/dist/captcha/guard.js.map +0 -1
- package/dist/cli/main.d.ts +0 -4
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -46
- package/dist/cli/main.js.map +0 -1
- package/dist/core/errors.d.ts +0 -84
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -54
- package/dist/core/errors.js.map +0 -1
- package/dist/core/events.d.ts +0 -9
- package/dist/core/events.d.ts.map +0 -1
- package/dist/core/events.js +0 -21
- package/dist/core/events.js.map +0 -1
- package/dist/core/hash.d.ts +0 -10
- package/dist/core/hash.d.ts.map +0 -1
- package/dist/core/hash.js +0 -82
- package/dist/core/hash.js.map +0 -1
- package/dist/core/ids.d.ts +0 -10
- package/dist/core/ids.d.ts.map +0 -1
- package/dist/core/ids.js +0 -15
- package/dist/core/ids.js.map +0 -1
- package/dist/delivery/manifest.d.ts +0 -35
- package/dist/delivery/manifest.d.ts.map +0 -1
- package/dist/delivery/manifest.js +0 -68
- package/dist/delivery/manifest.js.map +0 -1
- package/dist/deploy/index.d.ts +0 -6
- package/dist/deploy/index.d.ts.map +0 -1
- package/dist/deploy/index.js +0 -6
- package/dist/deploy/index.js.map +0 -1
- package/dist/dispatch/resumable.d.ts +0 -102
- package/dist/dispatch/resumable.d.ts.map +0 -1
- package/dist/dispatch/resumable.js +0 -64
- package/dist/dispatch/resumable.js.map +0 -1
- package/dist/dispatch/workflow.d.ts +0 -6
- package/dist/dispatch/workflow.d.ts.map +0 -1
- package/dist/dispatch/workflow.js +0 -37
- package/dist/dispatch/workflow.js.map +0 -1
- package/dist/domain/artifacts.d.ts +0 -12
- package/dist/domain/artifacts.d.ts.map +0 -1
- package/dist/domain/artifacts.js +0 -14
- package/dist/domain/artifacts.js.map +0 -1
- package/dist/domain/jobs.d.ts +0 -12
- package/dist/domain/jobs.d.ts.map +0 -1
- package/dist/domain/jobs.js +0 -20
- package/dist/domain/jobs.js.map +0 -1
- package/dist/domain/providers.d.ts +0 -10
- package/dist/domain/providers.d.ts.map +0 -1
- package/dist/domain/providers.js +0 -8
- package/dist/domain/providers.js.map +0 -1
- package/dist/domain/runtime.d.ts +0 -14
- package/dist/domain/runtime.d.ts.map +0 -1
- package/dist/domain/runtime.js +0 -10
- package/dist/domain/runtime.js.map +0 -1
- package/dist/domain/sessions.d.ts +0 -12
- package/dist/domain/sessions.d.ts.map +0 -1
- package/dist/domain/sessions.js +0 -57
- package/dist/domain/sessions.js.map +0 -1
- package/dist/examples/localjob.d.ts +0 -2
- package/dist/examples/localjob.d.ts.map +0 -1
- package/dist/examples/localjob.js.map +0 -1
- package/dist/examples/publicapi.d.ts +0 -2
- package/dist/examples/publicapi.d.ts.map +0 -1
- package/dist/examples/publicapi.js.map +0 -1
- package/dist/extension/build.d.ts +0 -9
- package/dist/extension/build.d.ts.map +0 -1
- package/dist/extension/build.js +0 -85
- package/dist/extension/build.js.map +0 -1
- package/dist/extension/content.d.ts +0 -6
- package/dist/extension/content.d.ts.map +0 -1
- package/dist/extension/content.js +0 -135
- package/dist/extension/content.js.map +0 -1
- package/dist/extension/index.d.ts +0 -7
- package/dist/extension/index.d.ts.map +0 -1
- package/dist/extension/index.js +0 -7
- package/dist/extension/index.js.map +0 -1
- package/dist/extension/pagebridge.d.ts +0 -6
- package/dist/extension/pagebridge.d.ts.map +0 -1
- package/dist/extension/pagebridge.js +0 -42
- package/dist/extension/pagebridge.js.map +0 -1
- package/dist/extension/permissions.d.ts +0 -26
- package/dist/extension/permissions.d.ts.map +0 -1
- package/dist/extension/permissions.js +0 -28
- package/dist/extension/permissions.js.map +0 -1
- package/dist/extension/popup.d.ts +0 -5
- package/dist/extension/popup.d.ts.map +0 -1
- package/dist/extension/popup.js +0 -26
- package/dist/extension/popup.js.map +0 -1
- package/dist/extension/protocol.d.ts +0 -58
- package/dist/extension/protocol.d.ts.map +0 -1
- package/dist/extension/protocol.js +0 -101
- package/dist/extension/protocol.js.map +0 -1
- package/dist/extension/serviceworker.d.ts +0 -25
- package/dist/extension/serviceworker.d.ts.map +0 -1
- package/dist/extension/serviceworker.js +0 -102
- package/dist/extension/serviceworker.js.map +0 -1
- package/dist/extension/worker.d.ts +0 -28
- package/dist/extension/worker.d.ts.map +0 -1
- package/dist/extension/worker.js +0 -22
- package/dist/extension/worker.js.map +0 -1
- package/dist/format/check.d.ts +0 -8
- package/dist/format/check.d.ts.map +0 -1
- package/dist/format/check.js +0 -38
- package/dist/format/check.js.map +0 -1
- package/dist/isolation/contracts.d.ts.map +0 -1
- package/dist/isolation/contracts.js.map +0 -1
- package/dist/library/public.d.ts.map +0 -1
- package/dist/library/public.js.map +0 -1
- package/dist/mcp/browser.d.ts +0 -9
- package/dist/mcp/browser.d.ts.map +0 -1
- package/dist/mcp/browser.js +0 -13
- package/dist/mcp/browser.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -35
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -40
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/transport.d.ts +0 -7
- package/dist/mcp/transport.d.ts.map +0 -1
- package/dist/mcp/transport.js +0 -17
- package/dist/mcp/transport.js.map +0 -1
- package/dist/memory/bridge.d.ts +0 -14
- package/dist/memory/bridge.d.ts.map +0 -1
- package/dist/memory/bridge.js +0 -16
- package/dist/memory/bridge.js.map +0 -1
- package/dist/memory/engine.d.ts +0 -38
- package/dist/memory/engine.d.ts.map +0 -1
- package/dist/memory/engine.js +0 -109
- package/dist/memory/engine.js.map +0 -1
- package/dist/memory/modes.d.ts +0 -43
- package/dist/memory/modes.d.ts.map +0 -1
- package/dist/memory/modes.js +0 -66
- package/dist/memory/modes.js.map +0 -1
- package/dist/memory/objects.d.ts +0 -21
- package/dist/memory/objects.d.ts.map +0 -1
- package/dist/memory/objects.js +0 -20
- package/dist/memory/objects.js.map +0 -1
- package/dist/memory/planner.d.ts +0 -66
- package/dist/memory/planner.d.ts.map +0 -1
- package/dist/memory/planner.js +0 -108
- package/dist/memory/planner.js.map +0 -1
- package/dist/memory/targets.d.ts +0 -78
- package/dist/memory/targets.d.ts.map +0 -1
- package/dist/memory/targets.js +0 -29
- package/dist/memory/targets.js.map +0 -1
- package/dist/memory/transforms.d.ts +0 -19
- package/dist/memory/transforms.d.ts.map +0 -1
- package/dist/memory/transforms.js +0 -14
- package/dist/memory/transforms.js.map +0 -1
- package/dist/modes/matrix.d.ts +0 -23
- package/dist/modes/matrix.d.ts.map +0 -1
- package/dist/modes/matrix.js +0 -18
- package/dist/modes/matrix.js.map +0 -1
- package/dist/modes/modes.d.ts +0 -33
- package/dist/modes/modes.d.ts.map +0 -1
- package/dist/modes/modes.js +0 -15
- package/dist/modes/modes.js.map +0 -1
- package/dist/modes/resolve.d.ts +0 -96
- package/dist/modes/resolve.d.ts.map +0 -1
- package/dist/modes/resolve.js +0 -48
- package/dist/modes/resolve.js.map +0 -1
- package/dist/observability/metrics.d.ts +0 -14
- package/dist/observability/metrics.d.ts.map +0 -1
- package/dist/observability/metrics.js +0 -18
- package/dist/observability/metrics.js.map +0 -1
- package/dist/packager/manifest.d.ts +0 -66
- package/dist/packager/manifest.d.ts.map +0 -1
- package/dist/packager/manifest.js +0 -94
- package/dist/packager/manifest.js.map +0 -1
- package/dist/packager/publish.d.ts +0 -51
- package/dist/packager/publish.d.ts.map +0 -1
- package/dist/packager/publish.js +0 -18
- package/dist/packager/publish.js.map +0 -1
- package/dist/packager/targetcli.d.ts +0 -7
- package/dist/packager/targetcli.d.ts.map +0 -1
- package/dist/packager/targetcli.js.map +0 -1
- package/dist/persistence/adapter.d.ts +0 -5
- package/dist/persistence/adapter.d.ts.map +0 -1
- package/dist/persistence/adapter.js +0 -11
- package/dist/persistence/adapter.js.map +0 -1
- package/dist/persistence/drizzle.d.ts +0 -2
- package/dist/persistence/drizzle.d.ts.map +0 -1
- package/dist/persistence/drizzle.js +0 -12
- package/dist/persistence/drizzle.js.map +0 -1
- package/dist/persistence/memory.d.ts +0 -2
- package/dist/persistence/memory.d.ts.map +0 -1
- package/dist/persistence/memory.js +0 -27
- package/dist/persistence/memory.js.map +0 -1
- package/dist/persistence/migrations.d.ts +0 -19
- package/dist/persistence/migrations.d.ts.map +0 -1
- package/dist/persistence/migrations.js +0 -13
- package/dist/persistence/migrations.js.map +0 -1
- package/dist/persistence/prisma.d.ts +0 -2
- package/dist/persistence/prisma.d.ts.map +0 -1
- package/dist/persistence/prisma.js +0 -25
- package/dist/persistence/prisma.js.map +0 -1
- package/dist/persistence/schema.d.ts +0 -63
- package/dist/persistence/schema.d.ts.map +0 -1
- package/dist/persistence/schema.js +0 -28
- package/dist/persistence/schema.js.map +0 -1
- package/dist/persistence/sql.d.ts +0 -3
- package/dist/persistence/sql.d.ts.map +0 -1
- package/dist/persistence/sql.js +0 -37
- package/dist/persistence/sql.js.map +0 -1
- package/dist/protocol/blocks.d.ts +0 -10
- package/dist/protocol/blocks.d.ts.map +0 -1
- package/dist/protocol/blocks.js +0 -26
- package/dist/protocol/blocks.js.map +0 -1
- package/dist/protocol/json.d.ts +0 -6
- package/dist/protocol/json.d.ts.map +0 -1
- package/dist/protocol/json.js +0 -6
- package/dist/protocol/json.js.map +0 -1
- package/dist/protocol/ndjson.d.ts +0 -3
- package/dist/protocol/ndjson.d.ts.map +0 -1
- package/dist/protocol/ndjson.js +0 -20
- package/dist/protocol/ndjson.js.map +0 -1
- package/dist/protocol/sse.d.ts +0 -7
- package/dist/protocol/sse.d.ts.map +0 -1
- package/dist/protocol/sse.js +0 -25
- package/dist/protocol/sse.js.map +0 -1
- package/dist/proxy/pool.d.ts +0 -9
- package/dist/proxy/pool.d.ts.map +0 -1
- package/dist/proxy/pool.js +0 -27
- package/dist/proxy/pool.js.map +0 -1
- package/dist/queue/idempotency.d.ts +0 -10
- package/dist/queue/idempotency.d.ts.map +0 -1
- package/dist/queue/idempotency.js +0 -13
- package/dist/queue/idempotency.js.map +0 -1
- package/dist/queue/persistent.d.ts +0 -14
- package/dist/queue/persistent.d.ts.map +0 -1
- package/dist/queue/persistent.js +0 -66
- package/dist/queue/persistent.js.map +0 -1
- package/dist/queue/queue.d.ts +0 -7
- package/dist/queue/queue.d.ts.map +0 -1
- package/dist/queue/queue.js +0 -55
- package/dist/queue/queue.js.map +0 -1
- package/dist/queue/saga.d.ts +0 -5
- package/dist/queue/saga.d.ts.map +0 -1
- package/dist/queue/saga.js +0 -20
- package/dist/queue/saga.js.map +0 -1
- package/dist/release/assets.d.ts +0 -144
- package/dist/release/assets.d.ts.map +0 -1
- package/dist/release/assets.js +0 -157
- package/dist/release/assets.js.map +0 -1
- package/dist/release/evidence.d.ts +0 -92
- package/dist/release/evidence.d.ts.map +0 -1
- package/dist/release/evidence.js +0 -148
- package/dist/release/evidence.js.map +0 -1
- package/dist/release/verify.d.ts +0 -12
- package/dist/release/verify.d.ts.map +0 -1
- package/dist/release/verify.js +0 -112
- package/dist/release/verify.js.map +0 -1
- package/dist/runners/chain.d.ts +0 -125
- package/dist/runners/chain.d.ts.map +0 -1
- package/dist/runners/chain.js +0 -95
- package/dist/runners/chain.js.map +0 -1
- package/dist/runners/health.d.ts +0 -36
- package/dist/runners/health.d.ts.map +0 -1
- package/dist/runners/health.js +0 -26
- package/dist/runners/health.js.map +0 -1
- package/dist/runners/heartbeat.d.ts +0 -23
- package/dist/runners/heartbeat.d.ts.map +0 -1
- package/dist/runners/heartbeat.js +0 -29
- package/dist/runners/heartbeat.js.map +0 -1
- package/dist/runners/inprocess.d.ts +0 -17
- package/dist/runners/inprocess.d.ts.map +0 -1
- package/dist/runners/inprocess.js +0 -20
- package/dist/runners/inprocess.js.map +0 -1
- package/dist/runners/scheduler.d.ts +0 -5
- package/dist/runners/scheduler.d.ts.map +0 -1
- package/dist/runners/scheduler.js +0 -19
- package/dist/runners/scheduler.js.map +0 -1
- package/dist/runtime/abort.d.ts +0 -8
- package/dist/runtime/abort.d.ts.map +0 -1
- package/dist/runtime/abort.js +0 -13
- package/dist/runtime/abort.js.map +0 -1
- package/dist/runtime/compatibility.d.ts +0 -37
- package/dist/runtime/compatibility.d.ts.map +0 -1
- package/dist/runtime/compatibility.js +0 -10
- package/dist/runtime/compatibility.js.map +0 -1
- package/dist/runtime/detect.d.ts +0 -13
- package/dist/runtime/detect.d.ts.map +0 -1
- package/dist/runtime/detect.js +0 -18
- package/dist/runtime/detect.js.map +0 -1
- package/dist/runtime/engine.d.ts +0 -20
- package/dist/runtime/engine.d.ts.map +0 -1
- package/dist/runtime/engine.js +0 -61
- package/dist/runtime/engine.js.map +0 -1
- package/dist/runtime/retry.d.ts +0 -19
- package/dist/runtime/retry.d.ts.map +0 -1
- package/dist/runtime/retry.js +0 -54
- package/dist/runtime/retry.js.map +0 -1
- package/dist/runtime/worker.d.ts +0 -10
- package/dist/runtime/worker.d.ts.map +0 -1
- package/dist/runtime/worker.js +0 -25
- package/dist/runtime/worker.js.map +0 -1
- package/dist/scrape/cache.d.ts +0 -45
- package/dist/scrape/cache.d.ts.map +0 -1
- package/dist/scrape/cache.js +0 -45
- package/dist/scrape/cache.js.map +0 -1
- package/dist/scrape/crawl.d.ts +0 -47
- package/dist/scrape/crawl.d.ts.map +0 -1
- package/dist/scrape/crawl.js +0 -114
- package/dist/scrape/crawl.js.map +0 -1
- package/dist/scrape/extract.d.ts +0 -63
- package/dist/scrape/extract.d.ts.map +0 -1
- package/dist/scrape/extract.js +0 -47
- package/dist/scrape/extract.js.map +0 -1
- package/dist/scrape/normalize.d.ts +0 -52
- package/dist/scrape/normalize.d.ts.map +0 -1
- package/dist/scrape/normalize.js +0 -102
- package/dist/scrape/normalize.js.map +0 -1
- package/dist/scrape/robots.d.ts +0 -37
- package/dist/scrape/robots.d.ts.map +0 -1
- package/dist/scrape/robots.js +0 -71
- package/dist/scrape/robots.js.map +0 -1
- package/dist/scrape/schema.d.ts +0 -23
- package/dist/scrape/schema.d.ts.map +0 -1
- package/dist/scrape/schema.js +0 -92
- package/dist/scrape/schema.js.map +0 -1
- package/dist/scrape/scraper.d.ts +0 -6
- package/dist/scrape/scraper.d.ts.map +0 -1
- package/dist/scrape/scraper.js +0 -46
- package/dist/scrape/scraper.js.map +0 -1
- package/dist/scrape/semantic.d.ts +0 -25
- package/dist/scrape/semantic.d.ts.map +0 -1
- package/dist/scrape/semantic.js +0 -27
- package/dist/scrape/semantic.js.map +0 -1
- package/dist/server/node.d.ts +0 -7
- package/dist/server/node.d.ts.map +0 -1
- package/dist/server/node.js.map +0 -1
- package/dist/sessions/file.d.ts +0 -25
- package/dist/sessions/file.d.ts.map +0 -1
- package/dist/sessions/file.js +0 -13
- package/dist/sessions/file.js.map +0 -1
- package/dist/sessions/replay.d.ts +0 -9
- package/dist/sessions/replay.d.ts.map +0 -1
- package/dist/sessions/replay.js +0 -70
- package/dist/sessions/replay.js.map +0 -1
- package/dist/sessions/store.d.ts +0 -25
- package/dist/sessions/store.d.ts.map +0 -1
- package/dist/sessions/store.js +0 -13
- package/dist/sessions/store.js.map +0 -1
- package/dist/storage/adapter.d.ts +0 -5
- package/dist/storage/adapter.d.ts.map +0 -1
- package/dist/storage/adapter.js +0 -11
- package/dist/storage/adapter.js.map +0 -1
- package/dist/storage/cache.d.ts +0 -23
- package/dist/storage/cache.d.ts.map +0 -1
- package/dist/storage/cache.js +0 -79
- package/dist/storage/cache.js.map +0 -1
- package/dist/storage/checksum.d.ts +0 -3
- package/dist/storage/checksum.d.ts.map +0 -1
- package/dist/storage/checksum.js +0 -19
- package/dist/storage/checksum.js.map +0 -1
- package/dist/storage/chunked.d.ts +0 -21
- package/dist/storage/chunked.d.ts.map +0 -1
- package/dist/storage/chunked.js +0 -67
- package/dist/storage/chunked.js.map +0 -1
- package/dist/storage/content.d.ts +0 -24
- package/dist/storage/content.d.ts.map +0 -1
- package/dist/storage/content.js +0 -44
- package/dist/storage/content.js.map +0 -1
- package/dist/storage/filehosting.d.ts +0 -2
- package/dist/storage/filehosting.d.ts.map +0 -1
- package/dist/storage/filehosting.js +0 -24
- package/dist/storage/filehosting.js.map +0 -1
- package/dist/storage/githubcontents.d.ts +0 -2
- package/dist/storage/githubcontents.d.ts.map +0 -1
- package/dist/storage/githubcontents.js +0 -29
- package/dist/storage/githubcontents.js.map +0 -1
- package/dist/storage/index.d.ts +0 -12
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -12
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/local.d.ts +0 -2
- package/dist/storage/local.d.ts.map +0 -1
- package/dist/storage/local.js +0 -72
- package/dist/storage/local.js.map +0 -1
- package/dist/storage/memory.d.ts +0 -6
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js +0 -36
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/pool.d.ts +0 -95
- package/dist/storage/pool.d.ts.map +0 -1
- package/dist/storage/pool.js +0 -202
- package/dist/storage/pool.js.map +0 -1
- package/dist/storage/s3compatible.d.ts +0 -3
- package/dist/storage/s3compatible.d.ts.map +0 -1
- package/dist/storage/s3compatible.js +0 -70
- package/dist/storage/s3compatible.js.map +0 -1
- package/dist/storage/sync.d.ts +0 -47
- package/dist/storage/sync.d.ts.map +0 -1
- package/dist/storage/sync.js +0 -75
- package/dist/storage/sync.js.map +0 -1
- package/dist/surfaces/adapters.d.ts +0 -97
- package/dist/surfaces/adapters.d.ts.map +0 -1
- package/dist/surfaces/adapters.js +0 -50
- package/dist/surfaces/adapters.js.map +0 -1
- package/dist/surfaces/controls.d.ts +0 -18
- package/dist/surfaces/controls.d.ts.map +0 -1
- package/dist/surfaces/controls.js +0 -45
- package/dist/surfaces/controls.js.map +0 -1
- package/dist/surfaces/manifest.d.ts +0 -68
- package/dist/surfaces/manifest.d.ts.map +0 -1
- package/dist/surfaces/manifest.js +0 -42
- package/dist/surfaces/manifest.js.map +0 -1
- package/dist/surfaces/n8n.d.ts +0 -25
- package/dist/surfaces/n8n.d.ts.map +0 -1
- package/dist/surfaces/n8n.js +0 -31
- package/dist/surfaces/n8n.js.map +0 -1
- package/dist/surfaces/operations.d.ts +0 -32
- package/dist/surfaces/operations.d.ts.map +0 -1
- package/dist/surfaces/operations.js +0 -53
- package/dist/surfaces/operations.js.map +0 -1
- package/dist/surfaces/requirements.d.ts +0 -29
- package/dist/surfaces/requirements.d.ts.map +0 -1
- package/dist/surfaces/requirements.js +0 -50
- package/dist/surfaces/requirements.js.map +0 -1
- package/dist/surfaces/targets.d.ts +0 -196
- package/dist/surfaces/targets.d.ts.map +0 -1
- package/dist/surfaces/targets.js +0 -27
- package/dist/surfaces/targets.js.map +0 -1
- package/dist/webhook/delivery.d.ts +0 -18
- package/dist/webhook/delivery.d.ts.map +0 -1
- package/dist/webhook/delivery.js +0 -36
- package/dist/webhook/delivery.js.map +0 -1
- package/dist/webhook/receiver.d.ts +0 -26
- package/dist/webhook/receiver.d.ts.map +0 -1
- package/dist/webhook/receiver.js +0 -24
- package/dist/webhook/receiver.js.map +0 -1
- package/dist/webhook/signature.d.ts +0 -3
- package/dist/webhook/signature.d.ts.map +0 -1
- package/dist/webhook/signature.js +0 -7
- package/dist/webhook/signature.js.map +0 -1
- package/dist/workflow/manifest.d.ts +0 -22
- package/dist/workflow/manifest.d.ts.map +0 -1
- package/dist/workflow/manifest.js +0 -21
- package/dist/workflow/manifest.js.map +0 -1
- package/dist/workflow/registry.d.ts +0 -7
- package/dist/workflow/registry.d.ts.map +0 -1
- package/dist/workflow/registry.js +0 -18
- package/dist/workflow/registry.js.map +0 -1
- package/dist/workflow/templates.d.ts +0 -6
- package/dist/workflow/templates.d.ts.map +0 -1
- package/dist/workflow/templates.js +0 -18
- package/dist/workflow/templates.js.map +0 -1
- package/dist/workflow/triggers.d.ts +0 -64
- package/dist/workflow/triggers.d.ts.map +0 -1
- package/dist/workflow/triggers.js +0 -99
- package/dist/workflow/triggers.js.map +0 -1
- /package/{extension/README.md → docs/extension.md} +0 -0
package/virtualcpu.ts
ADDED
|
@@ -0,0 +1,1273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* virtualcpu - virtual processor bank and procfs generators.
|
|
3
|
+
*
|
|
4
|
+
* This module embeds the BEST_VIRTUAL_PROCESSORS bank with real, verified
|
|
5
|
+
* specifications of the strongest server, workstation and desktop processors
|
|
6
|
+
* available on 2026-08-22 (AMD EPYC 9965 Turin, Ryzen 9 9950X3D, Threadripper
|
|
7
|
+
* PRO 9995WX, Threadripper 7980X, Intel Core Ultra 9 285K, AMD EPYC 9955) and
|
|
8
|
+
* converts any of them into byte-accurate procfs texts: generateVirtualCpuinfo
|
|
9
|
+
* renders a complete /proc/cpuinfo payload with vendor identity, family,
|
|
10
|
+
* model, topology, cache sizes and the full Zen 5 flag set (avx512f, avx512bw,
|
|
11
|
+
* avx512cd, avx512dq, avx512vl, avx512_bf16, sha_ni and friends), while
|
|
12
|
+
* generateVirtualLscpu renders the util-linux summary with NUMA ranges and
|
|
13
|
+
* vulnerability lines. The module also owns the cpuRegistry, a fluent
|
|
14
|
+
* virtualcpubuilder, a processor factory, topology solving, capability
|
|
15
|
+
* scoring, the marchFlag/validateCpuCount helpers absorbed from the v2 stub
|
|
16
|
+
* and the boards() socket index.
|
|
17
|
+
*
|
|
18
|
+
* /proc/meminfo generation (generateVirtualMeminfo, meminfoptions and
|
|
19
|
+
* pagealign) moved to virtualmemory.ts in the v2 reorganization so every
|
|
20
|
+
* memory concern lives in one module.
|
|
21
|
+
*
|
|
22
|
+
* Data sources (verified 2026-08-22): amd.com product pages (EPYC 9965,
|
|
23
|
+
* EPYC 9955, Ryzen 9 9950X3D, Threadripper PRO 9995WX), intel.com ARK
|
|
24
|
+
* (Core Ultra 9 285K), techpowerup.com CPU database and the QEMU 11.1.0
|
|
25
|
+
* target/i386 CPU model table (EPYC-v5).
|
|
26
|
+
*
|
|
27
|
+
* Contexts (24): hardwareerror, vendorid, vendorprofile, ZEN5FLAGS,
|
|
28
|
+
* ARROWLAKEFLAGS, vendorprofiles, virtualcpuspec, BEST_VIRTUAL_PROCESSORS,
|
|
29
|
+
* cpuRegistry, solvetopology, generateVirtualCpuinfo, generateVirtualLscpu,
|
|
30
|
+
* virtualcpubuilder, createVirtualProcessor, validateCpuCount, marchFlag,
|
|
31
|
+
* boards, cpuscore, compareVirtualProcessors, listBestVirtualProcessors,
|
|
32
|
+
* serializeprovisionedcpu, modellease, stableModelId, virtualcpudemo.
|
|
33
|
+
*
|
|
34
|
+
* Patterns: registry (cpuRegistry), builder (virtualcpubuilder), factory
|
|
35
|
+
* (createVirtualProcessor), proxy-free disposable lease (modellease).
|
|
36
|
+
* Rules: lowercase identifiers, english jsdoc, third person, no emoji,
|
|
37
|
+
* try/catch catcher on every fallible path, node:* built-ins only, and no
|
|
38
|
+
* hardcoded localhost address anywhere.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { createHash, randomInt } from 'node:crypto';
|
|
42
|
+
|
|
43
|
+
/* ------------------------------------------------------------------ */
|
|
44
|
+
/* Section 1: errors */
|
|
45
|
+
/* ------------------------------------------------------------------ */
|
|
46
|
+
|
|
47
|
+
/** Error thrown by every hardware subsystem with an optional cause chain. */
|
|
48
|
+
export class hardwareerror extends Error {
|
|
49
|
+
/** Machine readable subsystem tag. */
|
|
50
|
+
readonly subsystem: string;
|
|
51
|
+
|
|
52
|
+
constructor(message: string, options?: { cause?: Error; subsystem?: string }) {
|
|
53
|
+
super(message, options);
|
|
54
|
+
this.name = 'hardwareerror';
|
|
55
|
+
this.subsystem = options?.subsystem ?? 'virtualcpu';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ------------------------------------------------------------------ */
|
|
60
|
+
/* Section 2: vendor identities and flag sets */
|
|
61
|
+
/* ------------------------------------------------------------------ */
|
|
62
|
+
|
|
63
|
+
/** Supported CPU vendors. */
|
|
64
|
+
export type vendorid = 'amd' | 'intel';
|
|
65
|
+
|
|
66
|
+
/** Static vendor profile rendered into every cpuinfo block. */
|
|
67
|
+
export type vendorprofile = {
|
|
68
|
+
readonly vendorid: string;
|
|
69
|
+
readonly flags: readonly string[];
|
|
70
|
+
readonly bugs: readonly string[];
|
|
71
|
+
readonly tlbsize: string | null;
|
|
72
|
+
readonly cpuidlevel: number;
|
|
73
|
+
readonly powermanagement: string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Complete Zen 5 flag set as observed in production /proc/cpuinfo dumps of
|
|
78
|
+
* AMD Turin and Granite Ridge machines. Includes the full AVX-512 family
|
|
79
|
+
* (avx512f, avx512dq, avx512cd, avx512bw, avx512vl, avx512_bf16, avx512vbmi,
|
|
80
|
+
* avx512vbmi2, avx512ifma, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
|
81
|
+
* avx512bitalg), the vector crypto extensions (sha_ni, gfni, vaes,
|
|
82
|
+
* vpclmulqdq) and the modern memory extensions (movdiri, movdir64b, fsrm,
|
|
83
|
+
* serialize, cldemote).
|
|
84
|
+
*/
|
|
85
|
+
export const ZEN5FLAGS: readonly string[] = [
|
|
86
|
+
'fpu',
|
|
87
|
+
'vme',
|
|
88
|
+
'de',
|
|
89
|
+
'pse',
|
|
90
|
+
'tsc',
|
|
91
|
+
'msr',
|
|
92
|
+
'pae',
|
|
93
|
+
'mce',
|
|
94
|
+
'cx8',
|
|
95
|
+
'apic',
|
|
96
|
+
'sep',
|
|
97
|
+
'mtrr',
|
|
98
|
+
'pge',
|
|
99
|
+
'mca',
|
|
100
|
+
'cmov',
|
|
101
|
+
'pat',
|
|
102
|
+
'pse36',
|
|
103
|
+
'clflush',
|
|
104
|
+
'mmx',
|
|
105
|
+
'fxsr',
|
|
106
|
+
'sse',
|
|
107
|
+
'sse2',
|
|
108
|
+
'ht',
|
|
109
|
+
'syscall',
|
|
110
|
+
'nx',
|
|
111
|
+
'mmxext',
|
|
112
|
+
'fxsr_opt',
|
|
113
|
+
'pdpe1gb',
|
|
114
|
+
'rdtscp',
|
|
115
|
+
'lm',
|
|
116
|
+
'constant_tsc',
|
|
117
|
+
'rep_good',
|
|
118
|
+
'amd_lbr_v2',
|
|
119
|
+
'nopl',
|
|
120
|
+
'nonstop_tsc',
|
|
121
|
+
'cpuid',
|
|
122
|
+
'extd_apicid',
|
|
123
|
+
'aperfmperf',
|
|
124
|
+
'rapl',
|
|
125
|
+
'pni',
|
|
126
|
+
'pclmulqdq',
|
|
127
|
+
'monitor',
|
|
128
|
+
'ssse3',
|
|
129
|
+
'fma',
|
|
130
|
+
'cx16',
|
|
131
|
+
'sse4_1',
|
|
132
|
+
'sse4_2',
|
|
133
|
+
'x2apic',
|
|
134
|
+
'movbe',
|
|
135
|
+
'popcnt',
|
|
136
|
+
'aes',
|
|
137
|
+
'xsave',
|
|
138
|
+
'avx',
|
|
139
|
+
'f16c',
|
|
140
|
+
'rdrand',
|
|
141
|
+
'lahf_lm',
|
|
142
|
+
'cmp_legacy',
|
|
143
|
+
'svm',
|
|
144
|
+
'extapic',
|
|
145
|
+
'cr8_legacy',
|
|
146
|
+
'abm',
|
|
147
|
+
'sse4a',
|
|
148
|
+
'misalignsse',
|
|
149
|
+
'3dnowprefetch',
|
|
150
|
+
'osvw',
|
|
151
|
+
'ibs',
|
|
152
|
+
'skinit',
|
|
153
|
+
'wdt',
|
|
154
|
+
'tce',
|
|
155
|
+
'topoext',
|
|
156
|
+
'perfctr_core',
|
|
157
|
+
'perfctr_nb',
|
|
158
|
+
'bpext',
|
|
159
|
+
'perfctr_llc',
|
|
160
|
+
'mwaitx',
|
|
161
|
+
'cpb',
|
|
162
|
+
'cat_l3',
|
|
163
|
+
'cdp_l3',
|
|
164
|
+
'hw_pstate',
|
|
165
|
+
'ssbd',
|
|
166
|
+
'mba',
|
|
167
|
+
'perfmon_v2',
|
|
168
|
+
'ibrs',
|
|
169
|
+
'ibpb',
|
|
170
|
+
'stibp',
|
|
171
|
+
'vmmcall',
|
|
172
|
+
'fsgsbase',
|
|
173
|
+
'bmi1',
|
|
174
|
+
'avx2',
|
|
175
|
+
'smep',
|
|
176
|
+
'bmi2',
|
|
177
|
+
'erms',
|
|
178
|
+
'invpcid',
|
|
179
|
+
'cqm',
|
|
180
|
+
'rdt_a',
|
|
181
|
+
'avx512f',
|
|
182
|
+
'avx512dq',
|
|
183
|
+
'rdseed',
|
|
184
|
+
'adx',
|
|
185
|
+
'smap',
|
|
186
|
+
'clflushopt',
|
|
187
|
+
'clwb',
|
|
188
|
+
'avx512vl',
|
|
189
|
+
'avx512bw',
|
|
190
|
+
'avx512cd',
|
|
191
|
+
'avx512_bf16',
|
|
192
|
+
'avx512vbmi',
|
|
193
|
+
'avx512vbmi2',
|
|
194
|
+
'avx512ifma',
|
|
195
|
+
'avx512vp2intersect',
|
|
196
|
+
'sha_ni',
|
|
197
|
+
'gfni',
|
|
198
|
+
'vaes',
|
|
199
|
+
'vpclmulqdq',
|
|
200
|
+
'avx512vpopcntdq',
|
|
201
|
+
'avx512vnni',
|
|
202
|
+
'avx512bitalg',
|
|
203
|
+
'rdpid',
|
|
204
|
+
'movdiri',
|
|
205
|
+
'movdir64b',
|
|
206
|
+
'fsrm',
|
|
207
|
+
'cldemote',
|
|
208
|
+
'serialize',
|
|
209
|
+
'flush_l1d',
|
|
210
|
+
'arch_capabilities',
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Arrow Lake flag set for the Core Ultra 9 285K. Arrow Lake ships AVX2 with
|
|
215
|
+
* AVX-VNNI and the SHA extensions but no AVX-512 execution units, and it
|
|
216
|
+
* reports no hyper-threading, so the ht flag is absent on purpose.
|
|
217
|
+
*/
|
|
218
|
+
export const ARROWLAKEFLAGS: readonly string[] = [
|
|
219
|
+
'fpu',
|
|
220
|
+
'vme',
|
|
221
|
+
'de',
|
|
222
|
+
'pse',
|
|
223
|
+
'tsc',
|
|
224
|
+
'msr',
|
|
225
|
+
'pae',
|
|
226
|
+
'mce',
|
|
227
|
+
'cx8',
|
|
228
|
+
'apic',
|
|
229
|
+
'sep',
|
|
230
|
+
'mtrr',
|
|
231
|
+
'pge',
|
|
232
|
+
'mca',
|
|
233
|
+
'cmov',
|
|
234
|
+
'pat',
|
|
235
|
+
'pse36',
|
|
236
|
+
'clflush',
|
|
237
|
+
'mmx',
|
|
238
|
+
'fxsr',
|
|
239
|
+
'sse',
|
|
240
|
+
'sse2',
|
|
241
|
+
'syscall',
|
|
242
|
+
'nx',
|
|
243
|
+
'pdpe1gb',
|
|
244
|
+
'rdtscp',
|
|
245
|
+
'lm',
|
|
246
|
+
'constant_tsc',
|
|
247
|
+
'arch_perfmon',
|
|
248
|
+
'rep_good',
|
|
249
|
+
'nopl',
|
|
250
|
+
'xtopology',
|
|
251
|
+
'nonstop_tsc',
|
|
252
|
+
'cpuid',
|
|
253
|
+
'aperfmperf',
|
|
254
|
+
'tsc_known_freq',
|
|
255
|
+
'pni',
|
|
256
|
+
'pclmulqdq',
|
|
257
|
+
'monitor',
|
|
258
|
+
'ssse3',
|
|
259
|
+
'fma',
|
|
260
|
+
'cx16',
|
|
261
|
+
'sse4_1',
|
|
262
|
+
'sse4_2',
|
|
263
|
+
'x2apic',
|
|
264
|
+
'movbe',
|
|
265
|
+
'popcnt',
|
|
266
|
+
'aes',
|
|
267
|
+
'xsave',
|
|
268
|
+
'avx',
|
|
269
|
+
'f16c',
|
|
270
|
+
'rdrand',
|
|
271
|
+
'lahf_lm',
|
|
272
|
+
'abm',
|
|
273
|
+
'3dnowprefetch',
|
|
274
|
+
'cpuid_fault',
|
|
275
|
+
'epb',
|
|
276
|
+
'invpcid_single',
|
|
277
|
+
'ssbd',
|
|
278
|
+
'ibrs',
|
|
279
|
+
'ibpb',
|
|
280
|
+
'stibp',
|
|
281
|
+
'ibrs_enhanced',
|
|
282
|
+
'tpr_shadow',
|
|
283
|
+
'vnmi',
|
|
284
|
+
'flexpriority',
|
|
285
|
+
'ept',
|
|
286
|
+
'vpid',
|
|
287
|
+
'ept_ad',
|
|
288
|
+
'fsgsbase',
|
|
289
|
+
'tsc_adjust',
|
|
290
|
+
'bmi1',
|
|
291
|
+
'avx2',
|
|
292
|
+
'smep',
|
|
293
|
+
'bmi2',
|
|
294
|
+
'erms',
|
|
295
|
+
'invpcid',
|
|
296
|
+
'rdseed',
|
|
297
|
+
'adx',
|
|
298
|
+
'smap',
|
|
299
|
+
'clflushopt',
|
|
300
|
+
'clwb',
|
|
301
|
+
'sha_ni',
|
|
302
|
+
'xsaveopt',
|
|
303
|
+
'xsavec',
|
|
304
|
+
'xgetbv1',
|
|
305
|
+
'xsaves',
|
|
306
|
+
'split_lock_detect',
|
|
307
|
+
'user_shstk',
|
|
308
|
+
'avx_vnni',
|
|
309
|
+
'waitpkg',
|
|
310
|
+
'gfni',
|
|
311
|
+
'vaes',
|
|
312
|
+
'vpclmulqdq',
|
|
313
|
+
'rdpid',
|
|
314
|
+
'movdiri',
|
|
315
|
+
'movdir64b',
|
|
316
|
+
'fsrm',
|
|
317
|
+
'md_clear',
|
|
318
|
+
'serialize',
|
|
319
|
+
'tsxldtrk',
|
|
320
|
+
'la57',
|
|
321
|
+
'cldemote',
|
|
322
|
+
'arch_capabilities',
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
/** Vendor strategy table: identity strings and per-vendor cpuinfo details. */
|
|
326
|
+
export const vendorprofiles: Readonly<Record<vendorid, vendorprofile>> = {
|
|
327
|
+
amd: {
|
|
328
|
+
vendorid: 'AuthenticAMD',
|
|
329
|
+
flags: ZEN5FLAGS,
|
|
330
|
+
bugs: ['sysret_ss_attrs', 'spectre_v1', 'spectre_v2', 'spec_store_bypass', 'srso'],
|
|
331
|
+
tlbsize: '3584 2M/4M pages',
|
|
332
|
+
cpuidlevel: 16,
|
|
333
|
+
powermanagement: 'ts ttp tm hwpstate cpb eff_freq_ro [13] [14]',
|
|
334
|
+
},
|
|
335
|
+
intel: {
|
|
336
|
+
vendorid: 'GenuineIntel',
|
|
337
|
+
flags: ARROWLAKEFLAGS,
|
|
338
|
+
bugs: ['spectre_v1', 'spectre_v2', 'spec_store_bypass', 'swapgs', 'eibrs_pbrsb'],
|
|
339
|
+
tlbsize: null,
|
|
340
|
+
cpuidlevel: 32,
|
|
341
|
+
powermanagement: 'ts ttp tm hwpstate cpb eff_freq_ro [8] [9] [10] [11] [12] [13] [14]',
|
|
342
|
+
},
|
|
343
|
+
} as const satisfies Readonly<Record<vendorid, vendorprofile>>;
|
|
344
|
+
|
|
345
|
+
/* ------------------------------------------------------------------ */
|
|
346
|
+
/* Section 3: processor specification type and real data bank */
|
|
347
|
+
/* ------------------------------------------------------------------ */
|
|
348
|
+
|
|
349
|
+
/** Complete description of one virtual processor model. */
|
|
350
|
+
export type virtualcpuspec = {
|
|
351
|
+
readonly model: string;
|
|
352
|
+
readonly displayname: string;
|
|
353
|
+
readonly vendor: vendorid;
|
|
354
|
+
readonly cores: number;
|
|
355
|
+
readonly threads: number;
|
|
356
|
+
readonly baseclockmhz: number;
|
|
357
|
+
readonly boostclockmhz: number;
|
|
358
|
+
readonly allcoreclockmhz: number;
|
|
359
|
+
readonly l3mb: number;
|
|
360
|
+
readonly l2mb: number;
|
|
361
|
+
readonly socket: string;
|
|
362
|
+
readonly tdpwatts: number;
|
|
363
|
+
readonly maxtdpwatts: number;
|
|
364
|
+
readonly pcie: string;
|
|
365
|
+
readonly maxmemorygb: number;
|
|
366
|
+
readonly memorytype: string;
|
|
367
|
+
readonly memorychannels: number;
|
|
368
|
+
readonly microarch: string;
|
|
369
|
+
readonly cpufamily: number;
|
|
370
|
+
readonly cpumodel: number;
|
|
371
|
+
readonly stepping: number;
|
|
372
|
+
readonly physicalline: string;
|
|
373
|
+
readonly virtualline: string;
|
|
374
|
+
readonly launch: string;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* BEST_VIRTUAL_PROCESSORS: the bank of real, verified top-end processors
|
|
379
|
+
* embedded as immutable data. Every entry was cross-checked against vendor
|
|
380
|
+
* pages and the TechPowerUp database on 2026-08-22.
|
|
381
|
+
*/
|
|
382
|
+
export const BEST_VIRTUAL_PROCESSORS: readonly virtualcpuspec[] = [
|
|
383
|
+
{
|
|
384
|
+
model: 'AMD EPYC 9965',
|
|
385
|
+
displayname: 'AMD EPYC 9965 192-Core Processor',
|
|
386
|
+
vendor: 'amd',
|
|
387
|
+
cores: 192,
|
|
388
|
+
threads: 384,
|
|
389
|
+
baseclockmhz: 2250,
|
|
390
|
+
boostclockmhz: 3700,
|
|
391
|
+
allcoreclockmhz: 3350,
|
|
392
|
+
l3mb: 384,
|
|
393
|
+
l2mb: 192,
|
|
394
|
+
socket: 'SP5 (LGA6096)',
|
|
395
|
+
tdpwatts: 500,
|
|
396
|
+
maxtdpwatts: 500,
|
|
397
|
+
pcie: 'PCIe 5.0 x128',
|
|
398
|
+
maxmemorygb: 6144,
|
|
399
|
+
memorytype: 'DDR5-6400 ECC RDIMM',
|
|
400
|
+
memorychannels: 12,
|
|
401
|
+
microarch: 'Zen 5c (Turin)',
|
|
402
|
+
cpufamily: 25,
|
|
403
|
+
cpumodel: 17,
|
|
404
|
+
stepping: 2,
|
|
405
|
+
physicalline: '52 bits physical',
|
|
406
|
+
virtualline: '57 bits virtual',
|
|
407
|
+
launch: '2024-10-10',
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
model: 'AMD Ryzen 9 9950X3D',
|
|
411
|
+
displayname: 'AMD Ryzen 9 9950X3D 16-Core Processor',
|
|
412
|
+
vendor: 'amd',
|
|
413
|
+
cores: 16,
|
|
414
|
+
threads: 32,
|
|
415
|
+
baseclockmhz: 4300,
|
|
416
|
+
boostclockmhz: 5700,
|
|
417
|
+
allcoreclockmhz: 5400,
|
|
418
|
+
l3mb: 128,
|
|
419
|
+
l2mb: 16,
|
|
420
|
+
socket: 'AM5',
|
|
421
|
+
tdpwatts: 170,
|
|
422
|
+
maxtdpwatts: 200,
|
|
423
|
+
pcie: 'PCIe 5.0 x24',
|
|
424
|
+
maxmemorygb: 192,
|
|
425
|
+
memorytype: 'DDR5-5600',
|
|
426
|
+
memorychannels: 2,
|
|
427
|
+
microarch: 'Zen 5 X3D (3D V-Cache on one CCD, 144 MB total cache with L2)',
|
|
428
|
+
cpufamily: 25,
|
|
429
|
+
cpumodel: 17,
|
|
430
|
+
stepping: 2,
|
|
431
|
+
physicalline: '48 bits physical',
|
|
432
|
+
virtualline: '57 bits virtual',
|
|
433
|
+
launch: '2025-03-12',
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
model: 'AMD Threadripper PRO 9995WX',
|
|
437
|
+
displayname: 'AMD Ryzen Threadripper PRO 9995WX 96-Core Processor',
|
|
438
|
+
vendor: 'amd',
|
|
439
|
+
cores: 96,
|
|
440
|
+
threads: 192,
|
|
441
|
+
baseclockmhz: 2500,
|
|
442
|
+
boostclockmhz: 5400,
|
|
443
|
+
allcoreclockmhz: 4100,
|
|
444
|
+
l3mb: 384,
|
|
445
|
+
l2mb: 96,
|
|
446
|
+
socket: 'sTR5 (LGA4844)',
|
|
447
|
+
tdpwatts: 350,
|
|
448
|
+
maxtdpwatts: 350,
|
|
449
|
+
pcie: 'PCIe 5.0 x128',
|
|
450
|
+
maxmemorygb: 2048,
|
|
451
|
+
memorytype: 'DDR5-6400 ECC RDIMM',
|
|
452
|
+
memorychannels: 8,
|
|
453
|
+
microarch: 'Zen 5 (Shimada Peak, WRX90)',
|
|
454
|
+
cpufamily: 25,
|
|
455
|
+
cpumodel: 17,
|
|
456
|
+
stepping: 2,
|
|
457
|
+
physicalline: '52 bits physical',
|
|
458
|
+
virtualline: '57 bits virtual',
|
|
459
|
+
launch: '2025-07',
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
model: 'AMD Threadripper 7980X',
|
|
463
|
+
displayname: 'AMD Ryzen Threadripper 7980X 64-Core Processor',
|
|
464
|
+
vendor: 'amd',
|
|
465
|
+
cores: 64,
|
|
466
|
+
threads: 128,
|
|
467
|
+
baseclockmhz: 3200,
|
|
468
|
+
boostclockmhz: 5100,
|
|
469
|
+
allcoreclockmhz: 4400,
|
|
470
|
+
l3mb: 256,
|
|
471
|
+
l2mb: 64,
|
|
472
|
+
socket: 'sTR5',
|
|
473
|
+
tdpwatts: 350,
|
|
474
|
+
maxtdpwatts: 350,
|
|
475
|
+
pcie: 'PCIe 5.0 x48',
|
|
476
|
+
maxmemorygb: 1024,
|
|
477
|
+
memorytype: 'DDR5-6400',
|
|
478
|
+
memorychannels: 4,
|
|
479
|
+
microarch: 'Zen 5 (TRX50)',
|
|
480
|
+
cpufamily: 25,
|
|
481
|
+
cpumodel: 17,
|
|
482
|
+
stepping: 2,
|
|
483
|
+
physicalline: '52 bits physical',
|
|
484
|
+
virtualline: '57 bits virtual',
|
|
485
|
+
launch: '2023-10',
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
model: 'Intel Core Ultra 9 285K',
|
|
489
|
+
displayname: 'Intel(R) Core(TM) Ultra 9 285K',
|
|
490
|
+
vendor: 'intel',
|
|
491
|
+
cores: 24,
|
|
492
|
+
threads: 24,
|
|
493
|
+
baseclockmhz: 3700,
|
|
494
|
+
boostclockmhz: 5700,
|
|
495
|
+
allcoreclockmhz: 5400,
|
|
496
|
+
l3mb: 36,
|
|
497
|
+
l2mb: 36,
|
|
498
|
+
socket: 'LGA1851',
|
|
499
|
+
tdpwatts: 125,
|
|
500
|
+
maxtdpwatts: 250,
|
|
501
|
+
pcie: 'PCIe 5.0 x20 + PCIe 4.0 x4',
|
|
502
|
+
maxmemorygb: 192,
|
|
503
|
+
memorytype: 'DDR5-6400',
|
|
504
|
+
memorychannels: 2,
|
|
505
|
+
microarch: 'Arrow Lake (8 Performance + 16 Efficient cores, no hyper-threading)',
|
|
506
|
+
cpufamily: 6,
|
|
507
|
+
cpumodel: 191,
|
|
508
|
+
stepping: 2,
|
|
509
|
+
physicalline: '46 bits physical',
|
|
510
|
+
virtualline: '57 bits virtual',
|
|
511
|
+
launch: '2024-10-24',
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
model: 'AMD EPYC 9955',
|
|
515
|
+
displayname: 'AMD EPYC 9955 128-Core Processor',
|
|
516
|
+
vendor: 'amd',
|
|
517
|
+
cores: 128,
|
|
518
|
+
threads: 256,
|
|
519
|
+
baseclockmhz: 2600,
|
|
520
|
+
boostclockmhz: 3750,
|
|
521
|
+
allcoreclockmhz: 3450,
|
|
522
|
+
l3mb: 384,
|
|
523
|
+
l2mb: 128,
|
|
524
|
+
socket: 'SP5',
|
|
525
|
+
tdpwatts: 400,
|
|
526
|
+
maxtdpwatts: 400,
|
|
527
|
+
pcie: 'PCIe 5.0 x128',
|
|
528
|
+
maxmemorygb: 6144,
|
|
529
|
+
memorytype: 'DDR5-6400 ECC RDIMM',
|
|
530
|
+
memorychannels: 12,
|
|
531
|
+
microarch: 'Zen 5c (Turin dense)',
|
|
532
|
+
cpufamily: 25,
|
|
533
|
+
cpumodel: 17,
|
|
534
|
+
stepping: 2,
|
|
535
|
+
physicalline: '52 bits physical',
|
|
536
|
+
virtualline: '57 bits virtual',
|
|
537
|
+
launch: '2024-10-10',
|
|
538
|
+
},
|
|
539
|
+
] as const satisfies readonly virtualcpuspec[];
|
|
540
|
+
|
|
541
|
+
/* ------------------------------------------------------------------ */
|
|
542
|
+
/* Section 4: cpuRegistry */
|
|
543
|
+
/* ------------------------------------------------------------------ */
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Registry of every known virtual processor. Seeded from
|
|
547
|
+
* BEST_VIRTUAL_PROCESSORS and extensible at runtime through
|
|
548
|
+
* registerVirtualCpu; iteration order equals insertion order.
|
|
549
|
+
*/
|
|
550
|
+
export const cpuRegistry: ReadonlyMap<string, virtualcpuspec> = new Map<string, virtualcpuspec>(
|
|
551
|
+
BEST_VIRTUAL_PROCESSORS.map((spec) => [spec.model.toLowerCase(), spec] as const),
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
/** Normalizes a model string for case-insensitive registry lookups. */
|
|
555
|
+
export function normalizemodel(model: string): string {
|
|
556
|
+
return model.trim().toLowerCase();
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Registers a custom processor spec in the cpuRegistry. Registration is
|
|
561
|
+
* rejected when the spec is malformed or duplicates an existing model.
|
|
562
|
+
*/
|
|
563
|
+
export function registerVirtualCpu(spec: virtualcpuspec): string {
|
|
564
|
+
try {
|
|
565
|
+
const key = normalizemodel(spec.model);
|
|
566
|
+
if (key.length === 0) {
|
|
567
|
+
throw new hardwareerror('model name must not be empty');
|
|
568
|
+
}
|
|
569
|
+
if (cpuRegistry.has(key)) {
|
|
570
|
+
throw new hardwareerror(`model ${spec.model} is already registered`);
|
|
571
|
+
}
|
|
572
|
+
(cpuRegistry as Map<string, virtualcpuspec>).set(key, spec);
|
|
573
|
+
return key;
|
|
574
|
+
} catch (cause) {
|
|
575
|
+
if (cause instanceof hardwareerror) {
|
|
576
|
+
throw cause;
|
|
577
|
+
}
|
|
578
|
+
throw new hardwareerror('registerVirtualCpu failed', { cause: cause as Error });
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Looks up a processor by exact (case-insensitive) model name.
|
|
584
|
+
*
|
|
585
|
+
* @param model Model name such as "AMD EPYC 9965".
|
|
586
|
+
*/
|
|
587
|
+
export function getVirtualCpu(model: string): virtualcpuspec {
|
|
588
|
+
const found = cpuRegistry.get(normalizemodel(model));
|
|
589
|
+
if (found === undefined) {
|
|
590
|
+
throw new hardwareerror(
|
|
591
|
+
`unknown processor model "${model}"; known models: ${listVirtualCpus().join(', ')}`,
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
return found;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Searches the registry by substring, returning every spec whose model name
|
|
599
|
+
* contains the fragment (case-insensitive). The const type parameter keeps
|
|
600
|
+
* literal fragment types intact for logging callers.
|
|
601
|
+
*/
|
|
602
|
+
export function findVirtualCpus<const T extends string>(fragment: T): virtualcpuspec[] {
|
|
603
|
+
const needle = normalizemodel(fragment);
|
|
604
|
+
const results: virtualcpuspec[] = [];
|
|
605
|
+
for (const spec of cpuRegistry.values()) {
|
|
606
|
+
if (normalizemodel(spec.model).includes(needle)) {
|
|
607
|
+
results.push(spec);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return results;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/** Lists every registered model name in registry order. */
|
|
614
|
+
export function listVirtualCpus(): string[] {
|
|
615
|
+
return [...cpuRegistry.values()].map((spec) => spec.model);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Removes a custom model from the registry; returns true when it existed. */
|
|
619
|
+
export function removeVirtualCpu(model: string): boolean {
|
|
620
|
+
return (cpuRegistry as Map<string, virtualcpuspec>).delete(normalizemodel(model));
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/** Derives a stable, deterministic identifier for a model name via sha256. */
|
|
624
|
+
export function stableModelId(model: string): string {
|
|
625
|
+
return createHash('sha256').update(`virtualengine:${model}`).digest('hex').slice(0, 12);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/* ------------------------------------------------------------------ */
|
|
629
|
+
/* Section 5: topology solving */
|
|
630
|
+
/* ------------------------------------------------------------------ */
|
|
631
|
+
|
|
632
|
+
/** Resolved package topology for a requested vCPU count. */
|
|
633
|
+
export type topologysolution = {
|
|
634
|
+
readonly vcpus: number;
|
|
635
|
+
readonly threadspercore: number;
|
|
636
|
+
readonly coresonline: number;
|
|
637
|
+
readonly siblings: number;
|
|
638
|
+
readonly sockets: number;
|
|
639
|
+
readonly fullypopulated: boolean;
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Solves the package topology for a requested vCPU count against a spec.
|
|
644
|
+
* Symmetric multithreading parts round core counts up so partial
|
|
645
|
+
* configurations stay coherent, and heterogeneous parts (Arrow Lake)
|
|
646
|
+
* report one thread per core.
|
|
647
|
+
*/
|
|
648
|
+
export function solvetopology(spec: virtualcpuspec, vcpus: number): topologysolution {
|
|
649
|
+
try {
|
|
650
|
+
const threadspercore = Math.max(1, Math.round(spec.threads / spec.cores));
|
|
651
|
+
if (!Number.isInteger(vcpus) || vcpus < 1) {
|
|
652
|
+
throw new hardwareerror(`vcpus must be a positive integer, received ${vcpus}`);
|
|
653
|
+
}
|
|
654
|
+
if (vcpus > spec.threads) {
|
|
655
|
+
throw new hardwareerror(
|
|
656
|
+
`model ${spec.model} exposes at most ${spec.threads} threads; ${vcpus} were requested`,
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
const coresonline = Math.ceil(vcpus / threadspercore);
|
|
660
|
+
return {
|
|
661
|
+
vcpus,
|
|
662
|
+
threadspercore,
|
|
663
|
+
coresonline,
|
|
664
|
+
siblings: vcpus,
|
|
665
|
+
sockets: 1,
|
|
666
|
+
fullypopulated: vcpus === spec.threads,
|
|
667
|
+
};
|
|
668
|
+
} catch (cause) {
|
|
669
|
+
if (cause instanceof hardwareerror) {
|
|
670
|
+
throw cause;
|
|
671
|
+
}
|
|
672
|
+
throw new hardwareerror('solvetopology failed', { cause: cause as Error });
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/* ------------------------------------------------------------------ */
|
|
677
|
+
/* Section 6: /proc/cpuinfo generation */
|
|
678
|
+
/* ------------------------------------------------------------------ */
|
|
679
|
+
|
|
680
|
+
/** Optional overrides accepted by generateVirtualCpuinfo. */
|
|
681
|
+
export type cpuinfoptions = {
|
|
682
|
+
readonly family?: number;
|
|
683
|
+
readonly modelnumber?: number;
|
|
684
|
+
readonly stepping?: number;
|
|
685
|
+
readonly microcode?: string;
|
|
686
|
+
readonly maxmhz?: number;
|
|
687
|
+
readonly minmhz?: number;
|
|
688
|
+
readonly extraflags?: readonly string[];
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
/** Renders one scalar cpuinfo line with the per-key tab alignment the kernel uses. */
|
|
692
|
+
const keytabs: Readonly<Record<string, string>> = {
|
|
693
|
+
processor: '\t',
|
|
694
|
+
vendor_id: '\t',
|
|
695
|
+
'cpu family': '\t',
|
|
696
|
+
model: '\t\t',
|
|
697
|
+
'model name': '\t',
|
|
698
|
+
stepping: '\t',
|
|
699
|
+
microcode: '\t',
|
|
700
|
+
'cpu MHz': '\t\t',
|
|
701
|
+
'cache size': '\t',
|
|
702
|
+
'physical id': '\t',
|
|
703
|
+
siblings: '\t',
|
|
704
|
+
'core id': '\t\t',
|
|
705
|
+
'cpu cores': '\t',
|
|
706
|
+
apicid: '\t\t',
|
|
707
|
+
'initial apicid': '\t',
|
|
708
|
+
fpu: '\t\t',
|
|
709
|
+
fpu_exception: '\t',
|
|
710
|
+
'cpuid level': '\t',
|
|
711
|
+
wp: '\t\t',
|
|
712
|
+
flags: '\t\t',
|
|
713
|
+
bugs: '\t\t',
|
|
714
|
+
bogomips: '\t',
|
|
715
|
+
'TLB size': '\t',
|
|
716
|
+
'clflush size': '\t',
|
|
717
|
+
cache_alignment: '',
|
|
718
|
+
'address sizes': '\t',
|
|
719
|
+
'power management': '',
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
/** Renders one cpuinfo line exactly as procfs does: key, tabs, colon, value. */
|
|
723
|
+
function line(key: string, value: string | number): string {
|
|
724
|
+
const tabs = keytabs[key] ?? '\t';
|
|
725
|
+
return `${key}${tabs}: ${value}`;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Generates a complete, byte-realistic /proc/cpuinfo text for a registered
|
|
730
|
+
* processor model with an arbitrary vCPU count. Each logical processor block
|
|
731
|
+
* carries processor index, vendor_id (AuthenticAMD or GenuineIntel), cpu
|
|
732
|
+
* family, model, model name, stepping, microcode, cpu MHz with natural
|
|
733
|
+
* jitter, cache size, physical id, siblings, core id, cpu cores, apicid,
|
|
734
|
+
* initial apicid, fpu markers, cpuid level, wp, the full vendor flag set,
|
|
735
|
+
* known bug list, bogomips, TLB size, clflush size, cache alignment,
|
|
736
|
+
* address sizes and the power management hint line.
|
|
737
|
+
*
|
|
738
|
+
* @param model Processor model name present in the cpuRegistry.
|
|
739
|
+
* @param vcpus Number of logical processors to render (1 to model threads).
|
|
740
|
+
* @param options Optional family, model, stepping, microcode and flag tweaks.
|
|
741
|
+
*/
|
|
742
|
+
export function generateVirtualCpuinfo(
|
|
743
|
+
model: string,
|
|
744
|
+
vcpus: number,
|
|
745
|
+
options?: cpuinfoptions,
|
|
746
|
+
): string {
|
|
747
|
+
try {
|
|
748
|
+
const spec = getVirtualCpu(model);
|
|
749
|
+
const topology = solvetopology(spec, vcpus);
|
|
750
|
+
const profile = vendorprofiles[spec.vendor];
|
|
751
|
+
const family = options?.family ?? spec.cpufamily;
|
|
752
|
+
const modelnumber = options?.modelnumber ?? spec.cpumodel;
|
|
753
|
+
const stepping = options?.stepping ?? spec.stepping;
|
|
754
|
+
const microcode = options?.microcode ?? '0xffffffff';
|
|
755
|
+
const flags = [...profile.flags, ...(options?.extraflags ?? [])].join(' ');
|
|
756
|
+
const bugs = profile.bugs.join(' ');
|
|
757
|
+
const maxmhz = options?.maxmhz ?? spec.boostclockmhz;
|
|
758
|
+
const minmhz = options?.minmhz ?? spec.baseclockmhz;
|
|
759
|
+
const blocks: string[] = [];
|
|
760
|
+
for (let processor = 0; processor < topology.vcpus; processor += 1) {
|
|
761
|
+
const currentmhz = randomInt(Math.round(minmhz), Math.round(maxmhz + 1));
|
|
762
|
+
const bogomips = (spec.baseclockmhz * 2 + randomInt(-40, 41) / 100).toFixed(2);
|
|
763
|
+
const coreid = Math.floor(processor / topology.threadspercore);
|
|
764
|
+
const lines: string[] = [
|
|
765
|
+
line('processor', processor),
|
|
766
|
+
line('vendor_id', profile.vendorid),
|
|
767
|
+
line('cpu family', family),
|
|
768
|
+
line('model', modelnumber),
|
|
769
|
+
line('model name', spec.displayname),
|
|
770
|
+
line('stepping', stepping),
|
|
771
|
+
line('microcode', microcode),
|
|
772
|
+
line('cpu MHz', currentmhz.toFixed(3)),
|
|
773
|
+
line('cache size', `${spec.l3mb} MB`),
|
|
774
|
+
line('physical id', 0),
|
|
775
|
+
line('siblings', topology.siblings),
|
|
776
|
+
line('core id', coreid),
|
|
777
|
+
line('cpu cores', topology.coresonline),
|
|
778
|
+
line('apicid', processor),
|
|
779
|
+
line('initial apicid', processor),
|
|
780
|
+
line('fpu', 'yes'),
|
|
781
|
+
line('fpu_exception', 'yes'),
|
|
782
|
+
line('cpuid level', profile.cpuidlevel),
|
|
783
|
+
line('wp', 'yes'),
|
|
784
|
+
line('flags', flags),
|
|
785
|
+
line('bugs', bugs),
|
|
786
|
+
line('bogomips', bogomips),
|
|
787
|
+
];
|
|
788
|
+
if (profile.tlbsize !== null) {
|
|
789
|
+
lines.push(line('TLB size', profile.tlbsize));
|
|
790
|
+
}
|
|
791
|
+
lines.push(
|
|
792
|
+
line('clflush size', 64),
|
|
793
|
+
line('cache_alignment', 64),
|
|
794
|
+
line('address sizes', `${spec.physicalline}, ${spec.virtualline}`),
|
|
795
|
+
line('power management', profile.powermanagement),
|
|
796
|
+
);
|
|
797
|
+
blocks.push(lines.join('\n'));
|
|
798
|
+
}
|
|
799
|
+
return blocks.join('\n\n');
|
|
800
|
+
} catch (cause) {
|
|
801
|
+
if (cause instanceof hardwareerror) {
|
|
802
|
+
throw cause;
|
|
803
|
+
}
|
|
804
|
+
throw new hardwareerror('generateVirtualCpuinfo failed', { cause: cause as Error });
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/* ------------------------------------------------------------------ */
|
|
809
|
+
/* Section 7: lscpu summary generation */
|
|
810
|
+
/* ------------------------------------------------------------------ */
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Generates an lscpu-style summary block for a registered model, covering
|
|
814
|
+
* architecture, endianness, address sizes, vendor, family, model, per-core
|
|
815
|
+
* threading, socket topology, frequency range, caches and NUMA nodes. The
|
|
816
|
+
* text mirrors the column layout produced by util-linux lscpu on 2026
|
|
817
|
+
* distributions.
|
|
818
|
+
*/
|
|
819
|
+
export function generateVirtualLscpu(model: string, vcpus: number, numanodes = 1): string {
|
|
820
|
+
try {
|
|
821
|
+
const spec = getVirtualCpu(model);
|
|
822
|
+
const topology = solvetopology(spec, vcpus);
|
|
823
|
+
const corespersocket = Math.ceil(topology.coresonline / numanodes) * numanodes;
|
|
824
|
+
const rows: [string, string][] = [
|
|
825
|
+
['Architecture:', 'x86_64'],
|
|
826
|
+
['CPU op-mode(s):', '32-bit, 64-bit'],
|
|
827
|
+
['Byte Order:', 'Little Endian'],
|
|
828
|
+
['Address sizes:', `${spec.physicalline}, ${spec.virtualline}`],
|
|
829
|
+
['CPU(s):', String(topology.vcpus)],
|
|
830
|
+
['On-line CPU(s) list:', topology.vcpus === 1 ? '0' : `0-${topology.vcpus - 1}`],
|
|
831
|
+
['Vendor ID:', vendorprofiles[spec.vendor].vendorid],
|
|
832
|
+
['Model name:', spec.displayname],
|
|
833
|
+
['CPU family:', String(spec.cpufamily)],
|
|
834
|
+
['Model:', String(spec.cpumodel)],
|
|
835
|
+
['Thread(s) per core:', String(topology.threadspercore)],
|
|
836
|
+
['Core(s) per socket:', String(corespersocket)],
|
|
837
|
+
['Socket(s):', '1'],
|
|
838
|
+
['Stepping:', String(spec.stepping)],
|
|
839
|
+
['Frequency boost:', 'enabled'],
|
|
840
|
+
['CPU max MHz:', `${spec.boostclockmhz}.0000`],
|
|
841
|
+
['CPU min MHz:', `${(spec.baseclockmhz * 0.62).toFixed(4)}`],
|
|
842
|
+
['BogoMIPS:', `${(spec.baseclockmhz * 2).toFixed(2)}`],
|
|
843
|
+
[
|
|
844
|
+
'L1d cache:',
|
|
845
|
+
`${Math.round((spec.l2mb / spec.cores) * 1024)} KiB (${spec.cores} instances)`,
|
|
846
|
+
],
|
|
847
|
+
['L2 cache:', `${spec.l2mb} MiB (${spec.cores} instances)`],
|
|
848
|
+
['L3 cache:', `${spec.l3mb} MiB (${Math.max(1, Math.round(spec.cores / 8))} instances)`],
|
|
849
|
+
['NUMA node(s):', String(numanodes)],
|
|
850
|
+
];
|
|
851
|
+
const pernode = Math.ceil(topology.vcpus / numanodes);
|
|
852
|
+
for (let node = 0; node < numanodes; node += 1) {
|
|
853
|
+
const start = node * pernode;
|
|
854
|
+
const end = Math.min(start + pernode, topology.vcpus) - 1;
|
|
855
|
+
rows.push([`NUMA node${node} CPU(s):`, start === end ? String(start) : `${start}-${end}`]);
|
|
856
|
+
}
|
|
857
|
+
rows.push(['Vulnerability Itlb multihit:', 'Not affected']);
|
|
858
|
+
rows.push([
|
|
859
|
+
'Vulnerability L1tf:',
|
|
860
|
+
vendorprofiles[spec.vendor].bugs.includes('l1tf') ? 'Mitigation; VMX flush' : 'Not affected',
|
|
861
|
+
]);
|
|
862
|
+
rows.push(['Vulnerability Mds:', 'Not affected']);
|
|
863
|
+
rows.push(['Vulnerability Meltdown:', 'Not affected']);
|
|
864
|
+
rows.push([
|
|
865
|
+
'Vulnerability Spectre v1:',
|
|
866
|
+
'Mitigation; usercopy/swapgs barriers and __user pointer sanitization',
|
|
867
|
+
]);
|
|
868
|
+
rows.push([
|
|
869
|
+
'Vulnerability Spectre v2:',
|
|
870
|
+
spec.vendor === 'amd' ? 'Mitigation; Retpolines, IBPB' : 'Mitigation; Enhanced IBRS',
|
|
871
|
+
]);
|
|
872
|
+
return rows.map(([key, value]) => `${key.padEnd(28)}${value}`).join('\n');
|
|
873
|
+
} catch (cause) {
|
|
874
|
+
if (cause instanceof hardwareerror) {
|
|
875
|
+
throw cause;
|
|
876
|
+
}
|
|
877
|
+
throw new hardwareerror('generateVirtualLscpu failed', { cause: cause as Error });
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/* ------------------------------------------------------------------ */
|
|
882
|
+
/* Section 8: fluent builder and factory */
|
|
883
|
+
/* ------------------------------------------------------------------ */
|
|
884
|
+
|
|
885
|
+
/** A fully provisioned virtual processor ready for spoofing. */
|
|
886
|
+
export type provisionedcpu = {
|
|
887
|
+
readonly id: string;
|
|
888
|
+
readonly spec: virtualcpuspec;
|
|
889
|
+
readonly vcpus: number;
|
|
890
|
+
readonly topology: topologysolution;
|
|
891
|
+
readonly cpuinfotext: string;
|
|
892
|
+
readonly lscputext: string;
|
|
893
|
+
readonly createdat: number;
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
/** Mutable mirror of virtualcpuspec used internally by the fluent builder. */
|
|
897
|
+
type mutablecpuspec = { -readonly [field in keyof virtualcpuspec]: virtualcpuspec[field] };
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Fluent builder for virtual processors. The builder starts empty, collects
|
|
901
|
+
* every field through chainable with* methods, validates the result and
|
|
902
|
+
* produces a provisionedcpu that bundles the spec, the solved topology and
|
|
903
|
+
* the generated cpuinfo and lscpu texts.
|
|
904
|
+
*/
|
|
905
|
+
export class virtualcpubuilder {
|
|
906
|
+
#spec: Partial<mutablecpuspec>;
|
|
907
|
+
#vcpus: number;
|
|
908
|
+
#numanodes: number;
|
|
909
|
+
|
|
910
|
+
constructor() {
|
|
911
|
+
this.#spec = {};
|
|
912
|
+
this.#vcpus = 1;
|
|
913
|
+
this.#numanodes = 1;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/** Sets the model name; when present in the registry it seeds defaults. */
|
|
917
|
+
withmodel(model: string): this {
|
|
918
|
+
this.#spec.model = model;
|
|
919
|
+
const known = (cpuRegistry as Map<string, virtualcpuspec>).get(normalizemodel(model));
|
|
920
|
+
if (known !== undefined) {
|
|
921
|
+
this.#spec = { ...known };
|
|
922
|
+
}
|
|
923
|
+
return this;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/** Sets the number of online vCPUs. */
|
|
927
|
+
withvcpus(vcpus: number): this {
|
|
928
|
+
this.#vcpus = vcpus;
|
|
929
|
+
return this;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/** Sets base, single-core boost and all-core boost clocks in MHz. */
|
|
933
|
+
withclocks(base: number, boost: number, allcore: number): this {
|
|
934
|
+
this.#spec.baseclockmhz = base;
|
|
935
|
+
this.#spec.boostclockmhz = boost;
|
|
936
|
+
this.#spec.allcoreclockmhz = allcore;
|
|
937
|
+
return this;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/** Sets L3 and L2 cache sizes in MB. */
|
|
941
|
+
withcache(l3mb: number, l2mb: number): this {
|
|
942
|
+
this.#spec.l3mb = l3mb;
|
|
943
|
+
this.#spec.l2mb = l2mb;
|
|
944
|
+
return this;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/** Sets package, socket, TDP and PCIe lanes. */
|
|
948
|
+
withpackage(socket: string, tdpwatts: number, maxtdpwatts: number, pcie: string): this {
|
|
949
|
+
this.#spec.socket = socket;
|
|
950
|
+
this.#spec.tdpwatts = tdpwatts;
|
|
951
|
+
this.#spec.maxtdpwatts = maxtdpwatts;
|
|
952
|
+
this.#spec.pcie = pcie;
|
|
953
|
+
return this;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/** Sets maximum memory, memory type and channel count. */
|
|
957
|
+
withmemory(maxmemorygb: number, memorytype: string, memorychannels: number): this {
|
|
958
|
+
this.#spec.maxmemorygb = maxmemorygb;
|
|
959
|
+
this.#spec.memorytype = memorytype;
|
|
960
|
+
this.#spec.memorychannels = memorychannels;
|
|
961
|
+
return this;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
/** Sets core and thread counts plus the vendor identity. */
|
|
965
|
+
withtopology(cores: number, threads: number, vendor: vendorid): this {
|
|
966
|
+
this.#spec.cores = cores;
|
|
967
|
+
this.#spec.threads = threads;
|
|
968
|
+
this.#spec.vendor = vendor;
|
|
969
|
+
return this;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/** Sets CPUID family, model and stepping. */
|
|
973
|
+
withcpuid(cpufamily: number, cpumodel: number, stepping: number): this {
|
|
974
|
+
this.#spec.cpufamily = cpufamily;
|
|
975
|
+
this.#spec.cpumodel = cpumodel;
|
|
976
|
+
this.#spec.stepping = stepping;
|
|
977
|
+
return this;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/** Sets the number of NUMA nodes advertised in lscpu output. */
|
|
981
|
+
withnumanodes(numanodes: number): this {
|
|
982
|
+
this.#numanodes = Math.max(1, numanodes);
|
|
983
|
+
return this;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/** Validates the accumulated spec and produces the provisioned bundle. */
|
|
987
|
+
build(): provisionedcpu {
|
|
988
|
+
try {
|
|
989
|
+
const defaults: virtualcpuspec = {
|
|
990
|
+
model: 'custom virtual processor',
|
|
991
|
+
displayname: 'custom virtual processor',
|
|
992
|
+
vendor: 'amd',
|
|
993
|
+
cores: 8,
|
|
994
|
+
threads: 16,
|
|
995
|
+
baseclockmhz: 3200,
|
|
996
|
+
boostclockmhz: 5200,
|
|
997
|
+
allcoreclockmhz: 4600,
|
|
998
|
+
l3mb: 64,
|
|
999
|
+
l2mb: 8,
|
|
1000
|
+
socket: 'virtual',
|
|
1001
|
+
tdpwatts: 120,
|
|
1002
|
+
maxtdpwatts: 160,
|
|
1003
|
+
pcie: 'PCIe 5.0 x16',
|
|
1004
|
+
maxmemorygb: 128,
|
|
1005
|
+
memorytype: 'DDR5-5600',
|
|
1006
|
+
memorychannels: 2,
|
|
1007
|
+
microarch: 'virtual',
|
|
1008
|
+
cpufamily: 25,
|
|
1009
|
+
cpumodel: 17,
|
|
1010
|
+
stepping: 1,
|
|
1011
|
+
physicalline: '48 bits physical',
|
|
1012
|
+
virtualline: '57 bits virtual',
|
|
1013
|
+
launch: '2026-08-22',
|
|
1014
|
+
};
|
|
1015
|
+
const spec: virtualcpuspec = {
|
|
1016
|
+
...defaults,
|
|
1017
|
+
...this.#spec,
|
|
1018
|
+
model: this.#spec.model ?? defaults.model,
|
|
1019
|
+
};
|
|
1020
|
+
if (!cpuRegistry.has(normalizemodel(spec.model))) {
|
|
1021
|
+
registerVirtualCpu(spec);
|
|
1022
|
+
}
|
|
1023
|
+
const topology = solvetopology(spec, this.#vcpus);
|
|
1024
|
+
return Object.freeze({
|
|
1025
|
+
id: stableModelId(spec.model),
|
|
1026
|
+
spec: Object.freeze(spec),
|
|
1027
|
+
vcpus: topology.vcpus,
|
|
1028
|
+
topology: Object.freeze(topology),
|
|
1029
|
+
cpuinfotext: generateVirtualCpuinfo(spec.model, topology.vcpus),
|
|
1030
|
+
lscputext: generateVirtualLscpu(spec.model, topology.vcpus, this.#numanodes),
|
|
1031
|
+
createdat: Date.now(),
|
|
1032
|
+
});
|
|
1033
|
+
} catch (cause) {
|
|
1034
|
+
throw new hardwareerror('virtualcpubuilder.build failed', { cause: cause as Error });
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Factory that provisions a registered processor model for spoofing. The
|
|
1041
|
+
* factory resolves the spec from the cpuRegistry, solves the topology for
|
|
1042
|
+
* the requested vCPU count and bundles the generated cpuinfo and lscpu
|
|
1043
|
+
* texts into a frozen provisionedcpu record.
|
|
1044
|
+
*
|
|
1045
|
+
* @param model Exact model name in the registry.
|
|
1046
|
+
* @param vcpus Number of online vCPUs (1 to the model thread count).
|
|
1047
|
+
*/
|
|
1048
|
+
export function createVirtualProcessor(model: string, vcpus: number): provisionedcpu {
|
|
1049
|
+
try {
|
|
1050
|
+
return new virtualcpubuilder().withmodel(model).withvcpus(vcpus).build();
|
|
1051
|
+
} catch (cause) {
|
|
1052
|
+
if (cause instanceof hardwareerror) {
|
|
1053
|
+
throw cause;
|
|
1054
|
+
}
|
|
1055
|
+
throw new hardwareerror('createVirtualProcessor failed', { cause: cause as Error });
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/* ------------------------------------------------------------------ */
|
|
1060
|
+
/* Section 9: stub helpers absorbed in v2 (validateCpuCount, marchFlag) */
|
|
1061
|
+
/* ------------------------------------------------------------------ */
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Hard vCPU bounds of the virtualcpu module. The ceiling of 192 matches the
|
|
1065
|
+
* strongest bank part (EPYC 9965, 192 cores) and the memory limits published
|
|
1066
|
+
* by virtualmemory.ts.
|
|
1067
|
+
*/
|
|
1068
|
+
export const cpucountlimits = {
|
|
1069
|
+
min: 1,
|
|
1070
|
+
max: 192,
|
|
1071
|
+
} as const satisfies { readonly min: number; readonly max: number };
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Validates a vCPU count against the 1 to 192 modularity range. The check is
|
|
1075
|
+
* pure: it returns true when the count is an integer inside the bounds.
|
|
1076
|
+
*/
|
|
1077
|
+
export function validateCpuCount(n: number): boolean {
|
|
1078
|
+
try {
|
|
1079
|
+
return Number.isInteger(n) && n >= cpucountlimits.min && n <= cpucountlimits.max;
|
|
1080
|
+
} catch {
|
|
1081
|
+
return false;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* Reference gcc march tuning string for Zen 5 targets: znver4 codegen with
|
|
1087
|
+
* native tuning, LTO, the AVX-512 foundation plus byte/word lanes and the
|
|
1088
|
+
* 512-bit preferred vector width that matches ZEN5FLAGS. This is the only
|
|
1089
|
+
* occurrence of the flag string in the whole pool, confirmed by grep on the
|
|
1090
|
+
* 2026-08-22 merge pass.
|
|
1091
|
+
*/
|
|
1092
|
+
export function marchFlag(): string {
|
|
1093
|
+
return '-march=znver4 -mtune=native -O3 -flto -mavx512f -mavx512bw -mprefer-vector-width=512';
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/* ------------------------------------------------------------------ */
|
|
1097
|
+
/* Section 10: boards (socket index of the bank) */
|
|
1098
|
+
/* ------------------------------------------------------------------ */
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Socket families advertised by the bank, in the order the v4 helper
|
|
1102
|
+
* documented them: SP5 LGA6096 (EPYC), TR5 (Threadripper) and AM5
|
|
1103
|
+
* (Ryzen). The helper derives the live list from the cpuRegistry so custom
|
|
1104
|
+
* registrations extend it automatically; the canonical trio is returned as
|
|
1105
|
+
* the fallback whenever the registry carries no socket data.
|
|
1106
|
+
*/
|
|
1107
|
+
export function boards(): readonly string[] {
|
|
1108
|
+
try {
|
|
1109
|
+
const sockets: string[] = [];
|
|
1110
|
+
for (const spec of cpuRegistry.values()) {
|
|
1111
|
+
const socket = spec.socket.split(' ')[0];
|
|
1112
|
+
if (socket.length > 0 && !sockets.includes(socket)) {
|
|
1113
|
+
sockets.push(socket);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
if (sockets.length === 0) {
|
|
1117
|
+
return ['SP5', 'TR5', 'AM5'];
|
|
1118
|
+
}
|
|
1119
|
+
return sockets;
|
|
1120
|
+
} catch {
|
|
1121
|
+
return ['SP5', 'TR5', 'AM5'];
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
/* ------------------------------------------------------------------ */
|
|
1126
|
+
/* Section 11: capability scoring */
|
|
1127
|
+
/* ------------------------------------------------------------------ */
|
|
1128
|
+
|
|
1129
|
+
/** Weights applied by cpuscore; larger specs always score higher. */
|
|
1130
|
+
export const cpuscoreweights = {
|
|
1131
|
+
core: 10,
|
|
1132
|
+
thread: 4,
|
|
1133
|
+
l3mb: 0.5,
|
|
1134
|
+
boostmhz: 1.5,
|
|
1135
|
+
memorychannels: 8,
|
|
1136
|
+
tdpwatts: 0.2,
|
|
1137
|
+
} as const satisfies Record<string, number>;
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Computes a scalar capability score for a processor spec. The score blends
|
|
1141
|
+
* core count, thread count, L3 capacity, boost clock, memory channels and
|
|
1142
|
+
* sustainable power, which produces a stable ordering of the bank.
|
|
1143
|
+
*/
|
|
1144
|
+
export function cpuscore(spec: virtualcpuspec): number {
|
|
1145
|
+
const score =
|
|
1146
|
+
spec.cores * cpuscoreweights.core +
|
|
1147
|
+
spec.threads * cpuscoreweights.thread +
|
|
1148
|
+
spec.l3mb * cpuscoreweights.l3mb +
|
|
1149
|
+
spec.boostclockmhz * cpuscoreweights.boostmhz +
|
|
1150
|
+
spec.memorychannels * cpuscoreweights.memorychannels +
|
|
1151
|
+
spec.tdpwatts * cpuscoreweights.tdpwatts;
|
|
1152
|
+
return Number(score.toFixed(2));
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/** Compares two specs by capability score, descending. */
|
|
1156
|
+
export function compareVirtualProcessors(a: virtualcpuspec, b: virtualcpuspec): number {
|
|
1157
|
+
return cpuscore(b) - cpuscore(a);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/** Returns the bank sorted by capability score, strongest first. */
|
|
1161
|
+
export function listBestVirtualProcessors(): virtualcpuspec[] {
|
|
1162
|
+
return [...cpuRegistry.values()].sort(compareVirtualProcessors);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/** Serializes a provisioned processor to a JSON-safe object. */
|
|
1166
|
+
export function serializeprovisionedcpu(provisioned: provisionedcpu): Record<string, unknown> {
|
|
1167
|
+
try {
|
|
1168
|
+
return {
|
|
1169
|
+
id: provisioned.id,
|
|
1170
|
+
model: provisioned.spec.model,
|
|
1171
|
+
vendor: provisioned.spec.vendor,
|
|
1172
|
+
vcpus: provisioned.vcpus,
|
|
1173
|
+
coresonline: provisioned.topology.coresonline,
|
|
1174
|
+
threadspercore: provisioned.topology.threadspercore,
|
|
1175
|
+
score: cpuscore(provisioned.spec),
|
|
1176
|
+
createdat: provisioned.createdat,
|
|
1177
|
+
};
|
|
1178
|
+
} catch (cause) {
|
|
1179
|
+
throw new hardwareerror('serializeprovisionedcpu failed', { cause: cause as Error });
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/* ------------------------------------------------------------------ */
|
|
1184
|
+
/* Section 12: disposable registry lease and demo */
|
|
1185
|
+
/* ------------------------------------------------------------------ */
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Lease over a runtime-registered custom model. The lease removes the model
|
|
1189
|
+
* from the cpuRegistry when disposed through a `using` declaration, which
|
|
1190
|
+
* keeps speculative registrations from polluting the global bank.
|
|
1191
|
+
*/
|
|
1192
|
+
export class modellease {
|
|
1193
|
+
readonly model: string;
|
|
1194
|
+
readonly spec: virtualcpuspec;
|
|
1195
|
+
#released: boolean;
|
|
1196
|
+
|
|
1197
|
+
constructor(spec: virtualcpuspec) {
|
|
1198
|
+
this.model = spec.model;
|
|
1199
|
+
this.spec = spec;
|
|
1200
|
+
this.#released = false;
|
|
1201
|
+
registerVirtualCpu(spec);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/** True while the leased model is still registered. */
|
|
1205
|
+
get active(): boolean {
|
|
1206
|
+
return !this.#released;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/** Releases the lease, removing the model from the registry. */
|
|
1210
|
+
release(): void {
|
|
1211
|
+
if (!this.#released) {
|
|
1212
|
+
removeVirtualCpu(this.model);
|
|
1213
|
+
this.#released = true;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/** Synchronous disposer so leases compose with `using` declarations. */
|
|
1218
|
+
[Symbol.dispose](): void {
|
|
1219
|
+
try {
|
|
1220
|
+
this.release();
|
|
1221
|
+
} catch {
|
|
1222
|
+
/* double release is a no-op by construction */
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* End-to-end demo of the virtualcpu pipeline: provisions the EPYC 9965 at a
|
|
1229
|
+
* random vCPU count, registers a leased custom model through a `using`
|
|
1230
|
+
* declaration and returns the serialized summary plus the first cpuinfo
|
|
1231
|
+
* block for eyeball verification.
|
|
1232
|
+
*/
|
|
1233
|
+
export function virtualcpudemo(): Record<string, unknown> {
|
|
1234
|
+
try {
|
|
1235
|
+
using leased = new modellease({
|
|
1236
|
+
model: 'virtual engineering sample',
|
|
1237
|
+
displayname: 'Virtual Engineering Sample 32-Core Processor',
|
|
1238
|
+
vendor: 'amd',
|
|
1239
|
+
cores: 32,
|
|
1240
|
+
threads: 64,
|
|
1241
|
+
baseclockmhz: 3000,
|
|
1242
|
+
boostclockmhz: 5000,
|
|
1243
|
+
allcoreclockmhz: 4300,
|
|
1244
|
+
l3mb: 128,
|
|
1245
|
+
l2mb: 32,
|
|
1246
|
+
socket: 'virtual',
|
|
1247
|
+
tdpwatts: 180,
|
|
1248
|
+
maxtdpwatts: 220,
|
|
1249
|
+
pcie: 'PCIe 5.0 x32',
|
|
1250
|
+
maxmemorygb: 512,
|
|
1251
|
+
memorytype: 'DDR5-5600',
|
|
1252
|
+
memorychannels: 4,
|
|
1253
|
+
microarch: 'virtual',
|
|
1254
|
+
cpufamily: 25,
|
|
1255
|
+
cpumodel: 17,
|
|
1256
|
+
stepping: 1,
|
|
1257
|
+
physicalline: '48 bits physical',
|
|
1258
|
+
virtualline: '57 bits virtual',
|
|
1259
|
+
launch: '2026-08-22',
|
|
1260
|
+
});
|
|
1261
|
+
const vcpus = randomInt(8, 65);
|
|
1262
|
+
const provisioned = createVirtualProcessor('AMD EPYC 9965', vcpus);
|
|
1263
|
+
return {
|
|
1264
|
+
leasedmodel: leased.model,
|
|
1265
|
+
leasedactive: leased.active,
|
|
1266
|
+
summary: serializeprovisionedcpu(provisioned),
|
|
1267
|
+
march: marchFlag(),
|
|
1268
|
+
cpuinfohead: provisioned.cpuinfotext.split('\n').slice(0, 5).join('\n'),
|
|
1269
|
+
};
|
|
1270
|
+
} catch (cause) {
|
|
1271
|
+
throw new hardwareerror('virtualcpudemo failed', { cause: cause as Error });
|
|
1272
|
+
}
|
|
1273
|
+
}
|