refactor: burn wrapper shadowing baseline entries (#122040)

* refactor: burn wrapper shadowing entries

* chore: refresh wrapper shadowing baselines

* test: update secrets runtime state mocks

* fix(ci): absorb Control UI build identity variance
This commit is contained in:
Peter Steinberger
2026-08-11 08:24:03 -07:00
committed by GitHub
parent b30e0dc4c6
commit db73b59c04
172 changed files with 769 additions and 943 deletions
+20 -20
View File
@@ -3,12 +3,12 @@
{"contentHash":"0d6827cdd7180482c49dc67aacc2b512e587d3453536081c15d3febaea2f1492","entrypoint":"account-id","importSpecifier":"openclaw/plugin-sdk/account-id"}
{"contentHash":"0b4930a77ab3e63bed21a9651a23fb7130f623baf6ce153166cb80a965b0a004","entrypoint":"account-resolution","importSpecifier":"openclaw/plugin-sdk/account-resolution"}
{"contentHash":"0349da0a93dadbdcff03ae8064b5066c5f2e1c28ee298bfa9ab3f1f8563300eb","entrypoint":"agent-config-primitives","importSpecifier":"openclaw/plugin-sdk/agent-config-primitives"}
{"contentHash":"b6c5507d2fc6a0467480a468d1131efba94faef5284b78d2dd3e7b8cb2fd3105","entrypoint":"agent-harness","importSpecifier":"openclaw/plugin-sdk/agent-harness"}
{"contentHash":"ec417e2b535f930d1c9d52e4a64375327913b9b92022c583a2e7f7a1ea7a4b25","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime"}
{"contentHash":"bf900891a3c6ee746fdf5033882e8ca88bc03ae0b2c971bb5977c0f0db506506","entrypoint":"agent-harness","importSpecifier":"openclaw/plugin-sdk/agent-harness"}
{"contentHash":"4f8b570b60781e746c19cd370d5c5967ad68047b255e81fd29d0dff95bfc9f3e","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime"}
{"contentHash":"4387e74b1261f632a0e140276c0f8cbbbe848a11f7ad287325538ebbee3b09da","entrypoint":"agent-media-payload","importSpecifier":"openclaw/plugin-sdk/agent-media-payload"}
{"contentHash":"b065a946eca85d03276bc0f6b1c04af1e44ee4ce441e5a5477f13d13aa3de17b","entrypoint":"agent-runtime","importSpecifier":"openclaw/plugin-sdk/agent-runtime"}
{"contentHash":"6fe3155f10712bc5d001f1f69e502f3e1a0b4179bb5ed7100d0ca7df933085be","entrypoint":"agent-runtime","importSpecifier":"openclaw/plugin-sdk/agent-runtime"}
{"contentHash":"1f0e51c8b1a58fff13ab7d19806d97bf07fca61a5c7edeb3437cd805775a8320","entrypoint":"agent-scope-runtime","importSpecifier":"openclaw/plugin-sdk/agent-scope-runtime"}
{"contentHash":"ce460dee97b375e50944f4da2ac95fe4c7a3f7be6b435550f54088b16369ed49","entrypoint":"allow-from","importSpecifier":"openclaw/plugin-sdk/allow-from"}
{"contentHash":"1f45bc7ea08bd3029e9a6bfd723f930324df2e7da79e1bd81bfb02f50c57362a","entrypoint":"allow-from","importSpecifier":"openclaw/plugin-sdk/allow-from"}
{"contentHash":"c19f8658d0db60b1d3eddfeae9639ca6558592d7d69c6905ab2994b4a572f25b","entrypoint":"allowlist-config-edit","importSpecifier":"openclaw/plugin-sdk/allowlist-config-edit"}
{"contentHash":"2800815b9a0dac84fccd0b946bc938ba31ba3915990b899b0ebce3b80744ed47","entrypoint":"approval-auth-runtime","importSpecifier":"openclaw/plugin-sdk/approval-auth-runtime"}
{"contentHash":"6fef2bb5627a1f9de6bad01c0ba0d15a4fb64a0f3310c26f1c2cbce67088516c","entrypoint":"approval-client-runtime","importSpecifier":"openclaw/plugin-sdk/approval-client-runtime"}
@@ -26,19 +26,19 @@
{"contentHash":"222019df4c06aca4e9bbede0fdea4b946f9b024a1524e3837c3c13be6d3d9e6a","entrypoint":"channel-config-primitives","importSpecifier":"openclaw/plugin-sdk/channel-config-primitives"}
{"contentHash":"645ec473e40a04e4cc627d05c9156f66d835eb67dab32166f745f66eadc98880","entrypoint":"channel-config-schema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema"}
{"contentHash":"75935c1d837265d191436d43bbfe24c6328b35a45a68cad250c157923badf857","entrypoint":"channel-contract","importSpecifier":"openclaw/plugin-sdk/channel-contract"}
{"contentHash":"d1d17e04a95ebb93d4213caa49e214b9da55163465474c33a42cfab27dd855ee","entrypoint":"channel-core","importSpecifier":"openclaw/plugin-sdk/channel-core"}
{"contentHash":"28666b0cf5d0bdf28648baffffcf1239e4d27727408c785fa06f5c271fc0843a","entrypoint":"channel-core","importSpecifier":"openclaw/plugin-sdk/channel-core"}
{"contentHash":"b2d90f161ca88ef2d5ff35f87f160c772bd784a4ebda91b2ab33bf16b6abd843","entrypoint":"channel-dm-policy","importSpecifier":"openclaw/plugin-sdk/channel-dm-policy"}
{"contentHash":"571b88343e5e7028d2dc8a414d3c7c6cfc26c4fe72c296258e615a308fc1b6d5","entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract"}
{"contentHash":"49a549e6a39d55279ecafe650e7e00496ebd6da5266cb11e486f5ee19f53b4c1","entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract"}
{"contentHash":"8bc8b784c78a70ee58731aae0be9731c9af01705db00acbafa25de9745a23601","entrypoint":"channel-feedback","importSpecifier":"openclaw/plugin-sdk/channel-feedback"}
{"contentHash":"6da95ea5bb2850b714f47387e1e970b761ac64d02e40531e797d0584e2c6434d","entrypoint":"channel-inbound","importSpecifier":"openclaw/plugin-sdk/channel-inbound"}
{"contentHash":"99cee44d09759fdbb01bc1b50e430933c61c745ec3c7880ea7e2aa63b382c673","entrypoint":"channel-inbound","importSpecifier":"openclaw/plugin-sdk/channel-inbound"}
{"contentHash":"87ba6e4e9f2f56621f6d52cc262e8b80fada5e338e841439b4d20983e22dfb82","entrypoint":"channel-inbound-debounce","importSpecifier":"openclaw/plugin-sdk/channel-inbound-debounce"}
{"contentHash":"7a69b23fdd7b631ed407d9ae4af55df192d93b61488c81626f041d4199760d95","entrypoint":"channel-ingress-runtime","importSpecifier":"openclaw/plugin-sdk/channel-ingress-runtime"}
{"contentHash":"85afc43170761c8d7d6d2d91401b0ad033189636050e8cf85d22132e4aba9f1a","entrypoint":"channel-lifecycle","importSpecifier":"openclaw/plugin-sdk/channel-lifecycle"}
{"contentHash":"be803c0341214a8e731f98cb7bf98654410ab1e0254d90f9f1ad9f442f70669f","entrypoint":"channel-logging","importSpecifier":"openclaw/plugin-sdk/channel-logging"}
{"contentHash":"97e407fc8124084452fee297707490622f529565f4ca6f7dbc306b189db429ab","entrypoint":"channel-message","importSpecifier":"openclaw/plugin-sdk/channel-message"}
{"contentHash":"37a8bcb4eadeb02a4b71ebfa56e0a3d97efd52dd63f066a29766880abcb01146","entrypoint":"channel-outbound","importSpecifier":"openclaw/plugin-sdk/channel-outbound"}
{"contentHash":"970ba9dd27f5e4d6a09b0ffec37264cdb3f745a5934e2cb8cc53eee78f2c176a","entrypoint":"channel-message","importSpecifier":"openclaw/plugin-sdk/channel-message"}
{"contentHash":"574fa42cccdf71a38cb19a0662dacbcbd94486069f01fda496e950384897ddbf","entrypoint":"channel-outbound","importSpecifier":"openclaw/plugin-sdk/channel-outbound"}
{"contentHash":"fee97710da33e100a8987aed897be17ab3ec4ece9fa09b7eb871a90461c8fca3","entrypoint":"channel-pairing","importSpecifier":"openclaw/plugin-sdk/channel-pairing"}
{"contentHash":"1c135098d104d0b73b95b3fc41ba2c27e6eca836cbb16e21601452219d4d8099","entrypoint":"channel-plugin-common","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common"}
{"contentHash":"897b21d2b152cacd699378eabe938caaee71171ec4002a3dd6dd42efabcda0f7","entrypoint":"channel-plugin-common","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common"}
{"contentHash":"350b4986aec115e3674c9dd3712302e7c185dbefc534b65a98a6a84564e65e05","entrypoint":"channel-policy","importSpecifier":"openclaw/plugin-sdk/channel-policy"}
{"contentHash":"369721c067caf33fc86e50c7dd5aec3e8371d2e97e2e3c4305751b79da9e7387","entrypoint":"channel-reply-pipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline"}
{"contentHash":"5181d3f1c6936e1e13a7d3ab4b904f5ae929a1985480c130915710a9bf8e8a25","entrypoint":"channel-runtime-context","importSpecifier":"openclaw/plugin-sdk/channel-runtime-context"}
@@ -60,12 +60,12 @@
{"contentHash":"1deb735b023442072fe21294cf4f94af0e44356fd8591ed6a8a9befafc7c3d67","entrypoint":"config-mutation","importSpecifier":"openclaw/plugin-sdk/config-mutation"}
{"contentHash":"40df7e972484ae28718fef1095b2b44cb2cc9eadd35464bf28d4ae0d0f0f66b5","entrypoint":"config-runtime","importSpecifier":"openclaw/plugin-sdk/config-runtime"}
{"contentHash":"7a5a2f4d3e5e18d211480286d125419ecbf8175bb6f8eeee9a6ee105df03cb3f","entrypoint":"conversation-runtime","importSpecifier":"openclaw/plugin-sdk/conversation-runtime"}
{"contentHash":"ace1613bc3d78ac0daeb15bd9c2c048e5916ac2279095813e72b5ddfcfe68e60","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core"}
{"contentHash":"db165d4f6bdb943dae0cb3015cafcb6d94d2482fff712eda98eb5442d418b095","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core"}
{"contentHash":"184f6a3849b361adfc9db756699787e934e274f05eeedcda04cd2b7cb4f9fe5e","entrypoint":"dedupe-runtime","importSpecifier":"openclaw/plugin-sdk/dedupe-runtime"}
{"contentHash":"8ba476d7f0411071797cd4362f3a71720d9d008d54107b2cb4eccb4a4eb0db0a","entrypoint":"device-bootstrap","importSpecifier":"openclaw/plugin-sdk/device-bootstrap"}
{"contentHash":"cb6fbd1612e60755c7528a5243cec69c9123904297d2e16a9c716485785be532","entrypoint":"diagnostic-runtime","importSpecifier":"openclaw/plugin-sdk/diagnostic-runtime"}
{"contentHash":"f7b6949b179827646d4e047ce4f181550ca8d67bd4537441405d36fb79438556","entrypoint":"directory-runtime","importSpecifier":"openclaw/plugin-sdk/directory-runtime"}
{"contentHash":"ef6120fc7033025caad534b2ab4edbdffde2088e0019654fe8334c9e012917b6","entrypoint":"discord","importSpecifier":"openclaw/plugin-sdk/discord"}
{"contentHash":"4b32922587dab4f465f85b7fea02e3b64d89ebea73a496501aa3c59fa7ef6337","entrypoint":"discord","importSpecifier":"openclaw/plugin-sdk/discord"}
{"contentHash":"e0523b4936d7c7ec043265de9e2a8f6289d32dacba0a28c3999ba3a0975dfc21","entrypoint":"error-runtime","importSpecifier":"openclaw/plugin-sdk/error-runtime"}
{"contentHash":"5125d71bf8c4aeca728c4b8c73b2984247ba7bcc088a45ee29692ff64e3ebf90","entrypoint":"extension-shared","importSpecifier":"openclaw/plugin-sdk/extension-shared"}
{"contentHash":"cbeb81159a1e558846f3cf9eecf3fd5a84858029cfdd9ccf237af428e35e755c","entrypoint":"gateway-method-runtime","importSpecifier":"openclaw/plugin-sdk/gateway-method-runtime"}
@@ -75,7 +75,7 @@
{"contentHash":"273ebd4fcac3041e3a136410fa396b9704c73eedb66414723996127ed80db8f3","entrypoint":"hook-runtime","importSpecifier":"openclaw/plugin-sdk/hook-runtime"}
{"contentHash":"a6537713e63d101897ef9ddfeaae438a50645e2672be5bdced887c4e8a651b96","entrypoint":"inbound-envelope","importSpecifier":"openclaw/plugin-sdk/inbound-envelope"}
{"contentHash":"931a52a774750ab895236a8fa7851781ad0279cb5678b1a78e81af9dd25bb3a4","entrypoint":"inbound-event-delivery","importSpecifier":"openclaw/plugin-sdk/inbound-event-delivery"}
{"contentHash":"699bafa75513e6fffb80ecfc0ccc3f0746fdf291f570e128a1ddfa09c2fac97d","entrypoint":"inbound-reply-dispatch","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch"}
{"contentHash":"c1acc4ca962cb62ae6036308b6d90c2e018420cf8b0f12594b2b876f5a5b0ca2","entrypoint":"inbound-reply-dispatch","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch"}
{"contentHash":"b590647f65a2e148ba7a1bc207f70adbd3a57990b41d3bf6b10f61ee8f27ab87","entrypoint":"infra-runtime","importSpecifier":"openclaw/plugin-sdk/infra-runtime"}
{"contentHash":"41a1f24a1b745f833d44e622ae1922c9dc66ee5de56f0e967ec1a3f9e03a2d18","entrypoint":"ingress-effect-once","importSpecifier":"openclaw/plugin-sdk/ingress-effect-once"}
{"contentHash":"57f79c6e8db72b2806bc8c016066682de71bf690378ccb4403b8da6dd3d38b28","entrypoint":"interactive-runtime","importSpecifier":"openclaw/plugin-sdk/interactive-runtime"}
@@ -89,7 +89,7 @@
{"contentHash":"0df97720dfd7b1a5892bbf3d46bc64297468af9b8cbb8720ce0d80d42ff2e59d","entrypoint":"media-store","importSpecifier":"openclaw/plugin-sdk/media-store"}
{"contentHash":"684c061bb0d1112872c9b2d5a00e258d14b4ff8649a26dd0cc67995352d8ca8b","entrypoint":"media-understanding","importSpecifier":"openclaw/plugin-sdk/media-understanding"}
{"contentHash":"f48e34067ab9b25a232af71d8ce17f9cbf9165ebce0832deaae3c1d9c9aeaab7","entrypoint":"media-understanding-runtime","importSpecifier":"openclaw/plugin-sdk/media-understanding-runtime"}
{"contentHash":"98583ac36cd86b8533f323c2cdb76deb3803b23e10e2fc2cfc177ed7f47d6522","entrypoint":"meeting-runtime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime"}
{"contentHash":"18782530d1c5bb66e086dd0177eb8ee52d152805aa68932a945fbc35178c3b03","entrypoint":"meeting-runtime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime"}
{"contentHash":"27509d9bbabc547662a45bf258fa432d1e0c3c3f7c22051858d8a67375486e79","entrypoint":"memory-core-host-engine-foundation","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation"}
{"contentHash":"ad875662e95df74808357c234ac36825d1ff729165da941180061591525ff47f","entrypoint":"memory-host-core","importSpecifier":"openclaw/plugin-sdk/memory-host-core"}
{"contentHash":"0f140018c2c21965b6a8f7a2ac1882babcaf70e733b477bb693e498641629938","entrypoint":"messaging-targets","importSpecifier":"openclaw/plugin-sdk/messaging-targets"}
@@ -101,10 +101,10 @@
{"contentHash":"3b2106094ccada38a6736f39abbb5814e776638cdb7f1f6d065576e6f8a2d3b6","entrypoint":"persistent-dedupe","importSpecifier":"openclaw/plugin-sdk/persistent-dedupe"}
{"contentHash":"e43fcfe8f88cf8d338c3e3496f3bdd6ec14afc1fcf341e171f7758f5c0190d5b","entrypoint":"plugin-command-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime"}
{"contentHash":"756175b7ff16cd8456b3c85a87466f077476a9236e098c5545ea8ef31fcff0d2","entrypoint":"plugin-config-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-config-runtime"}
{"contentHash":"e898b4f42be94df7004177ecfe78d9f07eb5ea7156563f9c3d998ce1a9109d67","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry"}
{"contentHash":"998e819896710d288c7eb70eda60d0b2a6e78ad5a196abd67df6644178f73daf","entrypoint":"plugin-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime"}
{"contentHash":"3f92b4ce6954e9bbe85a7675f7ad000e01e6b34049523a9a3e38d23966ad959a","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry"}
{"contentHash":"60b7d6caebf369d35a367e431f77eb3f7e5437870ef1da5f024ea8c71217b1cb","entrypoint":"plugin-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime"}
{"contentHash":"d5d21f2a0883eac72d6642d93306c36e2de0f3851286eb3edbe3a2d9d6122dcc","entrypoint":"provider-auth","importSpecifier":"openclaw/plugin-sdk/provider-auth"}
{"contentHash":"62853769aed0937975c704dfef003559b5e9a48ae809cc5f0a1e53632ba17ff7","entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime"}
{"contentHash":"36aad63a3fda1116df864fcdaa3c26d2c0d7af809603d3d4afaf96dcccdd8391","entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime"}
{"contentHash":"aee2a235e7218ed4ba36e80e0a6d67ceb3b5de448f25ebc10d6f70552dc35b8a","entrypoint":"proxy-capture","importSpecifier":"openclaw/plugin-sdk/proxy-capture"}
{"contentHash":"55bc0be5ce1d700d8b671efccb69ec14a3c942535c2f77d3ed7ca87809dc1ad9","entrypoint":"question-gateway-runtime","importSpecifier":"openclaw/plugin-sdk/question-gateway-runtime"}
{"contentHash":"5263836c817c9391fd5a0efdda50552330dd01e4d6bc9cb4ebba58627c48f098","entrypoint":"reply-chunking","importSpecifier":"openclaw/plugin-sdk/reply-chunking"}
@@ -142,11 +142,11 @@
{"contentHash":"09957526abf9619fd2ef095119a7195f2bebf2d8e8b1a5605aee0868152f8b5c","entrypoint":"temp-path","importSpecifier":"openclaw/plugin-sdk/temp-path"}
{"contentHash":"4519df78f420290da1fd755f7e4a7de7d09dbc934b3e17fc139aaf64896ffa06","entrypoint":"text-chunking","importSpecifier":"openclaw/plugin-sdk/text-chunking"}
{"contentHash":"c5f29e3b48cb9a92111bf565f739875a32fc3e19a009dd0bab3c27bbb71f7583","entrypoint":"text-runtime","importSpecifier":"openclaw/plugin-sdk/text-runtime"}
{"contentHash":"4ce582ca52fde9a7281dcdd3b4b2d3ade5c248a524ceac6049a5f3868da8d81a","entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin"}
{"contentHash":"39bc2bdca81266a16eab23271664ad8cbffdf2fc9b7f0f1d04c98c2611c53c5d","entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin"}
{"contentHash":"17e58e27b06e2470908acd719f64ec2add1f117c1882adad79eb5a3b5bd74312","entrypoint":"tool-results","importSpecifier":"openclaw/plugin-sdk/tool-results"}
{"contentHash":"aabfb4eacce1bd5190b2f92189332abe7bbe3a5cea3655babe66bf1909206984","entrypoint":"tool-send","importSpecifier":"openclaw/plugin-sdk/tool-send"}
{"contentHash":"8d432f42395afae27f4a95c897dfca0bf5df6289c0846d326df424ad5f6b491b","entrypoint":"web-media","importSpecifier":"openclaw/plugin-sdk/web-media"}
{"contentHash":"e16eaf86f2bc171afd654f94fdfac5a396ef1371109f0c399fe607345e6de1cf","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress"}
{"contentHash":"fa8effcbdf093c93d07526b1655ed5941fd277e484a55e680ad84874a8323867","entrypoint":"web-media","importSpecifier":"openclaw/plugin-sdk/web-media"}
{"contentHash":"1600c91e3364cf9bd9cceaec9403f3c96503a145620e18a30502af3b53571e4c","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress"}
{"contentHash":"1fe8314d4dfa3d7b536f39ac5622ff688f6a20fa6ae8b8fa4770d4851e85a400","entrypoint":"webhook-request-guards","importSpecifier":"openclaw/plugin-sdk/webhook-request-guards"}
{"contentHash":"6091f4048c4464103dfdf659904c6afa6e29c483b9a05c502ab3333df08f942b","entrypoint":"widget-html","importSpecifier":"openclaw/plugin-sdk/widget-html"}
{"contentHash":"eafdc7277066acf893bfef9b635689c1a69d6d5af22ad8cee2b47351d9b53ca6","entrypoint":"zod","importSpecifier":"openclaw/plugin-sdk/zod"}
+9 -2
View File
@@ -23,6 +23,10 @@ const DEFAULT_STARTUP_BUDGET_BASELINE_PATH = path.resolve(
// fixed JS ceiling bounds cumulative creep.
export const CONTROL_UI_STARTUP_JS_GZIP_TOLERANCE_BYTES = 1024;
// The startup bundle embeds commit SHA and timestamp identity. Those fixed-length,
// high-entropy values move Linux gzip output by tens of bytes between identical builds.
export const CONTROL_UI_STARTUP_JS_GZIP_IDENTITY_VARIANCE_BYTES = 64;
// Small, explicit headroom over the optimized baseline. Budget changes should
// accompany an intentional loading or chunking decision.
const controlUiPerformanceBudgets = {
@@ -146,10 +150,13 @@ export function evaluateControlUiPerformanceBudgets(
startupBudgetBaseline: Readonly<ControlUiStartupBudgetBaseline> | null = null,
startupJsTolerance = CONTROL_UI_STARTUP_JS_GZIP_TOLERANCE_BYTES,
) {
const startupJsFixedLimit =
budgets.startupJsGzipBytes +
(startupBudgetBaseline ? CONTROL_UI_STARTUP_JS_GZIP_IDENTITY_VARIANCE_BYTES : 0);
const checks: Array<[string, number, number, "count" | "bytes"]> = [
["startup JS requests", metrics.startup.js.requests, budgets.startupJsRequests, "count"],
["startup CSS requests", metrics.startup.css.requests, budgets.startupCssRequests, "count"],
["startup JS gzip", metrics.startup.js.gzipBytes, budgets.startupJsGzipBytes, "bytes"],
["startup JS gzip", metrics.startup.js.gzipBytes, startupJsFixedLimit, "bytes"],
["startup CSS gzip", metrics.startup.css.gzipBytes, budgets.startupCssGzipBytes, "bytes"],
["largest JS gzip", metrics.largest.js.gzipBytes, budgets.largestJsGzipBytes, "bytes"],
["largest CSS gzip", metrics.largest.css.gzipBytes, budgets.largestCssGzipBytes, "bytes"],
@@ -226,7 +233,7 @@ export function formatControlUiPerformanceReport(
];
if (startupBudgetBaseline) {
lines.push(
` startup JS gzip vs baseline: ${metrics.startup.js.gzipBytes} B (baseline ${startupBudgetBaseline.startupJsGzipBytes} B + tolerance ${startupJsTolerance} B, ceiling ${budgets.startupJsGzipBytes} B)`,
` startup JS gzip vs baseline: ${metrics.startup.js.gzipBytes} B (baseline ${startupBudgetBaseline.startupJsGzipBytes} B + tolerance ${startupJsTolerance} B, ceiling ${budgets.startupJsGzipBytes} B + build-identity variance ${CONTROL_UI_STARTUP_JS_GZIP_IDENTITY_VARIANCE_BYTES} B)`,
);
}
lines.push(
@@ -7,13 +7,6 @@
],
"sdk": true
},
{
"name": "clearSecretsRuntimeSnapshot",
"files": [
"src/secrets/runtime-state.ts",
"src/secrets/runtime.ts"
]
},
{
"name": "createPluginLoaderLogger",
"files": [
-153
View File
@@ -1,157 +1,4 @@
[
{
"name": "buildConfigSchema",
"wrapped": "src/config/schema.ts",
"wrapper": "src/config/doc-baseline.runtime.ts"
},
{
"name": "buildShouldSuppressBuiltInModel",
"wrapped": "src/agents/model-suppression.ts",
"wrapper": "src/agents/model-suppression.runtime.ts"
},
{
"name": "clearRuntimeAuthProfileStoreSnapshot",
"wrapped": "src/agents/auth-profiles/runtime-snapshots.ts",
"wrapper": "src/agents/auth-profiles/store.ts"
},
{
"name": "clearSecretsRuntimeSnapshot",
"wrapped": "src/secrets/runtime-state.ts",
"wrapper": "src/secrets/runtime.ts"
},
{
"name": "collectBundledChannelConfigs",
"wrapped": "src/plugins/bundled-channel-config-metadata.ts",
"wrapper": "src/config/doc-baseline.runtime.ts"
},
{
"name": "collectChannelSchemaMetadata",
"wrapped": "src/config/channel-config-metadata.ts",
"wrapper": "src/config/doc-baseline.runtime.ts"
},
{
"name": "collectChannelSecurityFindings",
"wrapped": "src/security/audit-channel.ts",
"wrapper": "src/security/audit-channel.collect.runtime.ts"
},
{
"name": "collectPluginSchemaMetadata",
"wrapped": "src/config/channel-config-metadata.ts",
"wrapper": "src/config/doc-baseline.runtime.ts"
},
{
"name": "createAgentHarnessToolSurfaceRuntime",
"wrapped": "src/agents/harness/tool-surface-bridge.ts",
"wrapper": "src/plugin-sdk/agent-harness-tool-runtime.ts"
},
{
"name": "createChannelPluginBase",
"wrapped": "src/plugin-sdk/core.ts",
"wrapper": "src/plugin-sdk/channel-core.ts"
},
{
"name": "createDeferred",
"wrapped": "src/shared/deferred.ts",
"wrapper": "src/plugin-sdk/extension-shared.ts"
},
{
"name": "DEFAULT_PROGRESS_DRAFT_LABELS",
"wrapped": "src/shared/progress-labels.ts",
"wrapper": "src/channels/streaming.ts"
},
{
"name": "getActivePluginRegistryWorkspaceDirFromState",
"wrapped": "src/plugins/runtime-workspace-state.ts",
"wrapper": "src/plugins/runtime-state.ts"
},
{
"name": "getActiveRuntimeWebToolsMetadata",
"wrapped": "src/secrets/runtime-web-tools-state.ts",
"wrapper": "src/secrets/runtime.ts"
},
{
"name": "getActiveSecretsRuntimeEnv",
"wrapped": "src/secrets/runtime-state.ts",
"wrapper": "src/secrets/runtime.ts"
},
{
"name": "getActiveSecretsRuntimeSnapshotRevision",
"wrapped": "src/secrets/runtime-state.ts",
"wrapper": "src/secrets/runtime.ts"
},
{
"name": "getActiveSecretsRuntimeSnapshot",
"wrapped": "src/secrets/runtime-state.ts",
"wrapper": "src/secrets/runtime.ts"
},
{
"name": "getActiveSkillEnvKeys",
"wrapped": "src/skills/runtime/env-overrides.ts",
"wrapper": "src/skills/runtime/env-overrides.runtime.ts"
},
{
"name": "getApiKeyForModel",
"wrapped": "src/agents/model-auth-model.ts",
"wrapper": "src/plugins/runtime/runtime-model-auth.runtime.ts",
"via": "src/agents/model-auth.ts"
},
{
"name": "getCoreCliCommandNames",
"wrapped": "src/cli/program/core-command-descriptors.ts",
"wrapper": "src/cli/program/command-registry-core.ts"
},
{
"name": "getDefaultLocalRoots",
"wrapped": "src/media/local-media-access.ts",
"wrapper": "src/plugins/runtime/runtime-web-channel-plugin.ts",
"via": "src/media/web-media.ts"
},
{
"name": "getDiagnosticSessionStateCountForTest",
"wrapped": "src/logging/diagnostic-session-state.ts",
"wrapper": "src/logging/diagnostic.ts"
},
{
"name": "getPreparedRuntimeAuthProfileStoreSnapshot",
"wrapped": "src/agents/auth-profiles/runtime-snapshots.ts",
"wrapper": "src/agents/auth-profiles/store.ts"
},
{
"name": "getRuntimeAuthProfileStoreSnapshot",
"wrapped": "src/agents/auth-profiles/runtime-snapshots.ts",
"wrapper": "src/agents/auth-profiles/store.ts"
},
{
"name": "getSubCliEntries",
"wrapped": "src/cli/program/subcli-descriptors.ts",
"wrapper": "src/cli/program/register.subclis-core.ts"
},
{
"name": "hasExplicitPluginConfig",
"wrapped": "src/plugins/config-normalization-shared.ts",
"wrapper": "src/plugins/config-state.ts"
},
{
"name": "isAllowedParsedChatSender",
"wrapped": "src/channels/plugins/chat-target-prefixes.ts",
"wrapper": "src/plugin-sdk/allow-from.ts"
},
{
"name": "isBundledChannelEnabledByChannelConfig",
"wrapped": "src/plugins/config-normalization-shared.ts",
"wrapper": "src/plugins/config-state.ts"
},
{
"name": "isMissingPathError",
"wrapped": "src/infra/errno.ts",
"wrapper": "src/plugin-sdk/memory-host-event-export.ts",
"via": "src/infra/errors.ts"
},
{
"name": "listAuthProfileStoreAgentDirs",
"wrapped": "src/secrets/auth-store-paths.ts",
"wrapper": "src/secrets/storage-scan.ts"
},
{
"name": "loadBundledPluginPublicSurfaceModuleSync",
"wrapped": "src/plugin-sdk/facade-loader.ts",
@@ -18,7 +18,7 @@ import {
saveAuthProfileStore,
} from "./auth-profiles.js";
import { isLiveTestEnabled, readLiveTestConfig } from "./live-test-helpers.js";
import { getApiKeyForModel, requireApiKey } from "./model-auth.js";
import { getApiKeyForModelCore, requireApiKey } from "./model-auth.js";
import { normalizeProviderId, parseModelRef } from "./model-selection.js";
import { ensureOpenClawModelsJson } from "./models-config.js";
@@ -205,7 +205,7 @@ describeLive("live anthropic setup-token", () => {
);
}
const apiKeyInfo = await getApiKeyForModel({
const apiKeyInfo = await getApiKeyForModelCore({
model,
cfg,
profileId: tokenSource.profileId,
+3 -3
View File
@@ -40,7 +40,7 @@ import { assertNoOAuthSecretRefPolicyViolations } from "./policy.js";
import { clearLastGoodProfileWithLock } from "./profiles.js";
import { suggestOAuthProfileIdForLegacyDefault } from "./repair.js";
import {
getRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshotCore,
hasRuntimeAuthProfileStoreSnapshot,
setRuntimeAuthProfileStoreSnapshot,
} from "./runtime-snapshots.js";
@@ -311,7 +311,7 @@ function resolveRuntimeAuthProfile(params: {
profile: AuthProfileCredential;
defaults: SecretDefaults | undefined;
}): { profile: AuthProfileCredential; published: boolean } {
const runtimeProfile = getRuntimeAuthProfileStoreSnapshot(params.agentDir)?.profiles[
const runtimeProfile = getRuntimeAuthProfileStoreSnapshotCore(params.agentDir)?.profiles[
params.profileId
];
const inputRefKey = authProfileSecretRefKey(params.profile, params.defaults);
@@ -514,7 +514,7 @@ export async function resolveApiKeyForProfile(
params.agentDir !== ownerAgentDir &&
hasRuntimeAuthProfileStoreSnapshot(params.agentDir)
) {
const snapshot = getRuntimeAuthProfileStoreSnapshot(params.agentDir);
const snapshot = getRuntimeAuthProfileStoreSnapshotCore(params.agentDir);
const providerKey = resolveProviderIdForAuth(cred.provider);
if (snapshot?.lastGood?.[providerKey] === profileId) {
delete snapshot.lastGood[providerKey];
+1 -1
View File
@@ -29,7 +29,7 @@ import {
} from "./profiles.js";
import {
clearRuntimeAuthProfileStoreSnapshots,
getRuntimeAuthProfileStoreSnapshot as getInternalRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshotCore as getInternalRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreCredentialMutationToken,
getRuntimeAuthProfileStoreCredentialsRevision,
getRuntimeAuthProfileStoreStateMutationToken,
@@ -12,10 +12,10 @@ import {
revokeRuntimeAuthMaterializations,
} from "./runtime-materializations.js";
import {
clearRuntimeAuthProfileStoreSnapshot,
clearRuntimeAuthProfileStoreSnapshotCore,
clearRuntimeAuthProfileStoreSnapshots,
getPreparedRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshot,
getPreparedRuntimeAuthProfileStoreSnapshotCore,
getRuntimeAuthProfileStoreSnapshotCore,
getRuntimeAuthProfileStoreCredentialsRevision,
noteRuntimeAuthProfileStorePersistedMutation,
registerRuntimeAuthProfileStoreMutationListener,
@@ -171,7 +171,7 @@ describe("runtime auth profile snapshots", () => {
},
agentDir,
);
clearRuntimeAuthProfileStoreSnapshot(agentDir);
clearRuntimeAuthProfileStoreSnapshotCore(agentDir);
expect(listener).toHaveBeenCalledTimes(2);
expect(listener).toHaveBeenNthCalledWith(1, {
@@ -223,7 +223,7 @@ describe("runtime auth profile snapshots", () => {
try {
setRuntimeAuthProfileStoreSnapshot(emptyStore, agentDir);
setRuntimeAuthProfileStoreSnapshot(emptyStore, agentDir);
clearRuntimeAuthProfileStoreSnapshot(agentDir);
clearRuntimeAuthProfileStoreSnapshotCore(agentDir);
expect(listener).toHaveBeenCalledTimes(2);
expect(listener).toHaveBeenNthCalledWith(1, {
@@ -268,7 +268,7 @@ describe("runtime auth profile snapshots", () => {
).provider = "mutated";
expectDefined(stored.order?.openai, "stored OpenAI profile order").push("mutated");
const first = getRuntimeAuthProfileStoreSnapshot(agentDir);
const first = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
expectOpenAICodexSnapshotCredential(first, { access: "access-1" });
expect(first?.order?.["openai"]).toEqual(["openai:default"]);
@@ -280,7 +280,7 @@ describe("runtime auth profile snapshots", () => {
"first OpenAI usage stats",
).lastUsed = 99;
const second = getRuntimeAuthProfileStoreSnapshot(agentDir);
const second = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
expectOpenAICodexSnapshotCredential(second, { access: "access-1" });
expect(second?.usageStats?.["openai:default"]?.lastUsed).toBe(1);
@@ -292,7 +292,7 @@ describe("runtime auth profile snapshots", () => {
replacementCredential.access = "mutated-replacement";
}
const replaced = getRuntimeAuthProfileStoreSnapshot(agentDir);
const replaced = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
expectOpenAICodexSnapshotCredential(replaced, {
access: "access-2",
refresh: "refresh-access-2",
@@ -324,7 +324,7 @@ describe("runtime auth profile snapshots", () => {
);
setRuntimeAuthProfileStoreSnapshot(createStore("agent"), agentDir);
const prepared = getPreparedRuntimeAuthProfileStoreSnapshot(agentDir, inheritedAuthDir);
const prepared = getPreparedRuntimeAuthProfileStoreSnapshotCore(agentDir, inheritedAuthDir);
expectOpenAICodexSnapshotCredential(prepared, { access: "agent" });
expect(prepared?.profiles["anthropic:default"]).toMatchObject({
@@ -333,7 +333,7 @@ describe("runtime auth profile snapshots", () => {
key: "inherited-key",
});
expect(
getPreparedRuntimeAuthProfileStoreSnapshot(
getPreparedRuntimeAuthProfileStoreSnapshotCore(
"/tmp/openclaw-auth-runtime-missing",
"/tmp/openclaw-auth-runtime-also-missing",
),
@@ -351,13 +351,15 @@ describe("runtime auth profile snapshots", () => {
setRuntimeAuthProfileStoreSnapshot(createStore("first"), firstAgentDir);
setRuntimeAuthProfileStoreSnapshot(createStore("second"), secondAgentDir);
expect(clearRuntimeAuthProfileStoreSnapshot(firstAgentDir)).toBe(true);
expect(getRuntimeAuthProfileStoreSnapshot(firstAgentDir)).toBeUndefined();
expectOpenAICodexSnapshotCredential(getRuntimeAuthProfileStoreSnapshot(), { access: "main" });
expectOpenAICodexSnapshotCredential(getRuntimeAuthProfileStoreSnapshot(secondAgentDir), {
expect(clearRuntimeAuthProfileStoreSnapshotCore(firstAgentDir)).toBe(true);
expect(getRuntimeAuthProfileStoreSnapshotCore(firstAgentDir)).toBeUndefined();
expectOpenAICodexSnapshotCredential(getRuntimeAuthProfileStoreSnapshotCore(), {
access: "main",
});
expectOpenAICodexSnapshotCredential(getRuntimeAuthProfileStoreSnapshotCore(secondAgentDir), {
access: "second",
});
expect(clearRuntimeAuthProfileStoreSnapshot(firstAgentDir)).toBe(false);
expect(clearRuntimeAuthProfileStoreSnapshotCore(firstAgentDir)).toBe(false);
} finally {
clearRuntimeAuthProfileStoreSnapshots();
}
@@ -234,7 +234,7 @@ export function registerRuntimeAuthProfileStoreMutationListener(
}
/** Reads a cloned runtime auth profile store snapshot for an agent dir. */
export function getRuntimeAuthProfileStoreSnapshot(
export function getRuntimeAuthProfileStoreSnapshotCore(
agentDir?: string,
): RuntimeAuthProfileStore | undefined {
const store = runtimeAuthStoreSnapshots.get(resolveRuntimeStoreKey(agentDir));
@@ -245,12 +245,12 @@ export function getRuntimeAuthProfileStoreSnapshot(
* Reads the effective prepared auth store without falling back to persisted storage.
* Lifecycle consumers use this after auth publication so request paths never reopen SQLite.
*/
export function getPreparedRuntimeAuthProfileStoreSnapshot(
export function getPreparedRuntimeAuthProfileStoreSnapshotCore(
agentDir?: string,
inheritedAuthDir?: string,
): AuthProfileStore | undefined {
const inherited = getRuntimeAuthProfileStoreSnapshot(inheritedAuthDir);
const requested = getRuntimeAuthProfileStoreSnapshot(agentDir);
const inherited = getRuntimeAuthProfileStoreSnapshotCore(inheritedAuthDir);
const requested = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (!agentDir || resolveRuntimeStoreKey(agentDir) === resolveRuntimeStoreKey(inheritedAuthDir)) {
return requested ?? inherited;
}
@@ -280,14 +280,14 @@ export function hasRuntimeAuthProfileStoreSnapshot(agentDir?: string): boolean {
/** Returns true when requested or main runtime snapshots contain profiles. */
export function hasAnyRuntimeAuthProfileStoreSource(agentDir?: string): boolean {
const requestedStore = getRuntimeAuthProfileStoreSnapshot(agentDir);
const requestedStore = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (requestedStore && Object.keys(requestedStore.profiles).length > 0) {
return true;
}
if (!agentDir) {
return false;
}
const mainStore = getRuntimeAuthProfileStoreSnapshot();
const mainStore = getRuntimeAuthProfileStoreSnapshotCore();
return Boolean(mainStore && Object.keys(mainStore.profiles).length > 0);
}
@@ -342,7 +342,7 @@ export function clearRuntimeAuthProfileStoreSnapshots(): void {
}
/** Clears one runtime auth-profile snapshot without disturbing other active agents. */
export function clearRuntimeAuthProfileStoreSnapshot(agentDir?: string): boolean {
export function clearRuntimeAuthProfileStoreSnapshotCore(agentDir?: string): boolean {
const key = resolveRuntimeStoreKey(agentDir);
const store = runtimeAuthStoreSnapshots.get(key);
if (!store) {
+4 -4
View File
@@ -6,7 +6,7 @@ import { evaluateStoredCredentialEligibility } from "./credential-state.js";
import { hasLegacyAuthProfileCredentialSource } from "./legacy-source-diagnostic.js";
import { coercePersistedAuthProfileStore } from "./persisted.js";
import {
getRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshotCore,
hasAnyRuntimeAuthProfileStoreSource,
} from "./runtime-snapshots.js";
import {
@@ -116,7 +116,7 @@ export function hasAnyAuthProfileStoreSource(agentDir?: string): boolean {
/** Returns true when the requested agent dir has a local auth profile source. */
export function hasLocalAuthProfileStoreSource(agentDir?: string): boolean {
const runtimeStore = getRuntimeAuthProfileStoreSnapshot(agentDir);
const runtimeStore = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (runtimeStore && Object.keys(runtimeStore.profiles).length > 0) {
return true;
}
@@ -147,7 +147,7 @@ export function hasAuthProfileStoreSourceForProvider(
if (profileIds?.length === 0) {
return false;
}
const localRuntimeStore = getRuntimeAuthProfileStoreSnapshot(agentDir);
const localRuntimeStore = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (runtimeStoreHasProviderProfile(localRuntimeStore, provider, profileIds)) {
return true;
}
@@ -164,7 +164,7 @@ export function hasAuthProfileStoreSourceForProvider(
if (!agentDir) {
return false;
}
const mainRuntimeStore = getRuntimeAuthProfileStoreSnapshot();
const mainRuntimeStore = getRuntimeAuthProfileStoreSnapshotCore();
if (runtimeStoreHasProviderProfile(mainRuntimeStore, provider, profileIds)) {
return true;
}
+8 -8
View File
@@ -44,10 +44,10 @@ import {
mergeAuthProfileStores,
} from "./persisted.js";
import {
clearRuntimeAuthProfileStoreSnapshot as clearRuntimeAuthProfileStoreSnapshotImpl,
clearRuntimeAuthProfileStoreSnapshotCore,
clearRuntimeAuthProfileStoreSnapshots,
getPreparedRuntimeAuthProfileStoreSnapshot as getPreparedRuntimeAuthProfileStoreSnapshotImpl,
getRuntimeAuthProfileStoreSnapshot as getRuntimeAuthProfileStoreSnapshotImpl,
getPreparedRuntimeAuthProfileStoreSnapshotCore,
getRuntimeAuthProfileStoreSnapshotCore,
getRuntimeAuthProfileStoreSnapshotRevision,
noteRuntimeAuthProfileStorePersistedMutation,
listRuntimeAuthProfileStoreSnapshots,
@@ -282,8 +282,8 @@ function resolveRuntimeAuthProfileStore(
): AuthProfileStore | null {
const mainKey = resolveAuthStorePath(options?.inheritedAuthDir);
const requestedKey = resolveAuthStorePath(agentDir);
const mainStore = getRuntimeAuthProfileStoreSnapshotImpl(options?.inheritedAuthDir);
const requestedStore = getRuntimeAuthProfileStoreSnapshotImpl(agentDir);
const mainStore = getRuntimeAuthProfileStoreSnapshotCore(options?.inheritedAuthDir);
const requestedStore = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (!agentDir || requestedKey === mainKey) {
if (!mainStore) {
@@ -1317,7 +1317,7 @@ export {
export function getRuntimeAuthProfileStoreSnapshot(
agentDir?: string,
): AuthProfileStore | undefined {
return getRuntimeAuthProfileStoreSnapshotImpl(agentDir);
return getRuntimeAuthProfileStoreSnapshotCore(agentDir);
}
/** Return the lifecycle-published effective auth store without persisted fallback reads. */
@@ -1325,14 +1325,14 @@ export function getPreparedRuntimeAuthProfileStoreSnapshot(
agentDir?: string,
inheritedAuthDir?: string,
): AuthProfileStore | undefined {
return getPreparedRuntimeAuthProfileStoreSnapshotImpl(agentDir, inheritedAuthDir);
return getPreparedRuntimeAuthProfileStoreSnapshotCore(agentDir, inheritedAuthDir);
}
export { getRuntimeAuthProfileStoreSnapshotRevision };
/** Clear one runtime auth-profile snapshot. */
export function clearRuntimeAuthProfileStoreSnapshot(agentDir?: string): boolean {
return clearRuntimeAuthProfileStoreSnapshotImpl(agentDir);
return clearRuntimeAuthProfileStoreSnapshotCore(agentDir);
}
function saveAuthProfileStoreInTransaction(
@@ -1,6 +1,6 @@
import type { ManagedRun } from "../process/supervisor/index.js";
import type { SpawnInput } from "../process/supervisor/types.js";
import { createDeferred } from "../shared/deferred.js";
import { createDeferredCore } from "../shared/deferred.js";
import type { DeliveryContext } from "../utils/delivery-context.types.js";
import { markBackgrounded } from "./bash-process-registry.js";
import { runExecProcess } from "./bash-tools.exec-runtime.js";
@@ -14,7 +14,7 @@ export async function startDeferredNotifyRun(params: {
sessionKey: string;
notifyDeliveryContext?: DeliveryContext;
}) {
const exit = createDeferred<Awaited<ReturnType<ManagedRun["wait"]>>>();
const exit = createDeferredCore<Awaited<ReturnType<ManagedRun["wait"]>>>();
params.spawn.mockImplementationOnce(async (input) => {
input.onStdout?.("producer output\n");
return {
+1 -1
View File
@@ -137,7 +137,7 @@ vi.mock("./model-auth.js", () => ({
ensureAuthProfileStore: (...args: unknown[]) => ensureAuthProfileStoreMock(...args),
ensureAuthProfileStoreWithoutExternalProfiles: (...args: unknown[]) =>
ensureAuthProfileStoreWithoutExternalProfilesMock(...args),
getApiKeyForModel: (...args: unknown[]) => getApiKeyForModelMock(...args),
getApiKeyForModelCore: (...args: unknown[]) => getApiKeyForModelMock(...args),
hasUsableCustomProviderApiKey: (...args: unknown[]) => hasUsableCustomProviderApiKeyMock(...args),
requireApiKey: (...args: unknown[]) => requireApiKeyMock(...args),
resolveProviderEntryApiKeyProfileReference: (params: unknown) =>
@@ -781,7 +781,7 @@ export async function loadCompactHooksHarness(): Promise<{
(auth: { mode: string; source: string }, provider: string) =>
`No API key resolved for provider "${provider}" (auth mode: ${auth.mode}, checked: ${auth.source}).`,
),
getApiKeyForModel: (params: { profileId?: string; allowAuthProfileFallback?: boolean }) =>
getApiKeyForModelCore: (params: { profileId?: string; allowAuthProfileFallback?: boolean }) =>
getApiKeyForModelMock(params),
hasUsableCustomProviderApiKey: vi.fn(() => false),
resolveProviderEntryApiKeyProfileReference: resolveProviderEntryApiKeyProfileReferenceMock,
@@ -1004,7 +1004,7 @@ export async function loadRunOverflowCompactionHarness(): Promise<{
ensureAuthProfileStore: mockedEnsureAuthProfileStore,
ensureAuthProfileStoreWithoutExternalProfiles:
mockedEnsureAuthProfileStoreWithoutExternalProfiles,
getApiKeyForModel: mockedGetApiKeyForModel,
getApiKeyForModelCore: mockedGetApiKeyForModel,
hasUsableCustomProviderApiKey: mockedHasUsableCustomProviderApiKey,
resolveAuthProfileOrder: mockedResolveAuthProfileOrder,
resolveAuthProfileOrderWithMetadata: mockedResolveAuthProfileOrderWithMetadata,
@@ -15,7 +15,7 @@ import type { RuntimeAuthState } from "./helpers.js";
const mocks = vi.hoisted(() => ({
prepareProviderRuntimeAuth: vi.fn(),
getApiKeyForModel: vi.fn(),
getApiKeyForModelCore: vi.fn(),
}));
vi.mock("../../../plugins/provider-runtime.js", async () => {
@@ -32,7 +32,7 @@ vi.mock("../../model-auth.js", async () => {
const actual = await vi.importActual<typeof import("../../model-auth.js")>("../../model-auth.js");
return {
...actual,
getApiKeyForModel: mocks.getApiKeyForModel,
getApiKeyForModelCore: mocks.getApiKeyForModelCore,
};
});
@@ -165,7 +165,7 @@ function createMutableEmbeddedRunAuthController(params: {
describe("createEmbeddedRunAuthController", () => {
beforeEach(() => {
mocks.prepareProviderRuntimeAuth.mockReset();
mocks.getApiKeyForModel.mockReset();
mocks.getApiKeyForModelCore.mockReset();
});
it("commits a prepared route only after its credential resolves", async () => {
@@ -176,7 +176,7 @@ describe("createEmbeddedRunAuthController", () => {
baseUrl: "https://chatgpt.com/backend-api/codex",
contextWindow: 272_000,
};
mocks.getApiKeyForModel.mockImplementation(async ({ model }) => {
mocks.getApiKeyForModelCore.mockImplementation(async ({ model }) => {
expect(model).toBe(selectedModel);
expect(harness.runtimeModel).not.toBe(selectedModel);
return {
@@ -210,7 +210,7 @@ describe("createEmbeddedRunAuthController", () => {
it("rejects credentials whose class does not match the prepared route", async () => {
const harness = createMutableAuthControllerHarness();
const commit = vi.fn();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: "platform-key",
mode: "api-key",
source: "config",
@@ -243,7 +243,7 @@ describe("createEmbeddedRunAuthController", () => {
const harness = createMutableAuthControllerHarness();
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: "source-api-key",
mode: "api-key",
profileId: "default",
@@ -268,7 +268,7 @@ describe("createEmbeddedRunAuthController", () => {
await controller.initializeAuthProfile();
const apiKeyParams = mocks.getApiKeyForModel.mock.calls.at(0)?.[0] as
const apiKeyParams = mocks.getApiKeyForModelCore.mock.calls.at(0)?.[0] as
| { agentDir?: string; workspaceDir?: string }
| undefined;
expect(apiKeyParams?.agentDir).toBe("/tmp/agent");
@@ -296,7 +296,7 @@ describe("createEmbeddedRunAuthController", () => {
refKeys: ["env:default:MISSING_OPENAI_KEY"],
reason: "secret reference was not found",
});
mocks.getApiKeyForModel.mockImplementation(async ({ profileId }) => {
mocks.getApiKeyForModelCore.mockImplementation(async ({ profileId }) => {
if (profileId === "default") {
throw unavailable;
}
@@ -314,7 +314,7 @@ describe("createEmbeddedRunAuthController", () => {
});
await expect(controller.initializeAuthProfile()).rejects.toBe(unavailable);
expect(mocks.getApiKeyForModel).toHaveBeenCalledOnce();
expect(mocks.getApiKeyForModelCore).toHaveBeenCalledOnce();
expect(mocks.prepareProviderRuntimeAuth).not.toHaveBeenCalled();
});
@@ -328,7 +328,7 @@ describe("createEmbeddedRunAuthController", () => {
harness.effectiveModel = baseModel;
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
mocks.getApiKeyForModel.mockImplementation(async ({ profileId }) => ({
mocks.getApiKeyForModelCore.mockImplementation(async ({ profileId }) => ({
apiKey: `${String(profileId)}-source-key`,
mode: "api-key" as const,
profileId,
@@ -376,7 +376,7 @@ describe("createEmbeddedRunAuthController", () => {
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
const secret = "runtime-exchange-source-secret";
const sentinel = mintSecretSentinel(secret, { label: "model-auth:custom-openai" });
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: sentinel,
mode: "api-key",
source: "profile:custom-openai:default",
@@ -395,7 +395,7 @@ describe("createEmbeddedRunAuthController", () => {
const controller = createMutableEmbeddedRunAuthController({ harness, setRuntimeApiKey });
await controller.initializeAuthProfile();
expect(mocks.getApiKeyForModel).toHaveBeenCalledWith(
expect(mocks.getApiKeyForModelCore).toHaveBeenCalledWith(
expect.objectContaining({ secretSentinels: true }),
);
expect(mocks.prepareProviderRuntimeAuth).toHaveBeenCalledWith(
@@ -415,7 +415,7 @@ describe("createEmbeddedRunAuthController", () => {
const sentinel = mintSecretSentinel("runtime-source-secret", {
label: "model-auth:custom-openai",
});
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: sentinel,
mode: "api-key",
source: "profile:custom-openai:default",
@@ -435,7 +435,7 @@ describe("createEmbeddedRunAuthController", () => {
const source = mintSecretSentinel("kill-switch-source-secret", {
label: "model-auth:custom-openai",
});
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: source,
mode: "api-key",
source: "profile:custom-openai:default",
@@ -456,7 +456,7 @@ describe("createEmbeddedRunAuthController", () => {
const harness = createMutableAuthControllerHarness();
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
mode: "api-key",
source: "models.providers.custom-openai",
});
@@ -561,7 +561,7 @@ describe("createEmbeddedRunAuthController", () => {
it("rejects privileged runtime transport overrides on the first auth exchange", async () => {
let runtimeModel = createTestModel();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: "source-api-key",
mode: "api-key",
profileId: "default",
@@ -642,7 +642,7 @@ describe("createEmbeddedRunAuthController", () => {
expiresAt: number;
}>();
mocks.getApiKeyForModel.mockImplementation(async ({ profileId }) => {
mocks.getApiKeyForModelCore.mockImplementation(async ({ profileId }) => {
if (profileId === "backup") {
return {
apiKey: "backup-source-api-key",
@@ -744,7 +744,7 @@ describe("createEmbeddedRunAuthController", () => {
const harness = createMutableAuthControllerHarness();
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: undefined,
mode: "aws-sdk",
source: "aws-sdk default chain",
@@ -774,7 +774,7 @@ describe("createEmbeddedRunAuthController", () => {
const harness = createMutableAuthControllerHarness();
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: undefined,
mode: "aws-sdk",
source: "aws-sdk default chain",
@@ -806,7 +806,7 @@ describe("createEmbeddedRunAuthController", () => {
refreshTimer: setTimeout(() => undefined, 60_000),
};
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: undefined,
mode: "aws-sdk",
source: "aws-sdk default chain",
@@ -834,7 +834,7 @@ describe("createEmbeddedRunAuthController", () => {
const setRuntimeApiKey = vi.fn<(provider: string, apiKey: string) => void>();
const warn = vi.fn<(message: string) => void>();
mocks.getApiKeyForModel.mockResolvedValue({
mocks.getApiKeyForModelCore.mockResolvedValue({
apiKey: undefined,
mode: "aws-sdk",
source: "aws-sdk default chain",
@@ -22,7 +22,7 @@ import { FailoverError, resolveFailoverStatus } from "../../failover-error.js";
import { shouldUseTransientCooldownProbeSlot } from "../../failover-policy.js";
import { renderAuthProfileFailoverCopy } from "../../failover/user-copy.js";
import {
getApiKeyForModel,
getApiKeyForModelCore,
MissingProviderAuthError,
type ResolvedProviderAuth,
} from "../../model-auth.js";
@@ -449,7 +449,7 @@ export function createEmbeddedRunAuthController(params: {
model = params.getRuntimeModel(),
allowAuthProfileFallback?: boolean,
) => {
return getApiKeyForModel({
return getApiKeyForModelCore({
model,
cfg: params.config,
profileId: candidate,
+8 -8
View File
@@ -55,7 +55,7 @@ const agentRunAttempt = vi.fn<AgentHarness["runAttempt"]>(async () =>
const compactAuthMocks = vi.hoisted(() => ({
ensureAuthProfileStore: vi.fn(),
ensureAuthProfileStoreWithoutExternalProfiles: vi.fn(),
getApiKeyForModel: vi.fn(),
getApiKeyForModelCore: vi.fn(),
prepareAgentRuntimeAuth: vi.fn(),
resolveModelAsync: vi.fn(),
}));
@@ -122,7 +122,7 @@ vi.mock("../model-auth.js", async (importOriginal) => ({
ensureAuthProfileStore: compactAuthMocks.ensureAuthProfileStore,
ensureAuthProfileStoreWithoutExternalProfiles:
compactAuthMocks.ensureAuthProfileStoreWithoutExternalProfiles,
getApiKeyForModel: compactAuthMocks.getApiKeyForModel,
getApiKeyForModelCore: compactAuthMocks.getApiKeyForModelCore,
}));
vi.mock("../embedded-agent-runner/model.js", () => ({
resolveModelAsync: compactAuthMocks.resolveModelAsync,
@@ -174,7 +174,7 @@ beforeEach(async () => {
compactAuthMocks.resolveModelAsync.mockResolvedValue({
model: { id: "gpt-5.5", provider: "openai" },
});
compactAuthMocks.getApiKeyForModel.mockResolvedValue({ apiKey: "test-key" });
compactAuthMocks.getApiKeyForModelCore.mockResolvedValue({ apiKey: "test-key" });
providerOwnerMocks.resolveProviderRefOwnership.mockReset();
providerOwnerMocks.resolveProviderRefOwnership.mockReturnValue({ status: "unowned" });
contextEngineTurnAttemptMocks.drainPendingContextEngineTurnsBeforeRun
@@ -214,7 +214,7 @@ afterEach(() => {
agentRunAttempt.mockClear();
compactAuthMocks.prepareAgentRuntimeAuth.mockClear();
compactAuthMocks.resolveModelAsync.mockReset();
compactAuthMocks.getApiKeyForModel.mockReset();
compactAuthMocks.getApiKeyForModelCore.mockReset();
compactAuthMocks.ensureAuthProfileStore.mockReset();
compactAuthMocks.ensureAuthProfileStoreWithoutExternalProfiles.mockReset();
providerOwnerMocks.resolveProviderRefOwnership.mockReset();
@@ -2655,7 +2655,7 @@ describe("selectAgentHarness", () => {
).resolves.toEqual({ ok: true, compacted: false });
expect(compactAuthMocks.resolveModelAsync).not.toHaveBeenCalled();
expect(compactAuthMocks.getApiKeyForModel).not.toHaveBeenCalled();
expect(compactAuthMocks.getApiKeyForModelCore).not.toHaveBeenCalled();
expect(compact).toHaveBeenCalledWith(
expect.objectContaining({
runtimeAuthPlan: expect.objectContaining({
@@ -2881,7 +2881,7 @@ describe("selectAgentHarness", () => {
});
it("keeps compaction recoverable when auth profile lookup fails", async () => {
compactAuthMocks.getApiKeyForModel.mockRejectedValue(new Error("missing auth profile"));
compactAuthMocks.getApiKeyForModelCore.mockRejectedValue(new Error("missing auth profile"));
const compact = vi.fn<NonNullable<AgentHarness["compact"]>>(async () => ({
ok: true,
compacted: false,
@@ -2958,7 +2958,7 @@ describe("selectAgentHarness", () => {
}),
).resolves.toEqual({ ok: true, compacted: false });
expect(compactAuthMocks.getApiKeyForModel).not.toHaveBeenCalled();
expect(compactAuthMocks.getApiKeyForModelCore).not.toHaveBeenCalled();
expect(compact).toHaveBeenCalledWith(
expect.objectContaining({
resolvedApiKey: "already-resolved",
@@ -3069,7 +3069,7 @@ describe("selectAgentHarness", () => {
workspaceDir: "/tmp/workspace",
}),
);
expect(compactAuthMocks.getApiKeyForModel).toHaveBeenCalledWith(
expect(compactAuthMocks.getApiKeyForModelCore).toHaveBeenCalledWith(
expect.objectContaining({
agentDir: expect.any(String),
model: expect.objectContaining({
@@ -10,7 +10,7 @@ import {
TOOL_SEARCH_RAW_TOOL_NAME,
} from "../tool-search.js";
import { testing } from "../tool-search.test-support.js";
import { createAgentHarnessToolSurfaceRuntime as createAgentHarnessToolSurfaceRuntimeBase } from "./tool-surface-bridge.js";
import { createAgentHarnessToolSurfaceRuntimeCore as createAgentHarnessToolSurfaceRuntimeBase } from "./tool-surface-bridge.js";
function createAgentHarnessToolSurfaceRuntime(
params: Parameters<typeof createAgentHarnessToolSurfaceRuntimeBase>[0],
+1 -1
View File
@@ -51,7 +51,7 @@ export type AgentHarnessToolSurfaceRuntime = {
toolSearchCatalogExecutor: ToolSearchCatalogToolExecutor | undefined;
};
export function createAgentHarnessToolSurfaceRuntime(params: {
export function createAgentHarnessToolSurfaceRuntimeCore(params: {
abortSignal?: AbortSignal;
agentId?: string;
config?: OpenClawConfig;
+2 -2
View File
@@ -11,7 +11,7 @@ import { resolveDefaultAgentDir } from "./agent-scope.js";
import { collectProviderApiKeys } from "./live-auth-keys.js";
import { isLiveTestEnabled } from "./live-test-helpers.js";
import {
getApiKeyForModel,
getApiKeyForModelCore,
isMissingProviderAuthError,
isProviderAuthError,
requireApiKey,
@@ -269,7 +269,7 @@ export async function resolveLiveDirectModelPool(params: {
let apiKey: string;
try {
apiKey = requireApiKey(
await getApiKeyForModel({
await getApiKeyForModelCore({
model: resolvedModel,
cfg,
agentDir,
+2 -2
View File
@@ -32,7 +32,7 @@ import {
resolveStoredCredentialReadOnlyAvailability,
} from "./auth-profiles/read-only-availability.js";
import type { RuntimeAuthMaterialization } from "./auth-profiles/runtime-materializations.js";
import { getRuntimeAuthProfileStoreSnapshot } from "./auth-profiles/runtime-snapshots.js";
import { getRuntimeAuthProfileStoreSnapshotCore } from "./auth-profiles/runtime-snapshots.js";
import type { AuthProfileCredential, AuthProfileStore } from "./auth-profiles/types.js";
import {
isAuthCooldownBypassedForProvider,
@@ -183,7 +183,7 @@ export function createModelAuthAvailabilityResolver(
const runtimeStore =
params.preparedRuntimeAuthStore ??
(params.allowPreparedRuntimeAuth !== false
? getRuntimeAuthProfileStoreSnapshot(params.agentDir)
? getRuntimeAuthProfileStoreSnapshotCore(params.agentDir)
: undefined);
const hydratedProfileIds = new Set<string>();
const sameSecretRef = (
+1 -1
View File
@@ -232,7 +232,7 @@ export async function hasAvailableAuthForProvider(params: {
}
/** Resolves request credentials from the provider attached to a model descriptor. */
export async function getApiKeyForModel(params: {
export async function getApiKeyForModelCore(params: {
model: Model;
cfg?: OpenClawConfig;
profileId?: string;
+7 -7
View File
@@ -18,7 +18,7 @@ import { resolveInlineProviderApiKeyUsageId } from "./auth-profiles/usage.js";
import type { ClaudeCliCredential } from "./cli-credentials.js";
import {
createRuntimeProviderAuthLookup,
getApiKeyForModel,
getApiKeyForModelCore,
hasAvailableAuthForProvider,
hasRuntimeAvailableProviderAuth,
isConfigBackedInlineProviderApiKey,
@@ -403,7 +403,7 @@ async function resolveDemoLocalApiKey(params: {
});
}
describe("getApiKeyForModel", () => {
describe("getApiKeyForModelCore", () => {
it("reads oauth auth-profiles entries from auth-profiles.json via explicit profile", async () => {
await withOpenClawTestState(
{
@@ -432,7 +432,7 @@ describe("getApiKeyForModel", () => {
const store = ensureAuthProfileStore(process.env.OPENCLAW_AGENT_DIR, {
allowKeychainPrompt: false,
});
const apiKey = await getApiKeyForModel({
const apiKey = await getApiKeyForModelCore({
model,
profileId: "openai:default",
store,
@@ -460,7 +460,7 @@ describe("getApiKeyForModel", () => {
},
};
const directAuth = await getApiKeyForModel({
const directAuth = await getApiKeyForModelCore({
model: {
id: "chat-latest",
provider: "openai",
@@ -468,7 +468,7 @@ describe("getApiKeyForModel", () => {
} as Model,
store,
});
const codexAuth = await getApiKeyForModel({
const codexAuth = await getApiKeyForModelCore({
model: {
id: "gpt-5.5",
provider: "openai",
@@ -502,7 +502,7 @@ describe("getApiKeyForModel", () => {
};
await expect(
getApiKeyForModel({
getApiKeyForModelCore({
model: {
id: "chat-latest",
provider: "openai",
@@ -528,7 +528,7 @@ describe("getApiKeyForModel", () => {
};
await expect(
getApiKeyForModel({
getApiKeyForModelCore({
model: {
id: "gpt-5.5",
provider: "openai",
+8 -8
View File
@@ -179,7 +179,7 @@ let hasRuntimeAvailableProviderAuth: typeof import("./model-auth.js").hasRuntime
let hasUsableCustomProviderApiKey: typeof import("./model-auth.js").hasUsableCustomProviderApiKey;
let hasSyntheticLocalProviderAuthConfig: typeof import("./model-auth.js").hasSyntheticLocalProviderAuthConfig;
let requireApiKey: typeof import("./model-auth.js").requireApiKey;
let getApiKeyForModel: typeof import("./model-auth.js").getApiKeyForModel;
let getApiKeyForModelCore: typeof import("./model-auth.js").getApiKeyForModelCore;
let resolveApiKeyForProvider: typeof import("./model-auth.js").resolveApiKeyForProvider;
let resolveAwsSdkEnvVarName: typeof import("./model-auth.js").resolveAwsSdkEnvVarName;
let resolveModelAuthMode: typeof import("./model-auth.js").resolveModelAuthMode;
@@ -210,7 +210,7 @@ beforeAll(async () => {
hasAvailableAuthForProvider,
hasRuntimeAvailableProviderAuth,
hasSyntheticLocalProviderAuthConfig,
getApiKeyForModel,
getApiKeyForModelCore,
hasUsableCustomProviderApiKey,
requireApiKey,
resolveApiKeyForProvider,
@@ -1586,7 +1586,7 @@ describe("resolveApiKeyForProvider", () => {
it("preserves explicit subscription modes for literal provider credentials", async () => {
for (const mode of ["oauth", "token"] as const) {
const provider = `custom-${mode}`;
const resolved = await getApiKeyForModel({
const resolved = await getApiKeyForModelCore({
model: {
id: "subscription-model",
provider,
@@ -1617,7 +1617,7 @@ describe("resolveApiKeyForProvider", () => {
it("does not reinterpret explicit OpenAI oauth material as a Platform API key", async () => {
await expect(
getApiKeyForModel({
getApiKeyForModelCore({
model: {
id: "platform-model",
provider: "openai",
@@ -1645,7 +1645,7 @@ describe("resolveApiKeyForProvider", () => {
"OPENCLAW_TEST_PROVIDER_SUBSCRIPTION_TOKEN",
"env-subscription-credential",
async () => {
const resolved = await getApiKeyForModel({
const resolved = await getApiKeyForModelCore({
model: {
id: "subscription-model",
provider: "custom-token-env",
@@ -1758,7 +1758,7 @@ describe("resolveApiKeyForProvider", () => {
sourceConfig,
);
const resolved = await getApiKeyForModel({
const resolved = await getApiKeyForModelCore({
model: {
id: "subscription-model",
provider: "custom-oauth-ref",
@@ -2013,7 +2013,7 @@ describe("resolveApiKeyForProvider synthetic local auth for custom providers
});
it("resolves synthetic auth when model overrides api to ollama within a non-ollama provider", async () => {
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
model: {
id: "my-router/local-llama",
name: "Local Llama",
@@ -2254,7 +2254,7 @@ describe("resolveApiKeyForProvider synthetic local auth for custom providers
});
it("uses implicit aws-sdk auth for built-in Bedrock Converse models", async () => {
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
model: {
id: "us.anthropic.claude-sonnet-4-6-v1",
name: "Claude Sonnet",
+1 -1
View File
@@ -12,7 +12,7 @@ export {
applyAuthHeaderOverride,
applyLocalNoAuthHeaderOverride,
applySecretRefHeaderSentinels,
getApiKeyForModel,
getApiKeyForModelCore,
hasAvailableAuthForProvider,
resolveModelAuthMode,
} from "./model-auth-model.js";
+3 -3
View File
@@ -4,14 +4,14 @@
* the full suppression implementation at module load.
*/
import {
buildShouldSuppressBuiltInModel as buildShouldSuppressBuiltInModelImpl,
buildShouldSuppressBuiltInModelCore,
shouldSuppressBuiltInModel as shouldSuppressBuiltInModelImpl,
} from "./model-suppression.js";
type ShouldSuppressBuiltInModel =
typeof import("./model-suppression.js").shouldSuppressBuiltInModel;
type BuildShouldSuppressBuiltInModel =
typeof import("./model-suppression.js").buildShouldSuppressBuiltInModel;
typeof import("./model-suppression.js").buildShouldSuppressBuiltInModelCore;
/** Runtime-forwarded predicate for hiding bundled models. */
export function shouldSuppressBuiltInModel(
@@ -24,5 +24,5 @@ export function shouldSuppressBuiltInModel(
export function buildShouldSuppressBuiltInModel(
...args: Parameters<BuildShouldSuppressBuiltInModel>
): ReturnType<BuildShouldSuppressBuiltInModel> {
return buildShouldSuppressBuiltInModelImpl(...args);
return buildShouldSuppressBuiltInModelCore(...args);
}
+4 -4
View File
@@ -15,7 +15,7 @@ vi.mock("../plugins/manifest-model-suppression.js", () => ({
import { setCurrentPluginMetadataSnapshotState } from "../plugins/current-plugin-metadata-state.js";
import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js";
import {
buildShouldSuppressBuiltInModel,
buildShouldSuppressBuiltInModelCore,
shouldSuppressBuiltInModel,
} from "./model-suppression.js";
@@ -147,7 +147,7 @@ describe("model suppression", () => {
expect(secondResolver).toHaveBeenCalledOnce();
});
describe("buildShouldSuppressBuiltInModel", () => {
describe("buildShouldSuppressBuiltInModelCore", () => {
beforeEach(() => {
mocks.buildManifestBuiltInModelSuppressionResolver.mockReset();
});
@@ -160,7 +160,7 @@ describe("model suppression", () => {
const config = {};
mocks.buildManifestBuiltInModelSuppressionResolver.mockReturnValueOnce(resolver);
const shouldSuppress = buildShouldSuppressBuiltInModel({ config });
const shouldSuppress = buildShouldSuppressBuiltInModelCore({ config });
expect(shouldSuppress({ provider: "bedrock", id: "Claude-3" })).toBe(true);
expect(shouldSuppress({ provider: "aws-bedrock", id: "claude-4" })).toBe(false);
@@ -183,7 +183,7 @@ describe("model suppression", () => {
const resolver = vi.fn();
mocks.buildManifestBuiltInModelSuppressionResolver.mockReturnValueOnce(resolver);
const shouldSuppress = buildShouldSuppressBuiltInModel({});
const shouldSuppress = buildShouldSuppressBuiltInModelCore({});
expect(shouldSuppress({ provider: "openai", id: "" })).toBe(false);
expect(shouldSuppress({ provider: "", id: "gpt-5.5" })).toBe(false);
+1 -1
View File
@@ -172,7 +172,7 @@ export function buildSuppressedBuiltInModelError(params: {
}
/** Build a reusable suppression predicate for repeated catalog filtering. */
export function buildShouldSuppressBuiltInModel(params: {
export function buildShouldSuppressBuiltInModelCore(params: {
config?: OpenClawConfig;
workspaceDir?: string;
}): (input: { provider?: string | null; id?: string | null; baseUrl?: string | null }) => boolean {
+4 -4
View File
@@ -49,7 +49,7 @@ import {
isLiveRateLimitDrift,
} from "./live-test-provider-drift.test-support.js";
import {
getApiKeyForModel,
getApiKeyForModelCore,
requireApiKey,
resolveUsableCustomProviderApiKey,
} from "./model-auth.js";
@@ -487,7 +487,7 @@ async function resolveLiveModelApiKeyInfo(params: {
model: Model;
cfg: OpenClawConfig;
requireProfileKeys: boolean;
}): Promise<Awaited<ReturnType<typeof getApiKeyForModel>>> {
}): Promise<Awaited<ReturnType<typeof getApiKeyForModelCore>>> {
if (isLiveLocalOllamaModel(params.model, params.cfg)) {
const configuredKey = canReuseConfiguredLocalOllamaApiKey(params.model, params.cfg)
? resolveUsableCustomProviderApiKey({
@@ -508,7 +508,7 @@ async function resolveLiveModelApiKeyInfo(params: {
mode: "api-key",
};
}
return await getApiKeyForModel({
return await getApiKeyForModelCore({
model: params.model,
cfg: params.cfg,
credentialPrecedence: resolveLiveCredentialPrecedence(
@@ -1829,7 +1829,7 @@ describeLive("live models (profile keys)", () => {
const skipped: Array<{ model: string; reason: string }> = [];
const candidates: Array<{
model: Model;
apiKeyInfo: Awaited<ReturnType<typeof getApiKeyForModel>>;
apiKeyInfo: Awaited<ReturnType<typeof getApiKeyForModelCore>>;
}> = [];
for (const model of models) {
@@ -16,7 +16,7 @@ import {
readLiveTestConfig,
resolveLiveCredentialPrecedence,
} from "./live-test-helpers.js";
import { getApiKeyForModel, requireApiKey } from "./model-auth.js";
import { getApiKeyForModelCore, requireApiKey } from "./model-auth.js";
import { ensureOpenClawModelsJson } from "./models-config.js";
const LIVE = isLiveTestEnabled();
@@ -118,7 +118,7 @@ describeLive("openai reasoning compat live", () => {
let apiKeyInfo;
try {
apiKeyInfo = await getApiKeyForModel({
apiKeyInfo = await getApiKeyForModelCore({
model,
cfg,
credentialPrecedence: resolveLiveCredentialPrecedence(
@@ -178,7 +178,7 @@ describeLive("openai reasoning compat live", () => {
let apiKeyInfo;
try {
apiKeyInfo = await getApiKeyForModel({
apiKeyInfo = await getApiKeyForModelCore({
model,
cfg,
credentialPrecedence: resolveLiveCredentialPrecedence(
+2 -2
View File
@@ -14,7 +14,7 @@ import { isEmbeddedMode } from "../infra/embedded-mode.js";
import { formatErrorMessage } from "../infra/errors.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { getActiveSecretsRuntimeConfigSnapshot } from "../secrets/runtime-state.js";
import { getActiveRuntimeWebToolsMetadata } from "../secrets/runtime-web-tools-state.js";
import { getActiveRuntimeWebToolsMetadataFromState } from "../secrets/runtime-web-tools-state.js";
import { isCronRunSessionKey } from "../sessions/session-key-utils.js";
import type { SkillWorkshopRunOptions } from "../skills/workshop/types.js";
import { resolveTranscriptsConfig } from "../transcripts/config.js";
@@ -265,7 +265,7 @@ export function createOpenClawTools(
// Scheduled turns keep delivery routing live, but Gateway authorization remains bound to the
// authenticated creator account captured in the immutable scheduled authority envelope.
const gatewayCallerAccountId = options?.gatewayCallerAccountId ?? options?.agentAccountId;
const runtimeWebTools = getActiveRuntimeWebToolsMetadata();
const runtimeWebTools = getActiveRuntimeWebToolsMetadataFromState();
const sandbox =
options?.sandboxRoot && options?.sandboxFsBridge
? { root: options.sandboxRoot, bridge: options.sandboxFsBridge }
@@ -181,7 +181,7 @@ vi.mock("./auth-profiles/runtime-materializations.js", () => ({
}));
vi.mock("./auth-profiles/runtime-snapshots.js", () => ({
getPreparedRuntimeAuthProfileStoreSnapshot: () => preparedModelRuntimeMocks.preparedAuthStore,
getPreparedRuntimeAuthProfileStoreSnapshotCore: () => preparedModelRuntimeMocks.preparedAuthStore,
getRuntimeAuthProfileStoreSnapshot: () => preparedModelRuntimeMocks.preparedAuthStore,
getRuntimeAuthProfileStoreSnapshotRevision: () => 0,
registerRuntimeAuthProfileStoreMutationListener: (
+3 -3
View File
@@ -3,7 +3,7 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
import type { Model } from "../../llm/types.js";
import type { AuthProfileStore } from "../auth-profiles.js";
import { resolveAgentHarnessPreparedAuthSupport } from "../harness/support.js";
import { getApiKeyForModel } from "../model-auth.js";
import { getApiKeyForModelCore } from "../model-auth.js";
import {
agentRuntimeAuthPlanMatchesTarget,
canRunPreparedAgentRuntimeAuthAttempt,
@@ -1219,7 +1219,7 @@ describe("prepareAgentRuntimeAuthPlan", () => {
maxTokens: 128_000,
} as Model;
const profileAttempt = prepared.attempts[0];
const profileResolved = await getApiKeyForModel({
const profileResolved = await getApiKeyForModelCore({
model,
cfg: config,
profileId: profileAttempt?.profileId,
@@ -1417,7 +1417,7 @@ describe("prepareAgentRuntimeAuthPlan", () => {
},
});
const resolved = await getApiKeyForModel({
const resolved = await getApiKeyForModelCore({
model: {
id: "gpt-5.5",
name: "GPT-5.5",
+8 -8
View File
@@ -4,7 +4,7 @@ import { SecretSurfaceUnavailableError } from "../../secrets/runtime-degraded-st
import { OAuthRefreshFailureError } from "../auth-profiles/oauth-refresh-failure.js";
import type { AuthProfileStore } from "../auth-profiles/types.js";
import { isProfileInCooldown } from "../auth-profiles/usage-state.js";
import { getApiKeyForModel } from "../model-auth.js";
import { getApiKeyForModelCore } from "../model-auth.js";
import { providerModelRouteAcceptsAuthMode } from "../provider-model-route-auth.js";
import { shouldForceDirectAuthFallbackModelResolve } from "./credential-scoped-model.js";
import { sameAgentRuntimeAuthModelRoute } from "./model-route.js";
@@ -16,7 +16,7 @@ import {
import type { AgentRuntimeAuthPlan } from "./types.js";
type PreparedRuntimeModelAuthResolution = Readonly<{
auth: Awaited<ReturnType<typeof getApiKeyForModel>>;
auth: Awaited<ReturnType<typeof getApiKeyForModelCore>>;
plan: AgentRuntimeAuthPlan;
}>;
@@ -212,7 +212,7 @@ export function scopeAuthProfileStoreToPreparedPlan(
function applyResolvedAuthToPlan(params: {
plan: AgentRuntimeAuthPlan;
auth: Awaited<ReturnType<typeof getApiKeyForModel>>;
auth: Awaited<ReturnType<typeof getApiKeyForModelCore>>;
candidates: string[];
}): AgentRuntimeAuthPlan {
const profileId = params.auth.profileId?.trim();
@@ -242,7 +242,7 @@ function applyResolvedAuthToPlan(params: {
function assertResolvedAuthMatchesPreparedRoute(params: {
plan: AgentRuntimeAuthPlan;
auth: Awaited<ReturnType<typeof getApiKeyForModel>>;
auth: Awaited<ReturnType<typeof getApiKeyForModelCore>>;
}): void {
const route = params.plan.modelRoute;
if (
@@ -261,7 +261,7 @@ function assertResolvedAuthMatchesPreparedRoute(params: {
/** Resolves prepared same-route candidates without pinning the first unresolved profile. */
export async function resolvePreparedRuntimeModelAuth(
params: Omit<Parameters<typeof getApiKeyForModel>[0], "profileId"> & {
params: Omit<Parameters<typeof getApiKeyForModelCore>[0], "profileId"> & {
plan: AgentRuntimeAuthPlan;
},
): Promise<PreparedRuntimeModelAuthResolution> {
@@ -275,7 +275,7 @@ export async function resolvePreparedRuntimeModelAuth(
if (candidates.length === 0) {
// The planner selected direct auth. Resolve only env/config material so an
// unrelated full store cannot replace or pre-reject that immutable source.
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
...authParams,
store: { version: 1, profiles: {} },
lockedProfile: false,
@@ -286,7 +286,7 @@ export async function resolvePreparedRuntimeModelAuth(
return { auth, plan: applyResolvedAuthToPlan({ plan, auth, candidates }) };
}
if (plan.forwardedAuthProfileSource !== "auto") {
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
...authParams,
profileId: plan.forwardedAuthProfileId,
lockedProfile: Boolean(plan.forwardedAuthProfileId),
@@ -314,7 +314,7 @@ export async function resolvePreparedRuntimeModelAuth(
let refreshFailure: OAuthRefreshFailureError | undefined;
for (const profileId of currentCandidates) {
try {
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
...authParams,
profileId,
// This loop owns fallback order. Pin each lookup so the generic auth
+3 -3
View File
@@ -26,7 +26,7 @@ import {
} from "../auth-profiles/legacy-source-diagnostic.js";
import { resolveOAuthRefreshLockPath } from "../auth-profiles/paths.js";
import { loadPersistedAuthProfileStore } from "../auth-profiles/persisted.js";
import { getRuntimeAuthProfileStoreSnapshot } from "../auth-profiles/runtime-snapshots.js";
import { getRuntimeAuthProfileStoreSnapshotCore } from "../auth-profiles/runtime-snapshots.js";
import {
inspectPersistedAuthProfileStateRaw,
inspectPersistedAuthProfileStoreRaw,
@@ -297,7 +297,7 @@ class SqliteAuthStorageBackend implements AuthStorageBackend {
) {}
private resolveMaterializedRuntimeStores(): AuthProfileStore[] {
const current = getRuntimeAuthProfileStoreSnapshot(this.agentDir);
const current = getRuntimeAuthProfileStoreSnapshotCore(this.agentDir);
// A current lifecycle snapshot is authoritative, including an unresolved
// ref after failed/revoked secrets reload. Prepared data is bootstrap-only.
return current ? [current] : this.preparedStore ? [this.preparedStore] : [];
@@ -446,7 +446,7 @@ export class AuthStorage {
static forAgent(agentDir: string = getAgentDir()): AuthStorage {
assertAuthProfileMigrationReady(agentDir);
const preparedStore =
getRuntimeAuthProfileStoreSnapshot(agentDir) ??
getRuntimeAuthProfileStoreSnapshotCore(agentDir) ??
loadAuthProfileStoreForSecretsRuntime(agentDir);
assertAuthStorageSecretRefsMaterialized(preparedStore);
return new AuthStorage(new SqliteAuthStorageBackend(agentDir, preparedStore), agentDir);
+2 -2
View File
@@ -70,7 +70,7 @@ vi.mock("./model-auth.js", () => ({
(auth: { source: string; mode: string }, provider: string) =>
`No API key resolved for provider "${provider}" (auth mode: ${auth.mode}, checked: ${auth.source}).`,
),
getApiKeyForModel: hoisted.getApiKeyForModelMock,
getApiKeyForModelCore: hoisted.getApiKeyForModelMock,
resolveApiKeyForProvider: hoisted.getApiKeyForModelMock,
applyLocalNoAuthHeaderOverride: hoisted.applyLocalNoAuthHeaderOverrideMock,
}));
@@ -478,7 +478,7 @@ describe("prepareSimpleCompletionModel", () => {
expect(result.model.baseUrl).toBe("https://api.copilot.enterprise.example");
});
it("returns error when getApiKeyForModel throws", async () => {
it("returns error when getApiKeyForModelCore throws", async () => {
hoisted.getApiKeyForModelMock.mockRejectedValueOnce(new Error("Profile not found: copilot"));
const result = await prepareSimpleCompletionModel({
+3 -3
View File
@@ -35,7 +35,7 @@ import {
applySecretRefHeaderSentinels,
applyLocalNoAuthHeaderOverride,
formatMissingAuthError,
getApiKeyForModel,
getApiKeyForModelCore,
resolveApiKeyForProvider,
type ResolvedProviderAuth,
} from "./model-auth.js";
@@ -306,7 +306,7 @@ export async function prepareSimpleCompletionModel(params: {
modelId: initialModel.id,
secretSentinels: true,
})
: await getApiKeyForModel({
: await getApiKeyForModelCore({
model: initialModel,
cfg: params.cfg,
agentDir: params.agentDir,
@@ -396,7 +396,7 @@ export async function prepareSimpleCompletionModel(params: {
),
})) ?? initialModel;
if (resolvesAuthBeforePhysicalRoute) {
auth = await getApiKeyForModel({
auth = await getApiKeyForModelCore({
model: resolvedModel,
cfg: params.cfg,
agentDir: params.agentDir,
+3 -3
View File
@@ -20,7 +20,7 @@ import {
resolveLiveCredentialPrecedence,
type CompleteSimpleContent,
} from "./live-test-helpers.js";
import { getApiKeyForModel, requireApiKey } from "./model-auth.js";
import { getApiKeyForModelCore, requireApiKey } from "./model-auth.js";
import { ensureOpenClawModelsJson } from "./models-config.js";
import { transformTransportMessages } from "./transport-message-transform.js";
@@ -261,7 +261,7 @@ describeLive("tool replay repair live", () => {
let apiKeyInfo;
try {
apiKeyInfo = await getApiKeyForModel({
apiKeyInfo = await getApiKeyForModelCore({
model,
cfg,
credentialPrecedence: resolveLiveCredentialPrecedence(
@@ -374,7 +374,7 @@ describeLive("tool replay repair live", () => {
let apiKeyInfo;
try {
apiKeyInfo = await getApiKeyForModel({
apiKeyInfo = await getApiKeyForModelCore({
model,
cfg,
credentialPrecedence: resolveLiveCredentialPrecedence(
@@ -7,7 +7,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import type { ModelDefinitionConfig } from "../../config/types.models.js";
import type { ImageDescriptionRequest } from "../../plugin-sdk/media-understanding.js";
import { getApiKeyForModel, hasUsableCustomProviderApiKey } from "../model-auth.js";
import { getApiKeyForModelCore, hasUsableCustomProviderApiKey } from "../model-auth.js";
import { resolveImageToolFactoryAvailable } from "../openclaw-tools.media-factory-plan.js";
import { createImageTool } from "./image-tool.js";
import { resolveImageModelConfigForTool, testing } from "./image-tool.test-support.js";
@@ -195,7 +195,7 @@ describe("image custom provider auth regression", () => {
// but execution still resolves the config-backed image-model key.
await withEmptyAgentDir(async (agentDir) => {
const cfg = createUserReportedConfig();
const auth = await getApiKeyForModel({
const auth = await getApiKeyForModelCore({
model: {
id: USER_MODEL,
name: USER_MODEL,
+8 -4
View File
@@ -16,7 +16,7 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
import type { SsrFPolicy } from "../../infra/net/ssrf.js";
import type { Model } from "../../llm/types.js";
import { resolveChannelInboundAttachmentRootsForChannel } from "../../media/channel-inbound-roots.js";
import { getDefaultLocalRoots } from "../../media/local-media-access.js";
import { getDefaultLocalRootsCore } from "../../media/local-media-access.js";
import { readSnakeCaseParamRaw } from "../../param-key.js";
import { loadCapabilityManifestSnapshot } from "../../plugins/capability-provider-runtime.js";
import { listAvailableManifestContractValues } from "../../plugins/manifest-contract-eligibility.js";
@@ -45,7 +45,11 @@ import {
resolveDefaultModelRef,
type ToolModelConfig,
} from "./model-config.helpers.js";
import { getApiKeyForModel, normalizeWorkspaceDir, requireApiKey } from "./tool-runtime.helpers.js";
import {
getApiKeyForModelCore,
normalizeWorkspaceDir,
requireApiKey,
} from "./tool-runtime.helpers.js";
type TextToolAttempt = {
provider: string;
@@ -597,7 +601,7 @@ export function resolveMediaToolLocalRoots(
}
// Channel inbound attachment roots stay separate: those paths are scoped to inbound media
// access, not broad host-local file reads.
const roots = getDefaultLocalRoots();
const roots = getDefaultLocalRootsCore();
return uniqueStrings([...roots, ...(workspaceDir ? [workspaceDir] : [])]);
}
@@ -730,7 +734,7 @@ export async function resolveModelRuntimeApiKey(params: {
setRuntimeApiKey: (provider: string, apiKey: string) => void;
};
}): Promise<string> {
const apiKeyInfo = await getApiKeyForModel({
const apiKeyInfo = await getApiKeyForModelCore({
model: params.model,
cfg: params.cfg,
agentDir: params.agentDir,
+1 -1
View File
@@ -110,7 +110,7 @@ export function createPdfToolInfraStub(completeMock: Mock) {
wrote: false,
});
vi.spyOn(modelAuth, "getApiKeyForModel").mockResolvedValue({ apiKey: "test-key" } as never);
vi.spyOn(modelAuth, "getApiKeyForModelCore").mockResolvedValue({ apiKey: "test-key" } as never);
vi.spyOn(modelAuth, "requireApiKey").mockReturnValue("test-key");
return { loadSpy, release, setRuntimeApiKey };
+2 -2
View File
@@ -330,7 +330,7 @@ describe("createPdfTool", () => {
const [, loadOptions] = firstMockCall(loadSpy, "loadWebMediaRaw");
expectFields(loadOptions, { maxBytes: 524_288 });
expect(modelAuth.getApiKeyForModel).toHaveBeenCalledWith(
expect(modelAuth.getApiKeyForModelCore).toHaveBeenCalledWith(
expect.objectContaining({ secretSentinels: true }),
);
});
@@ -833,7 +833,7 @@ describe("createPdfTool", () => {
api: "bedrock-converse-stream",
input: ["text", "image"],
});
vi.mocked(modelAuth.getApiKeyForModel).mockResolvedValue({
vi.mocked(modelAuth.getApiKeyForModelCore).mockResolvedValue({
apiKey: "",
source: "aws-sdk default chain",
mode: "aws-sdk",
+1 -1
View File
@@ -4,7 +4,7 @@
* Tools import from this module when they need model auth, fallback, discovery,
* sandbox media paths, or workspace helpers without depending on broad agent barrels.
*/
export { getApiKeyForModel, requireApiKey } from "../model-auth.js";
export { getApiKeyForModelCore, requireApiKey } from "../model-auth.js";
export { runWithImageModelFallback } from "../model-fallback-image.js";
export {
createSandboxBridgeReadFile,
@@ -25,7 +25,7 @@ vi.mock("../../secrets/runtime-state.js", () => ({
getActiveSecretsRuntimeConfigSnapshot: () => runtimeState.activeSecretsRuntimeSnapshot,
}));
vi.mock("../../secrets/runtime-web-tools-state.js", () => ({
getActiveRuntimeWebToolsMetadata: () => runtimeState.activeRuntimeWebToolsMetadata,
getActiveRuntimeWebToolsMetadataFromState: () => runtimeState.activeRuntimeWebToolsMetadata,
}));
describe("web_fetch provider fallback normalization", () => {
@@ -7,7 +7,7 @@ import { createWebSearchTool } from "./web-search.js";
const mocks = vi.hoisted(() => ({
runWebSearch: vi.fn(),
resolveManifestContractOwnerPluginId: vi.fn(),
getActiveRuntimeWebToolsMetadata: vi.fn(),
getActiveRuntimeWebToolsMetadataFromState: vi.fn(),
getActiveSecretsRuntimeConfigSnapshot: vi.fn(),
}));
@@ -21,7 +21,7 @@ vi.mock("../../plugins/plugin-registry.js", () => ({
}));
vi.mock("../../secrets/runtime-web-tools-state.js", () => ({
getActiveRuntimeWebToolsMetadata: mocks.getActiveRuntimeWebToolsMetadata,
getActiveRuntimeWebToolsMetadataFromState: mocks.getActiveRuntimeWebToolsMetadataFromState,
}));
vi.mock("../../secrets/runtime-state.js", () => ({
@@ -49,8 +49,8 @@ describe("web_search late-bound runtime fallback", () => {
});
mocks.resolveManifestContractOwnerPluginId.mockReset();
mocks.resolveManifestContractOwnerPluginId.mockReturnValue(undefined);
mocks.getActiveRuntimeWebToolsMetadata.mockReset();
mocks.getActiveRuntimeWebToolsMetadata.mockReturnValue(null);
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReset();
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReturnValue(null);
mocks.getActiveSecretsRuntimeConfigSnapshot.mockReset();
mocks.getActiveSecretsRuntimeConfigSnapshot.mockReturnValue(null);
});
@@ -136,7 +136,7 @@ describe("web_search late-bound runtime fallback", () => {
it("prefers active runtime metadata over options.runtimeWebSearch when present", async () => {
// Active runtime metadata reflects the newest credential snapshot; fallback
// options only cover tools created before that state exists.
mocks.getActiveRuntimeWebToolsMetadata.mockReturnValue({
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReturnValue({
search: {
selectedProvider: "perplexity",
providerConfigured: "perplexity",
@@ -7,7 +7,7 @@ import {
} from "./web-tool-runtime-context.js";
const mocks = vi.hoisted(() => ({
getActiveRuntimeWebToolsMetadata: vi.fn(),
getActiveRuntimeWebToolsMetadataFromState: vi.fn(),
getActiveSecretsRuntimeConfigSnapshot: vi.fn(),
resolveManifestContractOwnerPluginId: vi.fn(),
}));
@@ -17,7 +17,7 @@ vi.mock("../../plugins/plugin-registry.js", () => ({
}));
vi.mock("../../secrets/runtime-web-tools-state.js", () => ({
getActiveRuntimeWebToolsMetadata: mocks.getActiveRuntimeWebToolsMetadata,
getActiveRuntimeWebToolsMetadataFromState: mocks.getActiveRuntimeWebToolsMetadataFromState,
}));
vi.mock("../../secrets/runtime-state.js", () => ({
@@ -36,8 +36,8 @@ function latestOwnerLookupParams(): Record<string, unknown> {
describe("web tool runtime context", () => {
beforeEach(() => {
mocks.getActiveRuntimeWebToolsMetadata.mockReset();
mocks.getActiveRuntimeWebToolsMetadata.mockReturnValue(null);
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReset();
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReturnValue(null);
mocks.getActiveSecretsRuntimeConfigSnapshot.mockReset();
mocks.getActiveSecretsRuntimeConfigSnapshot.mockReturnValue(null);
mocks.resolveManifestContractOwnerPluginId.mockReset();
@@ -49,7 +49,7 @@ describe("web tool runtime context", () => {
tools: { web: { search: { provider: "perplexity" } } },
};
mocks.getActiveSecretsRuntimeConfigSnapshot.mockReturnValue({ config: runtimeConfig });
mocks.getActiveRuntimeWebToolsMetadata.mockReturnValue({
mocks.getActiveRuntimeWebToolsMetadataFromState.mockReturnValue({
search: {
providerConfigured: "perplexity",
providerSource: "configured",
+2 -2
View File
@@ -6,7 +6,7 @@
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolveManifestContractOwnerPluginId } from "../../plugins/plugin-registry.js";
import { getActiveSecretsRuntimeConfigSnapshot } from "../../secrets/runtime-state.js";
import { getActiveRuntimeWebToolsMetadata } from "../../secrets/runtime-web-tools-state.js";
import { getActiveRuntimeWebToolsMetadataFromState } from "../../secrets/runtime-web-tools-state.js";
import type {
RuntimeWebFetchMetadata,
RuntimeWebSearchMetadata,
@@ -61,7 +61,7 @@ function resolveWebToolRuntimeContext<TMetadata extends WebProviderRuntimeMetada
lateBindRuntimeConfig?: boolean;
}): ResolvedWebToolRuntimeContext<TMetadata> {
const activeWebTools =
params.lateBindRuntimeConfig === true ? getActiveRuntimeWebToolsMetadata() : null;
params.lateBindRuntimeConfig === true ? getActiveRuntimeWebToolsMetadataFromState() : null;
// Late-bound metadata wins over constructor-captured metadata for long-lived tool instances.
const runtimeMetadata = (activeWebTools?.[params.kind] ?? params.capturedRuntimeMetadata) as
| TMetadata
@@ -47,7 +47,7 @@ vi.mock("../../secrets/runtime-state.js", () => ({
vi.mock("../../web-search/runtime.js", async () => {
const { getActivePluginRegistry } = await import("../../plugins/runtime.js");
const { getActiveRuntimeWebToolsMetadata } =
const { getActiveRuntimeWebToolsMetadataFromState } =
await import("../../secrets/runtime-web-tools-state.js");
const resolveRuntimeDefinition = (options?: {
config?: unknown;
@@ -58,8 +58,8 @@ vi.mock("../../web-search/runtime.js", async () => {
const providerId =
options?.runtimeWebSearch?.selectedProvider ??
options?.runtimeWebSearch?.providerConfigured ??
getActiveRuntimeWebToolsMetadata()?.search?.selectedProvider ??
getActiveRuntimeWebToolsMetadata()?.search?.providerConfigured ??
getActiveRuntimeWebToolsMetadataFromState()?.search?.selectedProvider ??
getActiveRuntimeWebToolsMetadataFromState()?.search?.providerConfigured ??
readConfiguredSearchProvider(options?.config);
const registration = getActivePluginRegistry()?.webSearchProviders.find(
(entry) => entry.provider.id === providerId,
+1 -1
View File
@@ -134,7 +134,7 @@ vi.mock("../../config/runtime-schema.js", async () => {
const actual =
await vi.importActual<typeof import("../../config/schema.js")>("../../config/schema.js");
return {
loadGatewayRuntimeConfigSchema: () => actual.buildConfigSchema(),
loadGatewayRuntimeConfigSchema: () => actual.buildConfigSchemaCore(),
};
});
+2 -2
View File
@@ -7,7 +7,7 @@ import {
} from "../../config/mcp-config.js";
import { redactSensitiveArgv } from "../../config/redact-argv.js";
import { REDACTED_SENTINEL, redactConfigObject } from "../../config/redact-snapshot.js";
import { buildConfigSchema } from "../../config/schema.js";
import { buildConfigSchemaCore } from "../../config/schema.js";
import type { ExecApprovalRequest } from "../../infra/exec-approvals.js";
import type { ReplyPayload } from "../types.js";
import {
@@ -56,7 +56,7 @@ function redactMcpServersForDisplay(servers: Record<string, unknown>): Record<st
);
const redactedRoot = redactConfigObject(
{ mcp: { servers: argvRedacted } },
buildConfigSchema().uiHints,
buildConfigSchemaCore().uiHints,
) as {
mcp?: { servers?: Record<string, unknown> };
};
+2 -2
View File
@@ -3,7 +3,7 @@ import { normalizeOptionalString } from "@openclaw/normalization-core/string-coe
import { normalizeChatType } from "../../../channels/chat-type.js";
import { logMessageQueuedWithBacklogPolicy } from "../../../logging/diagnostic-runtime.js";
import { channelRouteDedupeKey } from "../../../plugin-sdk/channel-route.js";
import { createDeferred } from "../../../shared/deferred.js";
import { createDeferredCore } from "../../../shared/deferred.js";
import {
applyQueueDropPolicy,
countPendingQueueItems,
@@ -159,7 +159,7 @@ export function enqueueFollowupRun(
if (!markFollowupRunEnqueued(run)) {
return false;
}
const { promise: acceptance, resolve: settle } = createDeferred<boolean>();
const { promise: acceptance, resolve: settle } = createDeferredCore<boolean>();
run.steerPending = { predecessor: queue.steerAcceptanceTail, settle };
queue.steerAcceptanceTail = acceptance;
appendQueueItem({
@@ -1,5 +1,5 @@
import { normalizeStringifiedEntries } from "@openclaw/normalization-core/string-coerce";
import { createDeferred } from "../../shared/deferred.js";
import { createDeferredCore } from "../../shared/deferred.js";
import { resolveGlobalMap } from "../../shared/global-singleton.js";
export const REPLY_ADMISSION_TICKET = Symbol("openclaw.replyAdmissionTicket");
@@ -21,7 +21,7 @@ export function reserveReplyAdmissionTicket(
if (keys.length === 0) {
return undefined;
}
const { promise: completed, resolve: finish } = createDeferred();
const { promise: completed, resolve: finish } = createDeferredCore();
const predecessors = keys.map((key) => tails.get(key) ?? Promise.resolve());
const owned = keys.map((key, index) => {
const tail = predecessors[index]!.then(() => completed);
@@ -1,5 +1,5 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { createDeferred } from "../../shared/deferred.js";
import { createDeferredCore } from "../../shared/deferred.js";
import {
replyMessageInjectionTargetOperation,
type ReplyBackendHandle,
@@ -151,7 +151,7 @@ export function beginReplyMessageInjectionTarget(
// sub-10-minute user messages re-arm a wedged run's staleness window forever.
// Invoke before the first await. The capability owns the final synchronous
// admission check, matching Codex's active-turn lock boundary.
const acceptance = createDeferred<boolean>();
const acceptance = createDeferredCore<boolean>();
let acceptanceSettled = false;
const settleAcceptance = (accepted: boolean) => {
if (acceptanceSettled) {
@@ -6,7 +6,7 @@ import {
import { createAbortError } from "../../infra/abort-signal.js";
import { getAgentEventLifecycleGeneration } from "../../infra/agent-events.js";
import { diagnosticLogger as diag } from "../../logging/diagnostic-runtime.js";
import { createDeferred } from "../../shared/deferred.js";
import { createDeferredCore } from "../../shared/deferred.js";
import type { ReplyFollowupAdmissionBarrierTimeoutPolicy } from "./reply-dispatcher.types.js";
import * as replyRunSettle from "./reply-run-finalization-lease.js";
import {
@@ -94,7 +94,7 @@ export function createReplyOperation(params: {
let retainFailureUntilComplete = false;
let terminalRecovery = false;
let acceptedSteeredInboundAudio = false;
const ownerSettlement = createDeferred();
const ownerSettlement = createDeferredCore();
let ownerSettled = false;
const settleOwner = () => {
if (ownerSettled) {
@@ -5,7 +5,7 @@ import {
markDiagnosticRunProgress,
resolveRunStaleThresholdMs,
} from "../../logging/diagnostic-run-activity.js";
import { createDeferred } from "../../shared/deferred.js";
import { createDeferredCore } from "../../shared/deferred.js";
import { resolveGlobalSingleton } from "../../shared/global-singleton.js";
import { resolveTimerTimeoutMs } from "../../shared/number-coercion.js";
import type { ReplyFollowupAdmissionBarrierTimeoutPolicy } from "./reply-dispatcher.types.js";
@@ -229,7 +229,7 @@ export function registerReplyOperationSuccessorBarrier(params: {
sessionKeys: readonly string[];
start: () => PromiseLike<unknown>;
}): void {
const settlement = createDeferred();
const settlement = createDeferredCore();
const barriers = new Set<ReplyRunAdmissionBarrier>();
for (const sessionKey of new Set(params.sessionKeys.map(normalizeOptionalString))) {
if (sessionKey) {
+2 -5
View File
@@ -18,10 +18,7 @@ import type {
StreamingMode,
TextChunkMode,
} from "../config/types.base.js";
import {
DEFAULT_PROGRESS_DRAFT_LABELS as SHARED_PROGRESS_DRAFT_LABELS,
selectProgressLabel,
} from "../shared/progress-labels.js";
import { DEFAULT_PROGRESS_DRAFT_LABELS, selectProgressLabel } from "../shared/progress-labels.js";
import { asBoolean } from "../utils/boolean.js";
import {
getChannelStreamingConfigObject,
@@ -81,7 +78,7 @@ function asCommandTextMode(value: unknown): ChannelStreamingCommandTextMode | un
return value === "raw" || value === "status" ? value : undefined;
}
export const DEFAULT_PROGRESS_DRAFT_LABELS = SHARED_PROGRESS_DRAFT_LABELS;
export { DEFAULT_PROGRESS_DRAFT_LABELS } from "../shared/progress-labels.js";
// Short enough that a multi-tool turn is never silent, long enough that a
// quick answer posts no draft at all: the gate only creates the draft when the
+2 -2
View File
@@ -11,7 +11,7 @@ import {
import type { ProgramContext } from "./context.js";
import {
getCoreCliCommandDescriptors,
getCoreCliCommandNames as getCoreDescriptorNames,
getCoreCliCommandNamesCore,
} from "./core-command-descriptors.js";
import {
registerCommandGroupByName,
@@ -157,7 +157,7 @@ function resolveCoreCommandGroups(ctx: ProgramContext, argv: string[]): CommandG
}
export function getCoreCliCommandNames(): string[] {
return getCoreDescriptorNames();
return getCoreCliCommandNamesCore();
}
export async function registerCoreCliByName(
+4 -4
View File
@@ -1,7 +1,7 @@
import { levenshteinDistance } from "../../shared/levenshtein-distance.js";
import { formatCliCommand } from "../command-format.js";
import { getCoreCliCommandNames } from "./core-command-descriptors.js";
import { getSubCliEntries } from "./subcli-descriptors.js";
import { getCoreCliCommandNamesCore } from "./core-command-descriptors.js";
import { getSubCliEntriesCore } from "./subcli-descriptors.js";
const EXPLICIT_COMMAND_ALIASES = new Map<string, string>([
["upgrade", "update"],
@@ -23,8 +23,8 @@ export function formatCliCommandSuggestions(input: string): string | undefined {
}
const knownCommands = uniqueSortedCommandNames([
...getCoreCliCommandNames(),
...getSubCliEntries().map((entry) => entry.name),
...getCoreCliCommandNamesCore(),
...getSubCliEntriesCore().map((entry) => entry.name),
]);
const explicitAlias = EXPLICIT_COMMAND_ALIASES.get(normalizedInput);
if (explicitAlias && knownCommands.includes(explicitAlias)) {
+1 -1
View File
@@ -148,7 +148,7 @@ export function getCoreCliCommandDescriptors(): ReadonlyArray<CoreCliCommandDesc
}
/** Return names for all core root commands. */
export function getCoreCliCommandNames(): string[] {
export function getCoreCliCommandNamesCore(): string[] {
return visibleCoreCliCommandDescriptors().map((descriptor) => descriptor.name);
}
+3 -6
View File
@@ -19,10 +19,7 @@ import {
registerCommandGroups,
type CommandGroupEntry,
} from "./register-command-groups.js";
import {
getSubCliEntries as getSubCliEntryDescriptors,
type SubCliDescriptor,
} from "./subcli-descriptors.js";
import { getSubCliEntriesCore, type SubCliDescriptor } from "./subcli-descriptors.js";
export type SubCliRegistrationContext = {
purpose?: "runtime" | "completion";
@@ -317,7 +314,7 @@ function resolveSubCliCommandGroups(
argv: string[],
context: SubCliRegistrationContext = {},
): CommandGroupEntry[] {
const descriptors = getSubCliEntryDescriptors();
const descriptors = getSubCliEntriesCore();
const descriptorNames = new Set(descriptors.map((descriptor) => descriptor.name));
return buildCommandGroupEntries(
descriptors,
@@ -329,7 +326,7 @@ function resolveSubCliCommandGroups(
}
export function getSubCliEntries(): ReadonlyArray<SubCliDescriptor> {
return getSubCliEntryDescriptors();
return getSubCliEntriesCore();
}
export async function registerSubCliByNameCore(
+1 -1
View File
@@ -20,7 +20,7 @@ import {
registerSubCliCommandsCore,
type SubCliRegistrationContext,
} from "./register.subclis-core.js";
import { getSubCliEntries as getSubCliEntryDescriptors } from "./subcli-descriptors.js";
import { getSubCliEntriesCore as getSubCliEntryDescriptors } from "./subcli-descriptors.js";
type SubCliRegistrar = (
program: Command,
@@ -9,7 +9,7 @@ import { getCoreCliCommandNames, registerCoreCliByName } from "./command-registr
import { createProgramContext } from "./context.js";
import { getCoreCliCommandDescriptors } from "./core-command-descriptors.js";
import { registerSubCliByName, registerSubCliCommands } from "./register.subclis.js";
import { getSubCliEntries } from "./subcli-descriptors.js";
import { getSubCliEntriesCore } from "./subcli-descriptors.js";
const RESERVED_CATALOG_ROOTS = {
tool: "reserved so plugin registration cannot claim this unregistered root",
@@ -233,7 +233,7 @@ async function registerAllBuiltInCommands(): Promise<Command> {
for (const name of getCoreCliCommandNames()) {
await registerCoreCliByName(program, ctx, name, argv);
}
for (const entry of getSubCliEntries()) {
for (const entry of getSubCliEntriesCore()) {
await registerSubCliByName(program, entry.name, argv, { purpose: "completion" });
}
return program;
@@ -295,7 +295,7 @@ describe("root command descriptions", () => {
}
}
const descriptors = [...getCoreCliCommandDescriptors(), ...getSubCliEntries()];
const descriptors = [...getCoreCliCommandDescriptors(), ...getSubCliEntriesCore()];
const missing: string[] = [];
const mismatches: string[] = [];
for (const descriptor of descriptors) {
+1 -1
View File
@@ -38,7 +38,7 @@ vi.mock("./subcli-descriptors.js", () => ({
hasSubcommands: true,
},
],
getSubCliEntries: () => [
getSubCliEntriesCore: () => [
{
name: "config",
description: "Manage config",
+2 -2
View File
@@ -10,7 +10,7 @@ import {
} from "./command-descriptor-utils.js";
import { getCoreCliCommandDescriptors } from "./core-command-descriptors.js";
import { configureProgramHelp, formatProgramHelpOutput } from "./help.js";
import { getSubCliEntries } from "./subcli-descriptors.js";
import { getSubCliEntriesCore } from "./subcli-descriptors.js";
/** Options for rendering root help without fully registering the live CLI. */
export type RootHelpRenderOptions = Pick<PluginLoadOptions, "pluginSdkResolution"> & {
@@ -48,7 +48,7 @@ async function buildRootHelpProgram(renderOptions?: RootHelpRenderOptions): Prom
program,
collectUniqueCommandDescriptors([
getCoreCliCommandDescriptors(),
getSubCliEntries(),
getSubCliEntriesCore(),
pluginDescriptors,
]),
);
+4 -4
View File
@@ -45,10 +45,10 @@ describe("sub-cli descriptors", () => {
it("keeps the exported descriptor list aligned with private QA visibility when disabled (#83927)", async () => {
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
const { SUB_CLI_DESCRIPTORS, getSubCliEntries } = await importSubCliDescriptors();
const { SUB_CLI_DESCRIPTORS, getSubCliEntriesCore } = await importSubCliDescriptors();
const exportedNames = descriptorNames(SUB_CLI_DESCRIPTORS);
expect(exportedNames).toEqual(descriptorNames(getSubCliEntries()));
expect(exportedNames).toEqual(descriptorNames(getSubCliEntriesCore()));
expect(exportedNames).not.toContain("qa");
});
@@ -73,12 +73,12 @@ describe("sub-cli descriptors", () => {
const {
SUB_CLI_DESCRIPTORS,
getSubCliCommandsWithSubcommands,
getSubCliEntries,
getSubCliEntriesCore,
getSubCliParentDefaultHelpCommands,
} = await importSubCliDescriptors();
const exportedNames = descriptorNames(SUB_CLI_DESCRIPTORS);
expect(exportedNames).toEqual(descriptorNames(getSubCliEntries()));
expect(exportedNames).toEqual(descriptorNames(getSubCliEntriesCore()));
expect(exportedNames).toContain("qa");
expect(getSubCliCommandsWithSubcommands()).toContain("qa");
expect(getSubCliParentDefaultHelpCommands()).not.toContain("qa");
+1 -1
View File
@@ -263,7 +263,7 @@ export const SUB_CLI_DESCRIPTORS = filterPrivateQaItems(
);
/** Return visible sub-CLI descriptors in help/registration order. */
export function getSubCliEntries(): ReadonlyArray<SubCliDescriptor> {
export function getSubCliEntriesCore(): ReadonlyArray<SubCliDescriptor> {
return filterPrivateQaItems(
subCliCommandCatalog.getDescriptors(),
(descriptor) => descriptor.name,
+5 -5
View File
@@ -53,9 +53,9 @@ import { applyCliProfileEnv, parseCliProfileArgs } from "./profile.js";
import { formatCliCommandSuggestions } from "./program/command-suggestions.js";
import {
getCoreCliCommandDescriptors,
getCoreCliCommandNames,
getCoreCliCommandNamesCore,
} from "./program/core-command-descriptors.js";
import { getSubCliEntries } from "./program/subcli-descriptors.js";
import { getSubCliEntriesCore } from "./program/subcli-descriptors.js";
import {
resolveMissingPluginCommandMessage,
rewriteUpdateFlagArgv,
@@ -865,8 +865,8 @@ function shouldBootstrapCliProxyBeforeFastPath(env: NodeJS.ProcessEnv = process.
function isKnownBuiltInCommandRoot(primary: string): boolean {
return (
getCoreCliCommandNames().includes(primary) ||
getSubCliEntries().some((entry) => entry.name === primary)
getCoreCliCommandNamesCore().includes(primary) ||
getSubCliEntriesCore().some((entry) => entry.name === primary)
);
}
@@ -884,7 +884,7 @@ function resolveBuiltInMachineOutput(argv: string[]): boolean {
if (!primary) {
return false;
}
const descriptor = [...getCoreCliCommandDescriptors(), ...getSubCliEntries()].find(
const descriptor = [...getCoreCliCommandDescriptors(), ...getSubCliEntriesCore()].find(
(entry) => entry.name === primary,
);
return descriptor ? resolvesMachineOutput(descriptor, argv) : false;
+2 -2
View File
@@ -20,7 +20,7 @@ import {
import { isLikelySensitiveModelProviderHeaderName } from "../secrets/model-provider-header-policy.js";
import { hasConfiguredPlaintextSecretValue } from "../secrets/secret-value.js";
import { discoverConfigSecretTargets } from "../secrets/target-registry.js";
import { collectChannelSecurityFindings } from "../security/audit-channel.js";
import { collectChannelSecurityFindingsCore } from "../security/audit-channel.js";
import { collectExecFilesystemPolicyDriftHits } from "../security/exec-filesystem-policy.js";
function collectImplicitHeartbeatDirectPolicyWarnings(cfg: OpenClawConfig): string[] {
@@ -340,7 +340,7 @@ export async function collectSecurityWarnings(
warnings.push(...tokenConflict.warningLines);
}
const channelFindings = await collectChannelSecurityFindings({
const channelFindings = await collectChannelSecurityFindingsCore({
cfg,
mode: "doctor",
plugins: listReadOnlyChannelPluginsForConfig(cfg, {
+4 -2
View File
@@ -124,7 +124,9 @@ function normalizeCoreOwnedChannelSchema(schema: Record<string, unknown>): Recor
}
/** Collects plugin config UI metadata with deterministic origin precedence and output ordering. */
export function collectPluginSchemaMetadata(registry: PluginManifestRegistry): PluginUiMetadata[] {
export function collectPluginSchemaMetadataCore(
registry: PluginManifestRegistry,
): PluginUiMetadata[] {
const deduped = new Map<
string,
PluginUiMetadata & {
@@ -217,7 +219,7 @@ export function collectChannelSchemaMetadataWithOwnership(
}
/** Collects public per-channel config UI metadata without internal schema ownership. */
export function collectChannelSchemaMetadata(
export function collectChannelSchemaMetadataCore(
registry: PluginManifestRegistry,
): ChannelUiMetadata[] {
return collectChannelSchemaMetadataWithOwnership(registry).map(
+8 -8
View File
@@ -1,15 +1,15 @@
// Collects runtime data needed to generate config documentation baselines.
import { collectBundledChannelConfigs as collectBundledChannelConfigsImpl } from "../plugins/bundled-channel-config-metadata.js";
import { collectBundledChannelConfigsCore } from "../plugins/bundled-channel-config-metadata.js";
import { loadPluginManifestRegistry as loadPluginManifestRegistryImpl } from "../plugins/manifest-registry.js";
import {
collectChannelSchemaMetadata as collectChannelSchemaMetadataImpl,
collectPluginSchemaMetadata as collectPluginSchemaMetadataImpl,
collectChannelSchemaMetadataCore,
collectPluginSchemaMetadataCore,
} from "./channel-config-metadata.js";
import { buildConfigSchema as buildConfigSchemaImpl } from "./schema.js";
import { buildConfigSchemaCore } from "./schema.js";
/** Runtime facade used by docs baseline generation to keep imports narrow. */
export const loadPluginManifestRegistry = loadPluginManifestRegistryImpl;
export const collectBundledChannelConfigs = collectBundledChannelConfigsImpl;
export const collectChannelSchemaMetadata = collectChannelSchemaMetadataImpl;
export const collectPluginSchemaMetadata = collectPluginSchemaMetadataImpl;
export const buildConfigSchema = buildConfigSchemaImpl;
export const collectBundledChannelConfigs = collectBundledChannelConfigsCore;
export const collectChannelSchemaMetadata = collectChannelSchemaMetadataCore;
export const collectPluginSchemaMetadata = collectPluginSchemaMetadataCore;
export const buildConfigSchema = buildConfigSchemaCore;
+2 -2
View File
@@ -11,7 +11,7 @@ import {
import { replaceConfigFile } from "./mutate.js";
import { redactSensitiveArgv } from "./redact-argv.js";
import { REDACTED_SENTINEL, restoreRedactedValues } from "./redact-snapshot.js";
import { buildConfigSchema } from "./schema.js";
import { buildConfigSchemaCore } from "./schema.js";
import type { OpenClawConfig } from "./types.openclaw.js";
import { validateConfigObjectWithPlugins } from "./validation.js";
@@ -285,7 +285,7 @@ export async function setConfiguredMcpServer(params: {
const restored = restoreRedactedValues(
{ mcp: { servers: { [name]: argvRestored.server } } },
{ mcp: { servers: loaded.mcpServers } },
buildConfigSchema().uiHints,
buildConfigSchemaCore().uiHints,
);
if (!restored.ok) {
return {
+4 -4
View File
@@ -5,7 +5,7 @@ import { describe, expect, it } from "vitest";
import { redactSnapshotTestHints as mainSchemaHints } from "../../test/helpers/config/redact-snapshot-test-hints.js";
import { REDACTED_SENTINEL, redactConfigSnapshot } from "./redact-snapshot.js";
import { makeSnapshot, restoreRedactedValues } from "./redact-snapshot.test-helpers.js";
import { buildConfigSchema } from "./schema.js";
import { buildConfigSchemaCore } from "./schema.js";
describe("realredactConfigSnapshot_real", () => {
it("main schema redact works (samples)", () => {
@@ -50,7 +50,7 @@ describe("realredactConfigSnapshot_real", () => {
});
it("redacts bundled channel private keys from generated schema hints", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const snapshot = makeSnapshot({
channels: {
nostr: {
@@ -73,7 +73,7 @@ describe("realredactConfigSnapshot_real", () => {
});
it("redacts Discord Activity client secrets registered on plain string schemas", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
expect(hints["channels.discord.activities.clientSecret"]?.sensitive).toBe(true);
const snapshot = makeSnapshot({
channels: {
@@ -93,7 +93,7 @@ describe("realredactConfigSnapshot_real", () => {
});
it("redacts and restores web fetch operator headers from generated schema hints", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
expect(hints["tools.web.fetch.headers.*"]?.sensitive).toBe(true);
const snapshot = makeSnapshot({
tools: {
+9 -9
View File
@@ -12,7 +12,7 @@ import {
restoreRedactedValues,
type TestSnapshot,
} from "./redact-snapshot.test-helpers.js";
import { buildConfigSchema } from "./schema.js";
import { buildConfigSchemaCore } from "./schema.js";
import type { ConfigFileSnapshot, OpenClawConfig } from "./types.openclaw.js";
function expectNestedPairValue(
@@ -208,7 +208,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts and restores MCP SSE header values from schema hints", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const snapshot = makeSnapshot({
mcp: {
servers: {
@@ -252,7 +252,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts sensitive auth material from MCP SSE URLs", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
mcp: {
servers: {
@@ -289,7 +289,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts media request auth and proxy transport secrets from config snapshots", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
tools: {
media: {
@@ -346,7 +346,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts model provider request auth secrets from config snapshots", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
models: {
providers: {
@@ -394,7 +394,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts model provider local service env values from config snapshots", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
models: {
providers: {
@@ -448,7 +448,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts install policy env values from config snapshots", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
security: {
installPolicy: {
@@ -498,7 +498,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts model provider request proxy URLs from config snapshots", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
models: {
providers: {
@@ -1413,7 +1413,7 @@ describe("redactConfigSnapshot", () => {
});
it("redacts browser cdpUrl secrets while preserving bare endpoints", () => {
const hints = buildConfigSchema().uiHints;
const hints = buildConfigSchemaCore().uiHints;
const raw = `{
browser: {
cdpUrl: "https://user:pass@chrome.browserless.io?token=supersecret123",
+9 -9
View File
@@ -2,12 +2,12 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
import { resolvePluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import {
collectChannelSchemaMetadata,
collectPluginSchemaMetadata,
collectChannelSchemaMetadataCore,
collectPluginSchemaMetadataCore,
} from "./channel-config-metadata.js";
import { getRuntimeConfig, readConfigFileSnapshot } from "./config.js";
import type { OpenClawConfig } from "./config.js";
import { buildConfigSchema, type ConfigSchemaResponse } from "./schema.js";
import { buildConfigSchemaCore, type ConfigSchemaResponse } from "./schema.js";
// Runtime schemas include currently loaded plugin/channel metadata for accurate UI fields.
function loadManifestRegistry(config: OpenClawConfig, env?: NodeJS.ProcessEnv) {
@@ -24,9 +24,9 @@ function loadManifestRegistry(config: OpenClawConfig, env?: NodeJS.ProcessEnv) {
export function loadGatewayRuntimeConfigSchema(): ConfigSchemaResponse {
const config = getRuntimeConfig();
const registry = loadManifestRegistry(config);
return buildConfigSchema({
plugins: collectPluginSchemaMetadata(registry),
channels: collectChannelSchemaMetadata(registry),
return buildConfigSchemaCore({
plugins: collectPluginSchemaMetadataCore(registry),
channels: collectChannelSchemaMetadataCore(registry),
});
}
@@ -36,8 +36,8 @@ export async function readBestEffortRuntimeConfigSchema(): Promise<ConfigSchemaR
? snapshot.config
: { agents: { list: [{ id: "main", default: true }] }, plugins: { enabled: true } };
const registry = loadManifestRegistry(config);
return buildConfigSchema({
plugins: snapshot.valid ? collectPluginSchemaMetadata(registry) : [],
channels: collectChannelSchemaMetadata(registry),
return buildConfigSchemaCore({
plugins: snapshot.valid ? collectPluginSchemaMetadataCore(registry) : [],
channels: collectChannelSchemaMetadataCore(registry),
});
}
+13 -13
View File
@@ -2,7 +2,7 @@ import { SENSITIVE_URL_HINT_TAG } from "@openclaw/net-policy/redact-sensitive-ur
// Covers canonical config schema defaults, validation, and sensitive redaction.
import { expectDefined } from "@openclaw/normalization-core";
import { beforeAll, describe, expect, it } from "vitest";
import { buildConfigSchema, lookupConfigSchema } from "./schema.js";
import { buildConfigSchemaCore, lookupConfigSchema } from "./schema.js";
import { applyDerivedTags } from "./schema.tags.js";
import { applyResolvedConfigTierHints } from "./schema.tiers.js";
import { validateConfigObjectRaw } from "./validation.js";
@@ -10,8 +10,8 @@ import { ToolsSchema } from "./zod-schema.agent-runtime.js";
import { OpenClawSchema } from "./zod-schema.js";
describe("config schema", () => {
type SchemaInput = NonNullable<Parameters<typeof buildConfigSchema>[0]>;
let baseSchema: ReturnType<typeof buildConfigSchema>;
type SchemaInput = NonNullable<Parameters<typeof buildConfigSchemaCore>[0]>;
let baseSchema: ReturnType<typeof buildConfigSchemaCore>;
let pluginUiHintInput: SchemaInput;
let tokenHintInput: SchemaInput;
let mergedSchemaInput: SchemaInput;
@@ -19,7 +19,7 @@ describe("config schema", () => {
let cachedMergeInput: SchemaInput;
beforeAll(() => {
baseSchema = buildConfigSchema();
baseSchema = buildConfigSchemaCore();
pluginUiHintInput = {
plugins: [
{
@@ -471,7 +471,7 @@ describe("config schema", () => {
});
it("merges plugin ui hints", () => {
const res = buildConfigSchema(pluginUiHintInput);
const res = buildConfigSchemaCore(pluginUiHintInput);
expect(res.uiHints["plugins.entries.voice-call"]?.label).toBe("Voice Call");
expect(res.uiHints["plugins.entries.voice-call.config"]?.label).toBe("Voice Call Config");
@@ -482,13 +482,13 @@ describe("config schema", () => {
});
it("does not re-mark existing non-sensitive token-like fields", () => {
const res = buildConfigSchema(tokenHintInput);
const res = buildConfigSchemaCore(tokenHintInput);
expect(res.uiHints["plugins.entries.voice-call.config.tokens"]?.sensitive).toBe(false);
});
it("merges plugin + channel schemas", () => {
const res = buildConfigSchema(mergedSchemaInput);
const res = buildConfigSchemaCore(mergedSchemaInput);
const schema = res.schema as {
properties?: Record<string, unknown>;
@@ -544,7 +544,7 @@ describe("config schema", () => {
});
it("omits a single oversized plugin schema from the full schema response", () => {
const res = buildConfigSchema({
const res = buildConfigSchemaCore({
cache: false,
plugins: [
{
@@ -572,7 +572,7 @@ describe("config schema", () => {
});
it("omits later plugin schemas after the aggregate extension schema budget is exhausted", () => {
const res = buildConfigSchema({
const res = buildConfigSchemaCore({
cache: false,
plugins: Array.from({ length: 40 }, (_, index) => ({
id: `plugin-${index}`,
@@ -597,7 +597,7 @@ describe("config schema", () => {
});
it("looks up plugin config paths for slash-delimited plugin ids", () => {
const res = buildConfigSchema({
const res = buildConfigSchemaCore({
plugins: [
{
id: "pack/one",
@@ -622,7 +622,7 @@ describe("config schema", () => {
});
it("adds heartbeat target hints with dynamic channels", () => {
const res = buildConfigSchema(heartbeatChannelInput);
const res = buildConfigSchemaCore(heartbeatChannelInput);
const defaultsHint = res.uiHints["agents.defaults.heartbeat.target"];
const entryHint = res.uiHints["agents.entries.*.heartbeat.target"];
@@ -634,10 +634,10 @@ describe("config schema", () => {
});
it("caches merged schemas for identical plugin/channel metadata", () => {
const first = buildConfigSchema(cachedMergeInput);
const first = buildConfigSchemaCore(cachedMergeInput);
const plugin = expectDefined(cachedMergeInput.plugins?.[0], "cached plugin metadata");
const channel = expectDefined(cachedMergeInput.channels?.[0], "cached channel metadata");
const second = buildConfigSchema({
const second = buildConfigSchemaCore({
plugins: [{ ...plugin }],
channels: [{ ...channel }],
});
+1 -1
View File
@@ -567,7 +567,7 @@ function buildBaseConfigSchema(): ConfigSchemaResponse {
return next;
}
export function buildConfigSchema(params?: {
export function buildConfigSchemaCore(params?: {
plugins?: PluginUiMetadata[];
channels?: ChannelUiMetadata[];
cache?: boolean;
+2 -2
View File
@@ -21,7 +21,7 @@ import { openLocalFileSafely, FsSafeError } from "../infra/fs-safe.js";
import { safeFileURLToPath } from "../infra/local-file-access.js";
import { verifyPairingToken } from "../infra/pairing-token.js";
import { isWithinDir } from "../infra/path-safety.js";
import { assertLocalMediaAllowed, getDefaultLocalRoots } from "../media/local-media-access.js";
import { assertLocalMediaAllowed, getDefaultLocalRootsCore } from "../media/local-media-access.js";
import { getAgentScopedMediaLocalRoots } from "../media/local-roots.js";
import { probePlaybackMediaFileDescriptor, type MediaProbeResult } from "../media/media-probe.js";
import {
@@ -699,7 +699,7 @@ export async function handleControlUiAssistantMediaRequest(
}
const localRoots = opts?.config
? getAgentScopedMediaLocalRoots(opts.config, opts.agentId)
: getDefaultLocalRoots();
: getDefaultLocalRootsCore();
if (isMetaRequest) {
const availability = await resolveAssistantMediaAvailability(source, localRoots);
@@ -54,7 +54,7 @@ import {
isLiveBillingDrift,
isLiveRateLimitDrift,
} from "../agents/live-test-provider-drift.test-support.js";
import { getApiKeyForModel, resolveEnvApiKey } from "../agents/model-auth.js";
import { getApiKeyForModelCore, resolveEnvApiKey } from "../agents/model-auth.js";
import { normalizeProviderId } from "../agents/model-selection.js";
import { shouldSuppressBuiltInModel } from "../agents/model-suppression.js";
import { ensureOpenClawModelsJson } from "../agents/models-config.js";
@@ -5626,7 +5626,7 @@ describeLive("gateway live (dev agent, profile keys)", () => {
const modelRef = `${model.provider}/${model.id}`;
try {
const apiKeyInfo = await withGatewayLiveSetupTimeout(
getApiKeyForModel({
getApiKeyForModelCore({
model,
cfg,
store: authProfileStore,
@@ -5763,12 +5763,12 @@ describeLive("gateway live (dev agent, profile keys)", () => {
return;
}
try {
await getApiKeyForModel({
await getApiKeyForModelCore({
model: anthropic,
cfg,
credentialPrecedence: LIVE_CREDENTIAL_PRECEDENCE,
});
await getApiKeyForModel({
await getApiKeyForModelCore({
model: zai,
cfg,
credentialPrecedence: LIVE_CREDENTIAL_PRECEDENCE,
+4 -4
View File
@@ -9,7 +9,7 @@ import {
type RequestNodePairingResult,
} from "../infra/device-pairing-node.js";
import { KeyedAsyncQueue } from "../plugin-sdk/keyed-async-queue.js";
import { createDeferred, type Deferred } from "../shared/deferred.js";
import { createDeferredCore, type Deferred } from "../shared/deferred.js";
import {
AUTH_RATE_LIMIT_SCOPE_NODE_REAPPROVAL,
buildRateLimitIdentityKey,
@@ -171,7 +171,7 @@ export function createNodeReapprovalCoordinator(
const fingerprint = buildRequestFingerprint(params.input);
const state = requestStates.get(nodeId);
if (!state) {
const deferred = createDeferred<RequestNodePairingResult | null>();
const deferred = createDeferredCore<RequestNodePairingResult | null>();
const nextState: NodeRequestState = { activeFingerprint: fingerprint };
requestStates.set(nodeId, nextState);
startFirstRequest(nodeId, nextState, {
@@ -183,13 +183,13 @@ export function createNodeReapprovalCoordinator(
return deferred.promise;
}
if (state.queued?.fingerprint === fingerprint) {
const follower = createDeferred<RequestNodePairingResult | null>();
const follower = createDeferredCore<RequestNodePairingResult | null>();
state.queued.params = params;
state.queued.followers.push(follower);
return follower.promise;
}
const deferred = createDeferred<RequestNodePairingResult | null>();
const deferred = createDeferredCore<RequestNodePairingResult | null>();
if (state.queued) {
state.queued.deferred.resolve(null);
for (const follower of state.queued.followers) {
+2 -2
View File
@@ -6,7 +6,7 @@ import {
GATEWAY_CLIENT_NAMES,
} from "../../packages/gateway-protocol/src/client-info.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { createDeferred } from "../shared/deferred.js";
import { createDeferredCore } from "../shared/deferred.js";
import { resolveGatewayClientBootstrap } from "./client-bootstrap.js";
import { startGatewayClientWhenEventLoopReady } from "./client-start-readiness.js";
import { GatewayClient, type GatewayClientOptions } from "./client.js";
@@ -83,7 +83,7 @@ export async function withOperatorApprovalsGatewayClient<T>(
},
run: (client: GatewayClient) => Promise<T>,
): Promise<T> {
const ready = createDeferred();
const ready = createDeferredCore();
const gatewayClient = await createOperatorApprovalsGatewayClient({
config: params.config,
+2 -2
View File
@@ -25,7 +25,7 @@ vi.mock("../secrets/store/secret-store.js", () => {
});
import {
getRuntimeAuthProfileStoreCredentialsRevision,
getRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshotCore,
setRuntimeAuthProfileStoreSnapshot,
} from "../agents/auth-profiles/runtime-snapshots.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
@@ -750,7 +750,7 @@ describe("gateway aux handlers", () => {
required: "gen-old",
});
expect(
getRuntimeAuthProfileStoreSnapshot(authAgentDir)?.profiles["openai:default"],
getRuntimeAuthProfileStoreSnapshotCore(authAgentDir)?.profiles["openai:default"],
).toMatchObject({ access: "access-new", refresh: "refresh-new" });
});
+6 -6
View File
@@ -21,8 +21,8 @@ import {
type CommandSecretAssignment,
} from "../secrets/runtime-command-secrets.js";
import {
getActiveSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotRevision,
getActiveSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotRevisionState,
type PreparedSecretsRuntimeSnapshot,
} from "../secrets/runtime-state.js";
import { createLazyPromise } from "../shared/lazy-runtime.js";
@@ -381,11 +381,11 @@ export function createGatewayAuxHandlers(params: {
const restartedChannels = new Set<ChannelKind>();
try {
for (;;) {
const previousSnapshot = getActiveSecretsRuntimeSnapshot();
const previousSnapshot = getActiveSecretsRuntimeSnapshotState();
if (!previousSnapshot) {
throw new Error("Secrets runtime snapshot is not active.");
}
const previousSnapshotRevision = getActiveSecretsRuntimeSnapshotRevision();
const previousSnapshotRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const previousGenerationOwnership =
captureSharedGatewaySessionGenerationOwnership(
params.sharedGatewaySessionGenerationState,
@@ -404,7 +404,7 @@ export function createGatewayAuxHandlers(params: {
publishFailureAsDegraded: true,
forceColdRefKeys: reloadOptions?.forceColdRefKeys,
canPublishFailureAsDegraded: () =>
getActiveSecretsRuntimeSnapshotRevision() === previousSnapshotRevision,
getActiveSecretsRuntimeSnapshotRevisionState() === previousSnapshotRevision,
},
);
const plan = buildReloadPlan(
@@ -425,7 +425,7 @@ export function createGatewayAuxHandlers(params: {
activate: true,
},
async () => {
publishedSnapshotRevision = getActiveSecretsRuntimeSnapshotRevision();
publishedSnapshotRevision = getActiveSecretsRuntimeSnapshotRevisionState();
generationOwnership = claimSharedGatewaySessionGenerationIfOwned(
params.sharedGatewaySessionGenerationState,
previousGenerationOwnership,
+2 -2
View File
@@ -2,7 +2,7 @@ import { isNixMode } from "../config/paths.js";
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js";
import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js";
import { clearSecretsRuntimeSnapshot } from "../secrets/runtime-state.js";
import { clearSecretsRuntimeSnapshotState } from "../secrets/runtime-state.js";
import { createLazyRuntimeModule } from "../shared/lazy-runtime.js";
import { startGatewayCoreRuntime } from "./server-core-runtime.js";
import { prepareGatewayKernelRequestRuntime } from "./server-kernel-request-runtime.js";
@@ -162,7 +162,7 @@ export async function createGatewayKernel(port = 18789, opts: GatewayServerOptio
if (lifecycleRuntime) {
await lifecycleRuntime.closeOnStartupFailure();
} else {
clearSecretsRuntimeSnapshot();
clearSecretsRuntimeSnapshotState();
clearPluginMetadataLifecycleCaches();
}
throw error;
+2 -2
View File
@@ -12,7 +12,7 @@ import { upsertPresence } from "../infra/system-presence.js";
import { startDiagnosticHeartbeat, stopDiagnosticHeartbeat } from "../logging/diagnostic.js";
import type { createSubsystemLogger } from "../logging/subsystem.js";
import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js";
import { clearSecretsRuntimeSnapshot } from "../secrets/runtime-state.js";
import { clearSecretsRuntimeSnapshotState } from "../secrets/runtime-state.js";
import { roleScopesAllow } from "../shared/operator-scope-compat.js";
import {
recordRemoteNodeInfo,
@@ -517,7 +517,7 @@ export async function prepareGatewayLifecycle(params: {
await createGatewayCloseHandler({
bonjourStop: runtimeState.bonjourStop,
tailscaleCleanup: runtimeState.tailscaleCleanup,
clearSecretsRuntimeSnapshot,
clearSecretsRuntimeSnapshot: clearSecretsRuntimeSnapshotState,
channelIds,
stopChannel,
pluginServices: runtimeState.pluginServices,
@@ -8,7 +8,7 @@ import { applySessionEntryCanonicalReplacements } from "../config/sessions/sessi
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { createDeferred } from "../shared/deferred.js";
import { createDeferredCore } from "../shared/deferred.js";
import { withOpenClawTestState } from "../test-utils/openclaw-test-state.js";
import {
createGatewayMethodRegistry,
@@ -589,8 +589,8 @@ describe("sessions.patchMany orchestration", () => {
cfg,
key: conflictingAlias,
}).storePath;
const writerStarted = createDeferred();
const insertConflictingAlias = createDeferred();
const writerStarted = createDeferredCore();
const insertConflictingAlias = createDeferredCore();
const writer = applySessionEntryCanonicalReplacements({
agentId: "main",
sessionKeys: [conflictingAlias],
@@ -612,7 +612,7 @@ describe("sessions.patchMany orchestration", () => {
});
await writerStarted.promise;
const preflightCompleted = createDeferred();
const preflightCompleted = createDeferredCore();
const respond = vi.fn();
const request = sessionMutationHandlers["sessions.patchMany"]!({
params: {
@@ -686,8 +686,8 @@ describe("sessions.patchMany orchestration", () => {
cfg,
key: conflictingAlias,
}).storePath;
const writerStarted = createDeferred();
const insertConflictingAlias = createDeferred();
const writerStarted = createDeferredCore();
const insertConflictingAlias = createDeferredCore();
const writer = applySessionEntryCanonicalReplacements({
agentId: "main",
sessionKeys: [conflictingAlias],
@@ -709,7 +709,7 @@ describe("sessions.patchMany orchestration", () => {
});
await writerStarted.promise;
const preflightCompleted = createDeferred();
const preflightCompleted = createDeferredCore();
const respond = vi.fn();
const request = sessionMutationHandlers["sessions.patch"]!({
params: { key: conflictingAlias, pinned: true },
@@ -6,7 +6,7 @@ import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { afterEach, describe, expect, it, vi } from "vitest";
import { getDefaultLocalRoots } from "../../media/local-media-access.js";
import { getDefaultLocalRootsCore } from "../../media/local-media-access.js";
import { buildWebchatAssistantMessageFromReplyPayloads } from "./chat-webchat-media.js";
async function buildWebchatAudioBlocks(
@@ -211,7 +211,7 @@ describe("webchat audio blocks through assistant messages", () => {
});
it("falls back to default localRoots when explicit roots are omitted", async () => {
const [defaultRoot] = getDefaultLocalRoots();
const [defaultRoot] = getDefaultLocalRootsCore();
if (defaultRoot === undefined) {
throw new Error("expected default local media root");
}
@@ -25,7 +25,7 @@ vi.mock("../../secrets/runtime-state.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../secrets/runtime-state.js")>();
return {
...actual,
getActiveSecretsRuntimeSnapshot: () => secretsMocks.activeSnapshot,
getActiveSecretsRuntimeSnapshotState: () => secretsMocks.activeSnapshot,
};
});
@@ -15,7 +15,7 @@ import {
writeRestartSentinel,
} from "../../infra/restart-sentinel.js";
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
import { getActiveSecretsRuntimeSnapshot } from "../../secrets/runtime-state.js";
import { getActiveSecretsRuntimeSnapshotState } from "../../secrets/runtime-state.js";
import { isRecord } from "../../utils.js";
import { resolveEffectiveSharedGatewayAuth, resolveGatewayAuth } from "../auth.js";
import { invalidateConfigGetResponseCache } from "../config-get-response.js";
@@ -137,7 +137,7 @@ export function didActiveSharedGatewayAuthChange(params: {
fallbackSource?: OpenClawConfig;
next: OpenClawConfig;
}): boolean {
const active = getActiveSecretsRuntimeSnapshot();
const active = getActiveSecretsRuntimeSnapshotState();
if (!active) {
return didSharedGatewayAuthChange(params.fallbackPrev, params.next);
}
@@ -79,7 +79,7 @@ vi.mock("../../secrets/runtime.js", () => ({
}));
vi.mock("../../secrets/runtime-state.js", () => ({
getActiveSecretsRuntimeSnapshot: () => null,
getActiveSecretsRuntimeSnapshotState: () => null,
}));
vi.mock("../../infra/restart.js", () => ({
+1 -1
View File
@@ -16,7 +16,7 @@ const storeMocks = vi.hoisted(() => ({
vi.mock("../../secrets/runtime-state.js", () => ({
collectSecretStoreRefKeysInConfig: storeMocks.collectRefKeys,
getActiveSecretsRuntimeSnapshot: storeMocks.getSnapshot,
getActiveSecretsRuntimeSnapshotState: storeMocks.getSnapshot,
}));
vi.mock("../../secrets/store/secret-store.js", () => {
+2 -2
View File
@@ -16,7 +16,7 @@ import {
import { formatErrorMessage as errorMessage } from "../../infra/errors.js";
import {
collectSecretStoreRefKeysInConfig,
getActiveSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotState,
} from "../../secrets/runtime-state.js";
import {
deleteSecretStoreEntry,
@@ -136,7 +136,7 @@ export function createSecretsHandlers(params: {
const reloadStoreReference = async (
name: string,
): Promise<{ reloaded: boolean; warningCount?: number }> => {
const snapshot = getActiveSecretsRuntimeSnapshot();
const snapshot = getActiveSecretsRuntimeSnapshotState();
const refKeys = snapshot
? collectSecretStoreRefKeysInConfig(snapshot.sourceConfig, name)
: new Set<string>();
+16 -16
View File
@@ -6,9 +6,9 @@ import {
} from "../config/config.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
clearSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotRevision,
clearSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotRevisionState,
hasActiveSecretsRuntimeSnapshotLineage,
hasSameSecretReloadContract,
restoreSecretsRuntimeSourceSnapshotIfLineageCurrent,
@@ -43,7 +43,7 @@ import { publishRuntimeSecretsStateTransition } from "./server-startup-config.js
export function isRuntimeSecretsPreparationCurrent(
preparation: CurrentRuntimeSecretsPreparation,
): boolean {
return getActiveSecretsRuntimeSnapshotRevision() === preparation.expectedRevision;
return getActiveSecretsRuntimeSnapshotRevisionState() === preparation.expectedRevision;
}
async function activateSecretsRuntimeSnapshotIfCurrent(
@@ -124,8 +124,8 @@ export function createManagedReloadSecretHandlers(options: {
throw new GatewayConfigReloadSupersededError();
}
const previousRuntimeSourceConfig = getRuntimeConfigSourceSnapshot();
const previousSecretsSnapshot = getActiveSecretsRuntimeSnapshot();
const previousSecretsRevision = getActiveSecretsRuntimeSnapshotRevision();
const previousSecretsSnapshot = getActiveSecretsRuntimeSnapshotState();
const previousSecretsRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const previousRuntimeMetadata = getRuntimeConfigSnapshotMetadata();
const nextSecretsSourceConfig = prepareRuntimeCandidate(
nextConfig,
@@ -158,7 +158,7 @@ export function createManagedReloadSecretHandlers(options: {
) {
continue;
}
const committedSecretsRevision = getActiveSecretsRuntimeSnapshotRevision();
const committedSecretsRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const rollbackPublishedSource = async () => {
if (
!restoreSecretsRuntimeSourceSnapshotIfLineageCurrent({
@@ -246,7 +246,7 @@ export function createManagedReloadSecretHandlers(options: {
if (!activated) {
continue;
}
const committedSecretsRevision = getActiveSecretsRuntimeSnapshotRevision();
const committedSecretsRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const rollbackPublishedSource = async () => {
if (
!(await restoreSecretsRuntimeSnapshotIfCurrent(
@@ -334,8 +334,8 @@ export function createManagedReloadSecretHandlers(options: {
if (!transactionOwnership.isCurrent()) {
throw new GatewayConfigReloadSupersededError();
}
const previousSnapshot = getActiveSecretsRuntimeSnapshot();
const previousSnapshotRevision = getActiveSecretsRuntimeSnapshotRevision();
const previousSnapshot = getActiveSecretsRuntimeSnapshotState();
const previousSnapshotRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const previousGenerationOwnership = captureSharedGatewaySessionGenerationOwnership(
params.sharedGatewaySessionGenerationState,
);
@@ -361,7 +361,7 @@ export function createManagedReloadSecretHandlers(options: {
if (!transactionOwnership.isCurrent()) {
throw new GatewayConfigReloadSupersededError();
}
if (getActiveSecretsRuntimeSnapshotRevision() !== previousSnapshotRevision) {
if (getActiveSecretsRuntimeSnapshotRevisionState() !== previousSnapshotRevision) {
continue;
}
const nextSharedGatewaySessionGeneration =
@@ -416,7 +416,7 @@ export function createManagedReloadSecretHandlers(options: {
};
const publishRuntime = async () => {
runtimeSecretsPublished = true;
publishedSnapshotRevision = getActiveSecretsRuntimeSnapshotRevision();
publishedSnapshotRevision = getActiveSecretsRuntimeSnapshotRevisionState();
// Claim the generation at the snapshot activation edge, but keep
// `required` until the runtime commit succeeds.
claimGenerationOwnership();
@@ -461,9 +461,9 @@ export function createManagedReloadSecretHandlers(options: {
);
} else if (
publishedSnapshotRevision !== null &&
getActiveSecretsRuntimeSnapshotRevision() === publishedSnapshotRevision
getActiveSecretsRuntimeSnapshotRevisionState() === publishedSnapshotRevision
) {
clearSecretsRuntimeSnapshot();
clearSecretsRuntimeSnapshotState();
snapshotRestored = true;
if (generationOwnership) {
generationRestored = restoreOwnedCurrentSharedGatewaySessionGeneration(
@@ -572,9 +572,9 @@ export function createManagedReloadSecretHandlers(options: {
} else if (
publishedSnapshotRevision !== null &&
generationOwnership &&
getActiveSecretsRuntimeSnapshotRevision() === publishedSnapshotRevision
getActiveSecretsRuntimeSnapshotRevisionState() === publishedSnapshotRevision
) {
clearSecretsRuntimeSnapshot();
clearSecretsRuntimeSnapshotState();
snapshotRestored = true;
generationRestored = restoreOwnedCurrentSharedGatewaySessionGeneration(
params.sharedGatewaySessionGenerationState,
+5 -5
View File
@@ -1,6 +1,6 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { runWithGatewayIndependentRootWorkAdmission } from "../process/gateway-work-admission.js";
import { getActiveSecretsRuntimeSnapshotRevision } from "../secrets/runtime-state.js";
import { getActiveSecretsRuntimeSnapshotRevisionState } from "../secrets/runtime-state.js";
import { resetSkillSnapshotConfigFingerprintCache } from "../skills/runtime/snapshot-config-fingerprint.js";
import { invalidateConfigGetResponseCache } from "./config-get-response.js";
import {
@@ -71,26 +71,26 @@ export function startManagedGatewayConfigReloader(
if (!transactionOwnership.isCurrent()) {
throw new GatewayConfigReloadSupersededError();
}
const expectedRevision = getActiveSecretsRuntimeSnapshotRevision();
const expectedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
try {
const snapshot = await params.activateRuntimeSecrets(config, {
...activationParams,
activate: false,
canPublishFailureAsDegraded: () =>
transactionOwnership.isCurrent() &&
getActiveSecretsRuntimeSnapshotRevision() === expectedRevision,
getActiveSecretsRuntimeSnapshotRevisionState() === expectedRevision,
});
if (!transactionOwnership.isCurrent()) {
throw new GatewayConfigReloadSupersededError();
}
return getActiveSecretsRuntimeSnapshotRevision() === expectedRevision
return getActiveSecretsRuntimeSnapshotRevisionState() === expectedRevision
? { snapshot, expectedRevision }
: null;
} catch (error) {
if (!transactionOwnership.isCurrent()) {
throw new GatewayConfigReloadSupersededError();
}
if (getActiveSecretsRuntimeSnapshotRevision() !== expectedRevision) {
if (getActiveSecretsRuntimeSnapshotRevisionState() !== expectedRevision) {
return null;
}
throw error;
@@ -8,7 +8,7 @@ import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js";
import { loadAuthProfileStoreWithoutExternalProfiles } from "../agents/auth-profiles.js";
import {
getRuntimeAuthProfileStoreCredentialsRevision,
getRuntimeAuthProfileStoreSnapshot,
getRuntimeAuthProfileStoreSnapshotCore,
setRuntimeAuthProfileStoreSnapshot,
} from "../agents/auth-profiles/runtime-snapshots.js";
import { writePersistedAuthProfileStoreRaw } from "../agents/auth-profiles/sqlite.js";
@@ -20,9 +20,9 @@ import { activateProviderAuthRuntimeSnapshot } from "../secrets/runtime-provider
import {
activateSecretsRuntimeSnapshotState,
activateSecretsRuntimeSnapshotStateIfCurrent,
clearSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotRevision,
clearSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotRevisionState,
} from "../secrets/runtime-state.js";
import type { PreparedSecretsRuntimeSnapshot, SecretResolverWarning } from "../secrets/runtime.js";
import { withEnvAsync } from "../test-utils/env.js";
@@ -427,7 +427,7 @@ describe("gateway startup config secret preflight", () => {
const previousSkipProviders = process.env.OPENCLAW_SKIP_PROVIDERS;
afterEach(() => {
clearSecretsRuntimeSnapshot();
clearSecretsRuntimeSnapshotState();
if (previousSkipChannels === undefined) {
delete process.env.OPENCLAW_SKIP_CHANNELS;
} else {
@@ -452,9 +452,9 @@ describe("gateway startup config secret preflight", () => {
activateRuntimeSecretsSnapshot,
});
activateSecretsRuntimeSnapshotForTest(initial);
const initialRevision = getActiveSecretsRuntimeSnapshotRevision();
const initialRevision = getActiveSecretsRuntimeSnapshotRevisionState();
activateSecretsRuntimeSnapshotForTest(refreshed);
const refreshedRevision = getActiveSecretsRuntimeSnapshotRevision();
const refreshedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(candidate, initialRevision, {
@@ -514,7 +514,7 @@ describe("gateway startup config secret preflight", () => {
logSecrets,
});
activateSecretsRuntimeSnapshotForTest(initial);
const expectedRevision = getActiveSecretsRuntimeSnapshotRevision();
const expectedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const activateSnapshotIfCurrent = vi.fn(() => {
activateSecretsRuntimeSnapshotForTest(candidate);
return true;
@@ -576,7 +576,7 @@ describe("gateway startup config secret preflight", () => {
publishFailureAsDegraded: true,
}),
).rejects.toThrow(failure.message);
const expectedRevision = getActiveSecretsRuntimeSnapshotRevision();
const expectedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
await expect(
activateProviderAuthRuntimeSnapshot({
snapshot: candidate,
@@ -636,7 +636,7 @@ describe("gateway startup config secret preflight", () => {
await activateProviderAuthRuntimeSnapshot({
snapshot: providerDegraded,
expectedRevision: getActiveSecretsRuntimeSnapshotRevision(),
expectedRevision: getActiveSecretsRuntimeSnapshotRevisionState(),
activateSnapshotIfCurrent: () => {
activateSecretsRuntimeSnapshotForTest(providerDegraded);
return true;
@@ -652,7 +652,7 @@ describe("gateway startup config secret preflight", () => {
const recovered = preparedSnapshot(config);
await activateProviderAuthRuntimeSnapshot({
snapshot: recovered,
expectedRevision: getActiveSecretsRuntimeSnapshotRevision(),
expectedRevision: getActiveSecretsRuntimeSnapshotRevisionState(),
activateSnapshotIfCurrent: () => {
activateSecretsRuntimeSnapshotForTest(recovered);
return true;
@@ -689,7 +689,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateProviderAuthRuntimeSnapshot({
snapshot: candidate,
expectedRevision: getActiveSecretsRuntimeSnapshotRevision(),
expectedRevision: getActiveSecretsRuntimeSnapshotRevisionState(),
activateSnapshotIfCurrent: () => true,
}),
).resolves.toBe(true);
@@ -728,7 +728,7 @@ describe("gateway startup config secret preflight", () => {
const recovered = preparedSnapshot(config);
await activateProviderAuthRuntimeSnapshot({
snapshot: recovered,
expectedRevision: getActiveSecretsRuntimeSnapshotRevision(),
expectedRevision: getActiveSecretsRuntimeSnapshotRevisionState(),
activateSnapshotIfCurrent: () => {
activateSecretsRuntimeSnapshotForTest(recovered);
return true;
@@ -797,7 +797,7 @@ describe("gateway startup config secret preflight", () => {
const recovered = preparedSnapshot(config);
await activateProviderAuthRuntimeSnapshot({
snapshot: recovered,
expectedRevision: getActiveSecretsRuntimeSnapshotRevision(),
expectedRevision: getActiveSecretsRuntimeSnapshotRevisionState(),
activateSnapshotIfCurrent: () => {
activateSecretsRuntimeSnapshotForTest(recovered);
return true;
@@ -848,7 +848,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
rolledBackCandidate,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(rolledBackCandidate);
@@ -859,7 +859,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
committedCandidate,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(committedCandidate);
@@ -918,11 +918,11 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
degraded,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(degraded);
const outerRevision = getActiveSecretsRuntimeSnapshotRevision();
const outerRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const descendant: PreparedSecretsRuntimeSnapshot = structuredClone(degraded);
descendant.degradedOwners?.push({
ownerKind: "provider",
@@ -985,11 +985,11 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
degraded,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(degraded);
const outerRevision = getActiveSecretsRuntimeSnapshotRevision();
const outerRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const recovered = preparedSnapshot(config);
await expect(
@@ -1060,11 +1060,11 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
providerDegraded,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(providerDegraded);
const outerRevision = getActiveSecretsRuntimeSnapshotRevision();
const outerRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const recovered = preparedSnapshot(config);
await expect(
@@ -1126,11 +1126,11 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
recovered,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(recovered);
const outerRevision = getActiveSecretsRuntimeSnapshotRevision();
const outerRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const descendant = structuredClone(recovered);
await expect(
@@ -1208,7 +1208,7 @@ describe("gateway startup config secret preflight", () => {
const sourceOnly = preparedSnapshot(stableConfig);
activateSecretsRuntimeSnapshotForTest(sourceOnly);
const committedRevision = getActiveSecretsRuntimeSnapshotRevision();
const committedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const descendant = structuredClone(sourceOnly);
expect(
activateSecretsRuntimeSnapshotStateIfCurrent({
@@ -1259,7 +1259,7 @@ describe("gateway startup config secret preflight", () => {
activateRuntimeSecretsSnapshot,
});
activateSecretsRuntimeSnapshotForTest(initial);
const initialRevision = getActiveSecretsRuntimeSnapshotRevision();
const initialRevision = getActiveSecretsRuntimeSnapshotRevisionState();
setRuntimeAuthProfileStoreSnapshot(
{
version: 1,
@@ -1283,7 +1283,9 @@ describe("gateway startup config secret preflight", () => {
}),
).resolves.toBeNull();
expect(activateRuntimeSecretsSnapshot).not.toHaveBeenCalled();
expect(getRuntimeAuthProfileStoreSnapshot(agentDir)?.profiles["openai:default"]).toMatchObject({
expect(
getRuntimeAuthProfileStoreSnapshotCore(agentDir)?.profiles["openai:default"],
).toMatchObject({
access: "access-new",
refresh: "refresh-new",
});
@@ -1298,7 +1300,7 @@ describe("gateway startup config secret preflight", () => {
activateRuntimeSecretsSnapshot: vi.fn(activateSecretsRuntimeSnapshotForTest),
});
activateSecretsRuntimeSnapshotForTest(initial);
const initialRevision = getActiveSecretsRuntimeSnapshotRevision();
const initialRevision = getActiveSecretsRuntimeSnapshotRevisionState();
let releasePublication: (() => void) | undefined;
const publicationBlocked = new Promise<void>((resolve) => {
releasePublication = resolve;
@@ -1330,7 +1332,7 @@ describe("gateway startup config secret preflight", () => {
releasePublication?.();
await candidateActivation;
await laterActivation;
expect(getActiveSecretsRuntimeSnapshot()?.config.gateway?.auth?.token).toBe("later-token");
expect(getActiveSecretsRuntimeSnapshotState()?.config.gateway?.auth?.token).toBe("later-token");
});
it("measures startup auth subphases", async () => {
@@ -2092,7 +2094,7 @@ describe("gateway startup config secret preflight", () => {
}),
).rejects.toThrow(missingSecretError.message);
shouldResolve = true;
const activeRevision = getActiveSecretsRuntimeSnapshotRevision();
const activeRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const prepared = await activateRuntimeSecrets(sourceConfig, {
reason: "restart-check",
activate: false,
@@ -2140,7 +2142,7 @@ describe("gateway startup config secret preflight", () => {
}),
).rejects.toThrow(missingSecretError.message);
shouldResolve = true;
const sourceOnlyRevision = getActiveSecretsRuntimeSnapshotRevision();
const sourceOnlyRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const sourceOnly = await activateRuntimeSecrets(sourceConfig, {
reason: "reload",
activate: false,
@@ -2173,7 +2175,7 @@ describe("gateway startup config secret preflight", () => {
"SECRETS_RELOADER_DEGRADED",
]);
shouldResolve = true;
const newerRevision = getActiveSecretsRuntimeSnapshotRevision();
const newerRevision = getActiveSecretsRuntimeSnapshotRevisionState();
const newerPrepared = await activateRuntimeSecrets(sourceConfig, {
reason: "reload",
activate: false,
@@ -2218,8 +2220,8 @@ describe("gateway startup config secret preflight", () => {
publishFailureAsDegraded: true,
}),
).rejects.toThrow(missingSecretError.message);
const revertedSnapshot = getActiveSecretsRuntimeSnapshot()!;
const revertedRevision = getActiveSecretsRuntimeSnapshotRevision();
const revertedSnapshot = getActiveSecretsRuntimeSnapshotState()!;
const revertedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
revertedSnapshot,
@@ -2267,11 +2269,11 @@ describe("gateway startup config secret preflight", () => {
publishFailureAsDegraded: true,
}),
).rejects.toThrow(missingSecretError.message);
const unrelatedRevertedSnapshot = getActiveSecretsRuntimeSnapshot()!;
const unrelatedRevertedSnapshot = getActiveSecretsRuntimeSnapshotState()!;
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
unrelatedRevertedSnapshot,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toMatchObject({ sourceConfig });
@@ -2290,8 +2292,8 @@ describe("gateway startup config secret preflight", () => {
publishFailureAsDegraded: true,
}),
).rejects.toThrow(missingSecretError.message);
const unchangedSnapshot = getActiveSecretsRuntimeSnapshot()!;
const unchangedRevision = getActiveSecretsRuntimeSnapshotRevision();
const unchangedSnapshot = getActiveSecretsRuntimeSnapshotState()!;
const unchangedRevision = getActiveSecretsRuntimeSnapshotRevisionState();
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
unchangedSnapshot,
@@ -2389,7 +2391,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
revertedSnapshot,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(revertedSnapshot);
@@ -2402,7 +2404,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
fullyResolvedSnapshot,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(fullyResolvedSnapshot);
@@ -2433,7 +2435,7 @@ describe("gateway startup config secret preflight", () => {
await expect(
activateRuntimeSecrets.activatePreparedSnapshotIfCurrent?.(
secondRevertedSnapshot,
getActiveSecretsRuntimeSnapshotRevision(),
getActiveSecretsRuntimeSnapshotRevisionState(),
{ reason: "reload", activate: true, deferStatePublication: true },
),
).resolves.toBe(secondRevertedSnapshot);
@@ -2689,8 +2691,8 @@ describe("gateway startup config secret preflight", () => {
try {
const {
clearSecretsRuntimeSnapshot: clearImportedSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshot: getImportedSecretsRuntimeSnapshot,
clearSecretsRuntimeSnapshotState: clearImportedSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotState: getImportedSecretsRuntimeSnapshot,
} = await import("../secrets/runtime-state.js");
const { getRuntimeConfigSnapshotRefreshHandler } =
await import("../config/runtime-snapshot.js");
@@ -2858,7 +2860,7 @@ describe("gateway startup config secret preflight", () => {
activate: true,
includeAuthStoreRefs: false,
});
expect(getRuntimeAuthProfileStoreSnapshot(agentDir)?.profiles["openai:default"]).toEqual(
expect(getRuntimeAuthProfileStoreSnapshotCore(agentDir)?.profiles["openai:default"]).toEqual(
credential,
);
});
+9 -9
View File
@@ -27,8 +27,8 @@ import {
import {
activateSecretsRuntimeSnapshotState,
graftActiveSecretsRuntimeAuthState,
getActiveSecretsRuntimeSnapshot,
getActiveSecretsRuntimeSnapshotRevision,
getActiveSecretsRuntimeSnapshotState,
getActiveSecretsRuntimeSnapshotRevisionState,
hasActiveSecretsRuntimeSnapshotLineage,
hasSameSecretReloadContract,
hasCurrentAuthStoreCredentialsRevision,
@@ -268,7 +268,7 @@ export function createRuntimeSecretsActivator(params: {
const activationScope = options?.stateScope ?? "full";
if (activationParams.activate && (statePrepared.degradedOwners?.length ?? 0) > 0) {
if (activationParams.deferStatePublication === true) {
const activationRevision = getActiveSecretsRuntimeSnapshotRevision();
const activationRevision = getActiveSecretsRuntimeSnapshotRevisionState();
deferredStateTransitions.set(prepared, {
kind: "degraded",
activationRevision,
@@ -282,7 +282,7 @@ export function createRuntimeSecretsActivator(params: {
} else if (activationParams.activate && secretsDegraded) {
if (activationParams.deferStatePublication === true) {
if (activeDegradationGeneration !== null) {
const activationRevision = getActiveSecretsRuntimeSnapshotRevision();
const activationRevision = getActiveSecretsRuntimeSnapshotRevisionState();
deferredStateTransitions.set(prepared, {
kind: "recovered",
activationRevision,
@@ -415,7 +415,7 @@ export function createRuntimeSecretsActivator(params: {
const prepareRuntimeSecretsSnapshot =
params.prepareRuntimeSecretsSnapshot ?? secretsRuntime!.prepareSecretsRuntimeSnapshot;
const allowUnavailableSecretOwners =
activationParams.reason !== "startup" || getActiveSecretsRuntimeSnapshot() === null;
activationParams.reason !== "startup" || getActiveSecretsRuntimeSnapshotState() === null;
const prepared = await measureDiagnosticsTimelineSpan(
"secrets.prepare",
() =>
@@ -485,7 +485,7 @@ export function createRuntimeSecretsActivator(params: {
: undefined;
return await runWithSecretsActivationLock(async () => {
if (
getActiveSecretsRuntimeSnapshotRevision() !== expectedRevision ||
getActiveSecretsRuntimeSnapshotRevisionState() !== expectedRevision ||
!hasCurrentAuthStoreCredentialsRevision(snapshot) ||
(canActivate && !canActivate())
) {
@@ -522,7 +522,7 @@ export function createRuntimeSecretsActivator(params: {
registerProviderAuthRuntimeSnapshotActivationOwner({
runExclusive: runWithSecretsActivationLock,
isCurrent: (snapshot, expectedRevision) =>
getActiveSecretsRuntimeSnapshotRevision() === expectedRevision &&
getActiveSecretsRuntimeSnapshotRevisionState() === expectedRevision &&
hasCurrentAuthStoreCredentialsRevision(snapshot),
assertValid: (snapshot) => assertRuntimeGatewayAuthNotKnownWeak(snapshot.config),
publish: async (snapshot) => {
@@ -553,7 +553,7 @@ export function createRuntimeSecretsActivator(params: {
options?.sourceOnly === true &&
options.expectedRevision !== undefined &&
hasActiveSecretsRuntimeSnapshotLineage(options.expectedRevision);
const activeSnapshot = sourceOnlyOwnsLineage ? getActiveSecretsRuntimeSnapshot() : null;
const activeSnapshot = sourceOnlyOwnsLineage ? getActiveSecretsRuntimeSnapshotState() : null;
const sourceOnlyDegradationGeneration = activeDegradationGeneration;
const sourceOnlyContractRecovered =
activeSnapshot !== null &&
@@ -574,7 +574,7 @@ export function createRuntimeSecretsActivator(params: {
if (!hasActiveSecretsRuntimeSnapshotLineage(transition.activationRevision)) {
return;
}
const activeSnapshot = getActiveSecretsRuntimeSnapshot();
const activeSnapshot = getActiveSecretsRuntimeSnapshotState();
if (!activeSnapshot) {
return;
}
@@ -5,7 +5,7 @@ import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { useAutoCleanupTempDirTracker } from "../../test/helpers/temp-dir.js";
import { resolveDefaultAgentDir } from "../agents/agent-scope-config.js";
import { getRuntimeAuthProfileStoreSnapshot } from "../agents/auth-profiles/runtime-snapshots.js";
import { getRuntimeAuthProfileStoreSnapshotCore } from "../agents/auth-profiles/runtime-snapshots.js";
import { saveAuthProfileStore } from "../agents/auth-profiles/store.js";
import { resolveMemorySearchConfig } from "../agents/memory-search.js";
import { resolveApiKeyForProvider } from "../agents/model-auth.js";
@@ -591,7 +591,7 @@ describe("Gateway startup SecretRef owner isolation", () => {
expect(active?.degradedOwners).toMatchObject([
{ ownerKind: "account", ownerId, state: "unavailable" },
]);
const store = getRuntimeAuthProfileStoreSnapshot(agentDir);
const store = getRuntimeAuthProfileStoreSnapshotCore(agentDir);
if (!store || !active) {
throw new Error("Expected activated Gateway auth profile snapshot");
}
@@ -3,7 +3,7 @@ import { getRuntimeConfig } from "../config/config.js";
import type { PluginRegistry } from "../plugins/registry-types.js";
import {
getActiveSecretsRuntimeConfigSnapshot,
getActiveSecretsRuntimeEnv,
getActiveSecretsRuntimeEnvState,
} from "../secrets/runtime-state.js";
import { createLazyRuntimeModule } from "../shared/lazy-runtime.js";
import type { WorkerBundleProducer, WorkerNpmArtifact } from "./worker-environments/bundle.js";
@@ -180,7 +180,7 @@ export async function createGatewayWorkerEnvironmentRuntime(params: {
kind: "material",
contents: await workerRuntime.resolveSecretRefString(genericKeyRef, {
config: getActiveSecretsRuntimeConfigSnapshot()?.sourceConfig ?? getRuntimeConfig(),
env: getActiveSecretsRuntimeEnv(),
env: getActiveSecretsRuntimeEnvState(),
}),
}),
});
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import { createDeferred } from "../shared/deferred.js";
import { createDeferredCore } from "../shared/deferred.js";
import {
coordinateWorkerPlacementDispatch,
type GatewayWorkerPlacementRuntime,
@@ -33,8 +33,8 @@ describe("worker placement dispatch coordinator", () => {
});
it("coalesces an identical dispatch and rejects a conflicting in-flight request", async () => {
const dispatchStarted = createDeferred();
const releaseDispatch = createDeferred();
const dispatchStarted = createDeferredCore();
const releaseDispatch = createDeferredCore();
const active = { state: "active" };
const dispatch = vi.fn(async () => {
dispatchStarted.resolve();
@@ -76,8 +76,8 @@ describe("worker placement dispatch coordinator", () => {
});
it("joins a retry before a queued reconciliation after dispatch failure", async () => {
const dispatchStarted = createDeferred();
const releaseDispatch = createDeferred();
const dispatchStarted = createDeferredCore();
const releaseDispatch = createDeferredCore();
const dispatchError = new Error("provision failed");
const dispatch = vi.fn(async () => {
dispatchStarted.resolve();
@@ -116,8 +116,8 @@ describe("worker placement dispatch coordinator", () => {
});
it("coalesces full sweeps but runs a fresh targeted pass with its environment id", async () => {
const fullSweepStarted = createDeferred();
const releaseFullSweep = createDeferred();
const fullSweepStarted = createDeferredCore();
const releaseFullSweep = createDeferredCore();
const reconcileActive = vi.fn(async (environmentId?: string) => {
if (environmentId === undefined) {
fullSweepStarted.resolve();
@@ -8,7 +8,7 @@ import {
isSessionLifecycleMutationActive,
runExclusiveSessionLifecycleMutation,
} from "../sessions/session-lifecycle-admission.js";
import { createDeferred } from "../shared/deferred.js";
import { createDeferredCore } from "../shared/deferred.js";
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { markChatAbortTerminalPersistenceError } from "./chat-abort-lifecycle-internal.js";
import { registerChatAbortController, removeChatAbortControllerEntry } from "./chat-abort.js";
@@ -65,7 +65,7 @@ function activeRunContext(params: {
runId: string;
sessionId: string;
sessionKey: string;
persistence: ReturnType<typeof createDeferred<void>>;
persistence: ReturnType<typeof createDeferredCore<void>>;
ownerConnId?: string;
}) {
const chatAbortControllers = new Map();
@@ -306,7 +306,7 @@ test("sessions.patch cancels active work and commits only after admission and te
interrupted = true;
},
});
const persistence = createDeferred();
const persistence = createDeferredCore();
const active = activeRunContext({
runId,
sessionId,
@@ -385,7 +385,7 @@ test("sharing revocation fences archive before cancellation and forces fresh aut
interrupted = true;
},
});
const persistence = createDeferred();
const persistence = createDeferredCore();
const active = activeRunContext({ runId, sessionId, sessionKey, persistence });
const requestContext = await archiveLifecycleRequestContext(active.context);
const placement = workerPlacement({ sessionId, sessionKey, state: "active" });
@@ -410,7 +410,7 @@ test("sharing revocation fences archive before cancellation and forces fresh aut
throw new Error("expected resolved sharing target");
}
const releaseAudit = createDeferred();
const releaseAudit = createDeferredCore();
sessionAuditGate.entered.mockClear();
sessionAuditGate.wait = releaseAudit.promise;
let sharing: Promise<LifecycleHandlerResponse> | undefined;
@@ -492,11 +492,11 @@ test("archive retains the lifecycle fence until drain and commit before sharing
identities: [sessionKey, sessionId],
assertAllowed: () => {},
});
const persistence = createDeferred();
const persistence = createDeferredCore();
const active = activeRunContext({ runId, sessionId, sessionKey, persistence });
const requestContext = await archiveLifecycleRequestContext(active.context);
let placement = workerPlacement({ sessionId, sessionKey, state: "active" });
const reclaimGate = createDeferred();
const reclaimGate = createDeferredCore();
const reclaim = vi.fn(async () => {
await reclaimGate.promise;
placement = workerPlacement({ sessionId, sessionKey, state: "reclaimed" });
@@ -569,9 +569,9 @@ test("alias archive lets the canonical cloud reclaim barrier reenter without dea
const sessionId = "session-archive-cloud-alias";
await writeSessionStore({ entries: { [sessionKey]: sessionStoreEntry(sessionId) } });
let placement = workerPlacement({ sessionId, sessionKey, state: "active" });
const reclaimEntered = createDeferred();
const allowNestedReclaim = createDeferred();
const contenderRelease = createDeferred();
const reclaimEntered = createDeferredCore();
const allowNestedReclaim = createDeferredCore();
const contenderRelease = createDeferredCore();
const reclaim = vi.fn(async () => {
reclaimEntered.resolve();
await allowNestedReclaim.promise;
@@ -752,7 +752,7 @@ test("sessions.patch returns UNAVAILABLE when terminal persistence fails", async
const sessionId = "session-archive-persistence-failure";
const runId = "run-archive-persistence-failure";
await writeSessionStore({ entries: { [sessionKey]: sessionStoreEntry(sessionId) } });
const persistence = createDeferred();
const persistence = createDeferredCore();
const active = activeRunContext({ runId, sessionId, sessionKey, persistence });
try {
const archive = directSessionReq(
@@ -862,7 +862,7 @@ test("sessions.patchMany prepares independent archive drains concurrently and re
[secondKey]: sessionStoreEntry(secondSessionId),
},
});
const firstDrained = createDeferred();
const firstDrained = createDeferredCore();
const firstRelease = vi.fn();
const secondRelease = vi.fn();
const beginInferenceSessionDrain = vi.fn((sessionId: string) => ({
@@ -1012,7 +1012,7 @@ test("sessions.patch rejects a generation replaced after the exact preparation r
const sessionId = "session-archive-generation-race";
const runId = "run-archive-generation-race";
await writeSessionStore({ entries: { [sessionKey]: sessionStoreEntry(sessionId) } });
const persistence = createDeferred();
const persistence = createDeferredCore();
const active = activeRunContext({ runId, sessionId, sessionKey, persistence });
let placement = workerPlacement({ sessionId, sessionKey, state: "active" });
const dispatch = vi.fn();

Some files were not shown because too many files have changed in this diff Show More