@code-yeongyu/senpi 2026.11.6-2 → 2026.11.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/bundle/chunks/{bun-extension-importer-RCGPQTI2.js → bun-extension-importer-GQ6IKEXD.js} +2 -2
- package/dist/bundle/chunks/{chunk-GSKCWXXG.js → chunk-3CRPNPTR.js} +1 -1
- package/dist/bundle/chunks/{chunk-RQ6CHXQ2.js → chunk-3TZQXZKH.js} +1 -1
- package/dist/bundle/chunks/{chunk-QN2BHP3M.js → chunk-44BJPS5I.js} +1 -1
- package/dist/bundle/chunks/{chunk-WGRKM3N6.js → chunk-45MVD7BU.js} +1 -1
- package/dist/bundle/chunks/chunk-4JIBEZZE.js +106 -0
- package/dist/bundle/chunks/{chunk-CF5OGBC4.js → chunk-4NYNMAYF.js} +1 -1
- package/dist/bundle/chunks/{chunk-X5ZVYNOL.js → chunk-4UR6UFBH.js} +1 -1
- package/dist/bundle/chunks/{chunk-LNPAT22L.js → chunk-527Q2UYM.js} +9 -8
- package/dist/bundle/chunks/{chunk-HLM46XEB.js → chunk-622VYTRI.js} +1 -1
- package/dist/bundle/chunks/{chunk-GKAYPJ4E.js → chunk-7PROV6BB.js} +1 -1
- package/dist/bundle/chunks/{chunk-4E7GDG4H.js → chunk-7VMEE62L.js} +1 -1
- package/dist/bundle/chunks/{chunk-ECW7VBMB.js → chunk-HXNXISJD.js} +1 -1
- package/dist/bundle/chunks/{chunk-C7OKUC7L.js → chunk-K3UHGDUQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-47PPZKPO.js → chunk-LM6DOWQH.js} +4 -4
- package/dist/bundle/chunks/chunk-LPYBKMPT.js +2 -0
- package/dist/bundle/chunks/{chunk-2FDW2LQL.js → chunk-M7GF73FO.js} +2 -2
- package/dist/bundle/chunks/{chunk-D5MRJWUK.js → chunk-OCMGRBJ5.js} +221 -229
- package/dist/bundle/chunks/{chunk-TIPKAMSS.js → chunk-SGAFIMAU.js} +1 -1
- package/dist/bundle/chunks/{chunk-7PSBD5KS.js → chunk-STGOYIXC.js} +1 -1
- package/dist/bundle/chunks/{chunk-DSWDJ7HT.js → chunk-WQ4RBPMS.js} +1 -1
- package/dist/bundle/chunks/{chunk-7III44PV.js → chunk-WX2HB4DD.js} +1 -1
- package/dist/bundle/chunks/chunk-XZDCMDUH.js +2 -0
- package/dist/bundle/chunks/{chunk-GNSMNSL7.js → chunk-Y5L4UFMI.js} +2 -2
- package/dist/bundle/chunks/{cli-main-T74YJGIF.js → cli-main-E4NDWAUD.js} +1 -1
- package/dist/bundle/chunks/{dispatch-BAK2YZKD.js → dispatch-VDIYSXQN.js} +1 -1
- package/dist/bundle/chunks/{hand-entry-AYRUGE2A.js → hand-entry-5X5Z5Y3D.js} +1 -1
- package/dist/bundle/chunks/{headless-host-ES74ZB6M.js → headless-host-YXUGONR3.js} +1 -1
- package/dist/bundle/chunks/{host-command-YRXZE4TV.js → host-command-VHX2ILLM.js} +1 -1
- package/dist/bundle/chunks/{host-session-command-N7IN7ZDV.js → host-session-command-P3MRW63Z.js} +1 -1
- package/dist/bundle/chunks/interactive-mode-XUSBLLWI.js +2 -0
- package/dist/bundle/chunks/main-3TWVKTJN.js +2 -0
- package/dist/bundle/chunks/{multi-session-host-XSUJDHFZ.js → multi-session-host-HRGM66PY.js} +20 -17
- package/dist/bundle/chunks/{package-manager-cli-GLUNPQJU.js → package-manager-cli-WSH7U4YE.js} +1 -1
- package/dist/bundle/chunks/{role-RRFFHZF5.js → role-4BUU46VW.js} +3 -3
- package/dist/bundle/chunks/{rotation-stream-BN2YK2MC.js → rotation-stream-TODBIHXJ.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-OAPIV46G.js +2 -0
- package/dist/bundle/chunks/{run-attached-tui-W236SEOR.js → run-attached-tui-MXCC5IZR.js} +1 -1
- package/dist/bundle/chunks/{runtime-session-OBXYK4PI.js → runtime-session-VO3X4OE3.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-B2EJTBOE.js → schedule-command-MX56D6UE.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-YIMLHGLG.js → session-control-endpoint-IL6ERD4U.js} +1 -1
- package/dist/bundle/chunks/{session-picker-E6ZONUJB.js → session-picker-6VRC25MJ.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +114 -110
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session-runtime.d.ts +2 -0
- package/dist/core/agent-session-runtime.js +9 -2
- package/dist/core/agent-session-services.d.ts +2 -0
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session.d.ts +32 -3
- package/dist/core/agent-session.js +142 -29
- package/dist/core/credential-pool/rotation-slots.d.ts +3 -3
- package/dist/core/credential-pool/state-store.d.ts +1 -1
- package/dist/core/egress/classify.d.ts +8 -3
- package/dist/core/egress/classify.js +177 -158
- package/dist/core/egress/console-redactor.d.ts +7 -0
- package/dist/core/egress/console-redactor.js +74 -0
- package/dist/core/egress/credentials.d.ts +73 -0
- package/dist/core/egress/credentials.js +20 -0
- package/dist/core/egress/device-custody.d.ts +1 -1
- package/dist/core/egress/device-custody.js +18 -15
- package/dist/core/egress/device-proxy-call.d.ts +59 -0
- package/dist/core/egress/device-proxy-call.js +148 -0
- package/dist/core/egress/device-proxy-lost-calls.d.ts +27 -0
- package/dist/core/egress/device-proxy-lost-calls.js +28 -0
- package/dist/core/egress/device-proxy-ports.d.ts +49 -0
- package/dist/core/egress/device-proxy-ports.js +2 -0
- package/dist/core/egress/device-proxy-request.d.ts +34 -0
- package/dist/core/egress/device-proxy-request.js +69 -0
- package/dist/core/egress/device-proxy-waits.d.ts +40 -0
- package/dist/core/egress/device-proxy-waits.js +67 -0
- package/dist/core/egress/device-proxy.d.ts +3 -0
- package/dist/core/egress/device-proxy.js +214 -0
- package/dist/core/egress/endpoint.js +2 -1
- package/dist/core/egress/entry-verify.d.ts +13 -0
- package/dist/core/egress/entry-verify.js +33 -0
- package/dist/core/egress/hpke.d.ts +63 -0
- package/dist/core/egress/hpke.js +192 -0
- package/dist/core/egress/key-policy-template.d.ts +7 -1
- package/dist/core/egress/ledger-schema.d.ts +80 -0
- package/dist/core/egress/ledger-schema.js +117 -0
- package/dist/core/egress/ledger.d.ts +55 -0
- package/dist/core/egress/ledger.js +159 -0
- package/dist/core/egress/pinned-infra.d.ts +23 -2
- package/dist/core/egress/pinned-infra.js +9 -2
- package/dist/core/egress/placement-claim.d.ts +69 -0
- package/dist/core/egress/placement-claim.js +115 -0
- package/dist/core/egress/pool-state.d.ts +18 -0
- package/dist/core/egress/pool-state.js +5 -0
- package/dist/core/egress/redact.d.ts +10 -0
- package/dist/core/egress/redact.js +134 -0
- package/dist/core/egress/sealed-format.d.ts +101 -0
- package/dist/core/egress/sealed-format.js +174 -0
- package/dist/core/egress/sealed-source.d.ts +35 -0
- package/dist/core/egress/sealed-source.js +140 -0
- package/dist/core/egress/verified-keys.js +1 -1
- package/dist/core/egress/wire.d.ts +228 -0
- package/dist/core/egress/wire.js +49 -0
- package/dist/core/extensions/builtin/ask-user/escape-residue.d.ts +50 -0
- package/dist/core/extensions/builtin/ask-user/escape-residue.js +113 -0
- package/dist/core/extensions/builtin/ask-user/extension.js +7 -1
- package/dist/core/extensions/builtin/ask-user/resume.js +2 -1
- package/dist/core/extensions/builtin/ask-user/tool.d.ts +3 -0
- package/dist/core/extensions/builtin/ask-user/tool.js +8 -0
- package/dist/core/extensions/builtin/goal/index.js +46 -0
- package/dist/core/extensions/builtin/goal/stop-pause.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/stop-pause.js +4 -2
- package/dist/core/extensions/builtin/monitor-state-event.d.ts +26 -0
- package/dist/core/extensions/builtin/monitor-state-event.js +2 -0
- package/dist/core/extensions/builtin/permission-system/index.js +10 -4
- package/dist/core/extensions/builtin/permission-system/preset-registry.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/preset-registry.js +11 -0
- package/dist/core/extensions/builtin/permission-system/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/permission-system/settings.js +10 -1
- package/dist/core/extensions/builtin/terminal/background-age.d.ts +25 -0
- package/dist/core/extensions/builtin/terminal/background-age.js +91 -0
- package/dist/core/extensions/builtin/terminal/extension-state.d.ts +1 -1
- package/dist/core/extensions/builtin/terminal/extension-state.js +21 -3
- package/dist/core/extensions/builtin/terminal/notify.d.ts +6 -0
- package/dist/core/extensions/builtin/terminal/notify.js +39 -5
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +9 -2
- package/dist/core/extensions/builtin/terminal/session-bundle.js +36 -1
- package/dist/core/extensions/builtin/terminal/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/terminal/settings.js +8 -0
- package/dist/core/extensions/builtin/terminal/tools/background-auto-reap.d.ts +15 -0
- package/dist/core/extensions/builtin/terminal/tools/background-auto-reap.js +87 -0
- package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +3 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.js +44 -15
- package/dist/core/extensions/builtin/terminal/tools/child-placement.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/tools/child-placement.js +43 -6
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts +14 -2
- package/dist/core/extensions/bun-extension-importer.js +4 -3
- package/dist/core/extensions/bun-extension-load-turns.d.ts +4 -0
- package/dist/core/extensions/bun-extension-load-turns.js +45 -0
- package/dist/core/extensions/bun-extension-registry.d.ts +1 -0
- package/dist/core/extensions/bun-extension-registry.js +19 -1
- package/dist/core/extensions/loader.js +5 -0
- package/dist/core/extensions/session-control-types.d.ts +15 -0
- package/dist/core/extensions/session-control-types.js +11 -0
- package/dist/core/extensions/session-dialog-api.d.ts +5 -0
- package/dist/core/extensions/session-dialog-api.js +13 -0
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/external-admission.d.ts +16 -2
- package/dist/core/external-admission.js +22 -4
- package/dist/core/permission-decision.d.ts +22 -0
- package/dist/core/permission-decision.js +53 -0
- package/dist/core/permission-mode.d.ts +56 -0
- package/dist/core/permission-mode.js +133 -0
- package/dist/core/retry-fallback/controller-types.d.ts +6 -0
- package/dist/core/retry-fallback/controller.d.ts +9 -0
- package/dist/core/retry-fallback/controller.js +34 -3
- package/dist/core/retry-fallback/unusable.d.ts +25 -1
- package/dist/core/retry-fallback/unusable.js +87 -2
- package/dist/core/retry-fallback/usage-limit.d.ts +6 -1
- package/dist/core/retry-fallback/usage-limit.js +12 -4
- package/dist/core/sdk.d.ts +6 -1
- package/dist/core/sdk.js +3 -0
- package/dist/core/session-log.js +1 -1
- package/dist/core/stall-warning.d.ts +41 -0
- package/dist/core/stall-warning.js +72 -0
- package/dist/core/terminal-settings.d.ts +1 -0
- package/dist/core/turn-origin.d.ts +31 -0
- package/dist/core/turn-origin.js +64 -0
- package/dist/modes/interactive/components/remote-delivery-message.d.ts +2 -1
- package/dist/modes/interactive/components/remote-delivery-message.js +13 -5
- package/dist/modes/rpc/admit-external-message-command.d.ts +37 -0
- package/dist/modes/rpc/admit-external-message-command.js +61 -0
- package/dist/modes/rpc/admit-external-message-wire.d.ts +42 -0
- package/dist/modes/rpc/admit-external-message-wire.js +55 -0
- package/dist/modes/rpc/client-input-handler.d.ts +2 -0
- package/dist/modes/rpc/client-input-handler.js +2 -0
- package/dist/modes/rpc/connection-handler.js +30 -5
- package/dist/modes/rpc/connection-roles.d.ts +6 -0
- package/dist/modes/rpc/connection-roles.js +13 -0
- package/dist/modes/rpc/delegated-drive-origin.d.ts +9 -0
- package/dist/modes/rpc/delegated-drive-origin.js +16 -0
- package/dist/modes/rpc/effect-commands.d.ts +7 -1
- package/dist/modes/rpc/host-bare-endpoint-registration.d.ts +7 -0
- package/dist/modes/rpc/host-bare-endpoint-registration.js +35 -0
- package/dist/modes/rpc/host-capabilities.d.ts +2 -0
- package/dist/modes/rpc/host-capabilities.js +3 -0
- package/dist/modes/rpc/host-handover-parked.d.ts +11 -0
- package/dist/modes/rpc/host-handover-parked.js +17 -0
- package/dist/modes/rpc/host-handover-reopen.js +18 -6
- package/dist/modes/rpc/host-handover-resident-writer.d.ts +16 -0
- package/dist/modes/rpc/host-handover-resident-writer.js +57 -0
- package/dist/modes/rpc/host-idle-handover.js +1 -0
- package/dist/modes/rpc/host-warm.d.ts +16 -1
- package/dist/modes/rpc/host-warm.js +33 -6
- package/dist/modes/rpc/method-classes-schema-delivery.d.ts +32 -0
- package/dist/modes/rpc/method-classes-schema-delivery.js +22 -0
- package/dist/modes/rpc/method-classes-schema-session.d.ts +36 -0
- package/dist/modes/rpc/method-classes-schema-session.js +3 -0
- package/dist/modes/rpc/method-classes-schema.d.ts +36 -0
- package/dist/modes/rpc/method-classes.d.ts +2 -0
- package/dist/modes/rpc/method-classes.js +4 -0
- package/dist/modes/rpc/multi-session-host.js +6 -1
- package/dist/modes/rpc/permission-preset-command.d.ts +6 -0
- package/dist/modes/rpc/permission-preset-command.js +27 -0
- package/dist/modes/rpc/rpc-input-validation.js +4 -3
- package/dist/modes/rpc/rpc-mutation-response-types.d.ts +7 -0
- package/dist/modes/rpc/rpc-response-types.d.ts +2 -1
- package/dist/modes/rpc/rpc-session-command-types.d.ts +6 -1
- package/dist/modes/rpc/rpc-session-event-types.d.ts +5 -2
- package/dist/modes/rpc/rpc-session-state-types.d.ts +2 -1
- package/dist/modes/rpc/rpc-session-state.js +2 -0
- package/dist/modes/rpc/session-attachment-commands.js +3 -3
- package/dist/modes/rpc/session-event-writer-connections.js +1 -0
- package/dist/modes/rpc/session-event-writer.d.ts +1 -1
- package/dist/modes/rpc/session-registry-attach.d.ts +0 -9
- package/dist/modes/rpc/session-registry-attach.js +16 -3
- package/dist/modes/rpc/session-registry-types.d.ts +2 -0
- package/dist/modes/rpc/session-registry.d.ts +2 -0
- package/dist/modes/rpc/session-registry.js +16 -3
- package/dist/modes/rpc/session-router-close.js +43 -6
- package/dist/modes/rpc/session-router-context.js +2 -0
- package/dist/modes/rpc/session-router-occupancy.js +2 -11
- package/dist/modes/rpc/session-router-open-profile.js +4 -0
- package/dist/modes/rpc/session-router-open.d.ts +1 -1
- package/dist/modes/rpc/session-router-open.js +6 -17
- package/dist/modes/rpc/session-router-residency.d.ts +24 -0
- package/dist/modes/rpc/session-router-residency.js +90 -0
- package/dist/modes/rpc/session-router-routing.js +7 -1
- package/dist/modes/rpc/session-status.js +4 -1
- package/dist/modes/rpc/session-worker.js +4 -0
- package/dist/modes/rpc/tool-child/terminal-jobs.d.ts +1 -0
- package/dist/modes/rpc/tool-child/terminal-jobs.js +17 -1
- package/dist/modes/rpc/worker-session-registry.js +5 -2
- package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
- package/docs/engine-socket/fixtures/rpc-inbound-samples.json +29 -2
- package/docs/extensions.md +12 -0
- package/docs/rpc.md +129 -12
- package/docs/terminal-tools.md +25 -1
- package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
- package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-C7HEEBFH.js +0 -2
- package/dist/bundle/chunks/chunk-XCMII2VQ.js +0 -98
- package/dist/bundle/chunks/interactive-mode-B5SQDLH7.js +0 -2
- package/dist/bundle/chunks/main-UQFVFCNY.js +0 -2
- package/dist/bundle/chunks/rpc-mode-JYN3E7P7.js +0 -2
|
@@ -19,165 +19,183 @@ const COST = [
|
|
|
19
19
|
"tiers[].cacheWrite",
|
|
20
20
|
];
|
|
21
21
|
const PERCENTILES = ["", ".p50", ".p75", ".p90", ".p99"];
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
22
|
+
function compatFields() {
|
|
23
|
+
return [
|
|
24
|
+
"supportsWebSearch",
|
|
25
|
+
"supportsStore",
|
|
26
|
+
"supportsDeveloperRole",
|
|
27
|
+
"supportsReasoningEffort",
|
|
28
|
+
"supportsUsageInStreaming",
|
|
29
|
+
"supportsFinishReason",
|
|
30
|
+
"maxTokensField",
|
|
31
|
+
"requiresToolResultName",
|
|
32
|
+
"requiresAssistantAfterToolResult",
|
|
33
|
+
"requiresThinkingAsText",
|
|
34
|
+
"requiresReasoningContentOnAssistantMessages",
|
|
35
|
+
"supportsDisabledThinking",
|
|
36
|
+
"thinkingFormat",
|
|
37
|
+
"chatTemplateKwargs.{key}",
|
|
38
|
+
"chatTemplateKwargs.*",
|
|
39
|
+
"chatTemplateKwargs.*.$var",
|
|
40
|
+
"chatTemplateKwargs.*.omitWhenOff",
|
|
41
|
+
"cacheControlFormat",
|
|
42
|
+
...[
|
|
43
|
+
"allow_fallbacks",
|
|
44
|
+
"require_parameters",
|
|
45
|
+
"data_collection",
|
|
46
|
+
"zdr",
|
|
47
|
+
"enforce_distillable_text",
|
|
48
|
+
"order[]",
|
|
49
|
+
"only[]",
|
|
50
|
+
"ignore[]",
|
|
51
|
+
"quantizations[]",
|
|
52
|
+
"sort",
|
|
53
|
+
"sort.by",
|
|
54
|
+
"sort.partition",
|
|
55
|
+
...["prompt", "completion", "image", "audio", "request"].map((part) => `max_price.${part}`),
|
|
56
|
+
...PERCENTILES.map((suffix) => `preferred_min_throughput${suffix}`),
|
|
57
|
+
...PERCENTILES.map((suffix) => `preferred_max_latency${suffix}`),
|
|
58
|
+
].map((field) => `openRouterRouting.${field}`),
|
|
59
|
+
"vercelGatewayRouting.only[]",
|
|
60
|
+
"vercelGatewayRouting.order[]",
|
|
61
|
+
"zaiToolStream",
|
|
62
|
+
"supportsStrictMode",
|
|
63
|
+
"toolCallFormat",
|
|
64
|
+
"sendSessionAffinityHeaders",
|
|
65
|
+
"deferredToolsMode",
|
|
66
|
+
"sessionAffinityFormat",
|
|
67
|
+
"supportsLongCacheRetention",
|
|
68
|
+
"supportsForcedToolChoice",
|
|
69
|
+
"webSearchToolType",
|
|
70
|
+
"supportsWebSocket",
|
|
71
|
+
"supportsRemoteCompactionV2",
|
|
72
|
+
"supportsWebSearchPreview",
|
|
73
|
+
"supportsToolSearch",
|
|
74
|
+
"supportsEagerToolInputStreaming",
|
|
75
|
+
"supportsCacheControlOnTools",
|
|
76
|
+
"supportsTemperature",
|
|
77
|
+
"supportsToolChoice",
|
|
78
|
+
"forceAdaptiveThinking",
|
|
79
|
+
"allowEmptySignature",
|
|
80
|
+
"supportsToolReferences",
|
|
81
|
+
"allowedFallbackModels[].provider",
|
|
82
|
+
"allowedFallbackModels[].model",
|
|
83
|
+
...COST.map((field) => `allowedFallbackModels[].cost.${field}`),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
const THINKING_LEVEL_MAP = [
|
|
87
|
+
"thinkingLevelMap.off",
|
|
88
|
+
"thinkingLevelMap.minimal",
|
|
89
|
+
"thinkingLevelMap.low",
|
|
90
|
+
"thinkingLevelMap.medium",
|
|
91
|
+
"thinkingLevelMap.high",
|
|
92
|
+
"thinkingLevelMap.xhigh",
|
|
93
|
+
"thinkingLevelMap.max",
|
|
83
94
|
];
|
|
84
|
-
const THINKING_LEVEL_MAP = ["off", "minimal", "low", "medium", "high", "xhigh", "max"].map((level) => `thinkingLevelMap.${level}`);
|
|
85
95
|
const INPUT_LIMITS = [
|
|
86
|
-
"maxRequestBytes",
|
|
87
|
-
"images.resize.maxWidth",
|
|
88
|
-
"images.resize.maxHeight",
|
|
89
|
-
"images.resize.maxBytes",
|
|
90
|
-
"images.resize.jpegQuality",
|
|
91
|
-
"images.maxPerMessage",
|
|
92
|
-
"images.maxPerRequest",
|
|
93
|
-
]
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
96
|
+
"inputLimits.maxRequestBytes",
|
|
97
|
+
"inputLimits.images.resize.maxWidth",
|
|
98
|
+
"inputLimits.images.resize.maxHeight",
|
|
99
|
+
"inputLimits.images.resize.maxBytes",
|
|
100
|
+
"inputLimits.images.resize.jpegQuality",
|
|
101
|
+
"inputLimits.images.maxPerMessage",
|
|
102
|
+
"inputLimits.images.maxPerRequest",
|
|
103
|
+
];
|
|
104
|
+
function modelDefinition() {
|
|
105
|
+
return {
|
|
106
|
+
...fields("public", [
|
|
107
|
+
"id",
|
|
108
|
+
"name",
|
|
109
|
+
"upstreamModelId",
|
|
110
|
+
"serviceTier",
|
|
111
|
+
"promptPreset",
|
|
112
|
+
"recoverTextToolCalls",
|
|
113
|
+
"api",
|
|
114
|
+
"reasoning",
|
|
115
|
+
...THINKING_LEVEL_MAP,
|
|
116
|
+
"defaultThinkingLevel",
|
|
117
|
+
"input[]",
|
|
118
|
+
...INPUT_LIMITS,
|
|
119
|
+
...COST.map((field) => `cost.${field}`),
|
|
120
|
+
"promptCache.short",
|
|
121
|
+
"promptCache.long",
|
|
122
|
+
"contextWindow",
|
|
123
|
+
"maxTokens",
|
|
124
|
+
"cacheRetention",
|
|
125
|
+
...compatFields().map((field) => `compat.${field}`),
|
|
126
|
+
"headers.{key}",
|
|
127
|
+
"extraBody.{key}",
|
|
128
|
+
]),
|
|
129
|
+
baseUrl: "endpoint",
|
|
130
|
+
"headers.*": "sealed",
|
|
131
|
+
"extraBody.*": "forces-device",
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function modelOverride() {
|
|
135
|
+
return {
|
|
136
|
+
...fields("public", [
|
|
137
|
+
"name",
|
|
138
|
+
"promptPreset",
|
|
139
|
+
"recoverTextToolCalls",
|
|
140
|
+
"reasoning",
|
|
141
|
+
...THINKING_LEVEL_MAP,
|
|
142
|
+
"thinkingLevelMapMode",
|
|
143
|
+
"input[]",
|
|
144
|
+
...INPUT_LIMITS,
|
|
145
|
+
...compatFields().map((field) => `compat.${field}`),
|
|
146
|
+
...COST.map((field) => `cost.${field}`),
|
|
147
|
+
"promptCache.short",
|
|
148
|
+
"promptCache.long",
|
|
149
|
+
"contextWindow",
|
|
150
|
+
"maxTokens",
|
|
151
|
+
"cacheRetention",
|
|
152
|
+
"headers.{key}",
|
|
153
|
+
"extraBody.{key}",
|
|
154
|
+
]),
|
|
155
|
+
"headers.*": "sealed",
|
|
156
|
+
"extraBody.*": "forces-device",
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function providerFields() {
|
|
160
|
+
return {
|
|
161
|
+
...fields("public", [
|
|
162
|
+
"name",
|
|
163
|
+
"disabled",
|
|
164
|
+
"api",
|
|
165
|
+
"headers.{key}",
|
|
166
|
+
"extraBody.{key}",
|
|
167
|
+
"cacheRetention",
|
|
168
|
+
"authHeader",
|
|
169
|
+
"whitelist[]",
|
|
170
|
+
"blacklist[]",
|
|
171
|
+
"hideFreeModels",
|
|
172
|
+
...compatFields().map((field) => `compat.${field}`),
|
|
173
|
+
"credentials.rotation",
|
|
174
|
+
"credentials.affinity",
|
|
175
|
+
"credentials.accountStrategy",
|
|
176
|
+
"credentials.cooldownBaseMs",
|
|
177
|
+
"credentials.cooldownCapMs",
|
|
178
|
+
"credentials.slots.{key}",
|
|
179
|
+
"modelOverrides.{key}",
|
|
180
|
+
]),
|
|
181
|
+
baseUrl: "endpoint",
|
|
182
|
+
apiKey: "sealed",
|
|
183
|
+
"headers.*": "sealed",
|
|
184
|
+
"extraBody.*": "forces-device",
|
|
185
|
+
"credentials.slots.*.value": "sealed",
|
|
186
|
+
"credentials.slots.*.env": "device-only",
|
|
187
|
+
...prefixed("models[].", modelDefinition()),
|
|
188
|
+
...prefixed("modelOverrides.*.", modelOverride()),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
175
191
|
/** models.json, keyed by schema path: `.` nests, `[]` is an array item, `.{key}` a record key, `.*` a record value. */
|
|
176
|
-
export
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
192
|
+
export function modelsJsonFieldClasses() {
|
|
193
|
+
return {
|
|
194
|
+
"disabledProviders[]": "public",
|
|
195
|
+
"providers.{key}": "public",
|
|
196
|
+
...prefixed("providers.*.", providerFields()),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
181
199
|
/** Fields the runtime types add on top of the models.json schema (`model-config.ts`). */
|
|
182
200
|
export const MODELS_JSON_TYPE_ONLY_FIELDS = {
|
|
183
201
|
"providers.*.models[].samplingParams.{key}": "public",
|
|
@@ -185,8 +203,9 @@ export const MODELS_JSON_TYPE_ONLY_FIELDS = {
|
|
|
185
203
|
"providers.*.modelOverrides.*.samplingParams.{key}": "public",
|
|
186
204
|
"providers.*.modelOverrides.*.samplingParams.*": "forces-device",
|
|
187
205
|
};
|
|
188
|
-
export function classifyModelsJsonField(path) {
|
|
189
|
-
|
|
206
|
+
export function classifyModelsJsonField(path, classes = modelsJsonFieldClasses()) {
|
|
207
|
+
const typeOnly = MODELS_JSON_TYPE_ONLY_FIELDS;
|
|
208
|
+
return classes[path] ?? typeOnly[path];
|
|
190
209
|
}
|
|
191
210
|
function fields(fieldClass, paths) {
|
|
192
211
|
return Object.fromEntries(paths.map((path) => [path, fieldClass]));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Redactor } from "./redact.ts";
|
|
2
|
+
type ConsoleTarget = object;
|
|
3
|
+
export declare function sealedWindowCount(): number;
|
|
4
|
+
export declare function runSealed<T>(redactor: Redactor, work: () => Promise<T>): Promise<T>;
|
|
5
|
+
export declare function installConsoleRedactor(target: ConsoleTarget): void;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=console-redactor.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { format } from "node:util";
|
|
3
|
+
const INSTALLED = Symbol.for("senpi.egress.consoleRedactorInstalled");
|
|
4
|
+
// no-module-state: console-redactor-install
|
|
5
|
+
const sealedContext = new AsyncLocalStorage();
|
|
6
|
+
// no-module-state: sealed-window-counter
|
|
7
|
+
let sealedWindows = 0;
|
|
8
|
+
export function sealedWindowCount() {
|
|
9
|
+
return sealedWindows;
|
|
10
|
+
}
|
|
11
|
+
export async function runSealed(redactor, work) {
|
|
12
|
+
sealedWindows++;
|
|
13
|
+
try {
|
|
14
|
+
return await sealedContext.run(redactor, work);
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
sealedWindows--;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Console members that never write a line; wrapping them would only break them (Node and Bun consoles). */
|
|
21
|
+
const NON_WRITING_MEMBERS = [
|
|
22
|
+
"context",
|
|
23
|
+
"createTask",
|
|
24
|
+
"profile",
|
|
25
|
+
"profileEnd",
|
|
26
|
+
"timeStamp",
|
|
27
|
+
"takeHeapSnapshot",
|
|
28
|
+
"record",
|
|
29
|
+
"recordEnd",
|
|
30
|
+
"screenshot",
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* The console members to wrap: every function-valued member except constructors (`Console`), `_`-prefixed
|
|
34
|
+
* stream internals (`_stdoutErrorHandler`) and the known non-writing members. Anything unknown is wrapped, so a
|
|
35
|
+
* writing method no list names (Bun's `console.write`) cannot bypass the redactor.
|
|
36
|
+
*/
|
|
37
|
+
function consoleMethods(target) {
|
|
38
|
+
const names = new Set();
|
|
39
|
+
for (let level = target; level !== null && level !== Object.prototype; level = Object.getPrototypeOf(level)) {
|
|
40
|
+
for (const name of Object.getOwnPropertyNames(level)) {
|
|
41
|
+
if (name === "constructor" || name.startsWith("_") || /^[A-Z]/u.test(name))
|
|
42
|
+
continue;
|
|
43
|
+
if (NON_WRITING_MEMBERS.some((member) => member === name))
|
|
44
|
+
continue;
|
|
45
|
+
if (typeof target[name] === "function")
|
|
46
|
+
names.add(name);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return [...names];
|
|
50
|
+
}
|
|
51
|
+
export function installConsoleRedactor(target) {
|
|
52
|
+
const console = target;
|
|
53
|
+
if (console[INSTALLED])
|
|
54
|
+
return;
|
|
55
|
+
console[INSTALLED] = true;
|
|
56
|
+
for (const method of consoleMethods(target)) {
|
|
57
|
+
const original = console[method];
|
|
58
|
+
const keepsCondition = method === "assert";
|
|
59
|
+
console[method] = (...args) => {
|
|
60
|
+
const redactor = sealedContext.getStore();
|
|
61
|
+
if (redactor === undefined) {
|
|
62
|
+
if (sealedWindows > 0)
|
|
63
|
+
return;
|
|
64
|
+
return original.apply(target, args);
|
|
65
|
+
}
|
|
66
|
+
if (keepsCondition) {
|
|
67
|
+
const [condition, ...message] = args;
|
|
68
|
+
return original.call(target, condition, redactor.redact(format(...message)));
|
|
69
|
+
}
|
|
70
|
+
return original.call(target, redactor.redact(format(...args)));
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=console-redactor.js.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { HpkeWrap, ProviderId, SecretField } from "./sealed-format.ts";
|
|
2
|
+
export type { SecretField } from "./sealed-format.ts";
|
|
3
|
+
export interface SecretLease extends Disposable {
|
|
4
|
+
/** Throws SecretNotLeased for a field outside this lease, or after dispose. */
|
|
5
|
+
value(field: SecretField): string;
|
|
6
|
+
readonly expiresAt?: number;
|
|
7
|
+
/** Drops references and zeroes the byte buffers (custody design 3.4). */
|
|
8
|
+
[Symbol.dispose](): void;
|
|
9
|
+
}
|
|
10
|
+
/** Audit only; asserted by the brain. */
|
|
11
|
+
export interface ReleaseScope {
|
|
12
|
+
readonly sessionId: string;
|
|
13
|
+
readonly callId: string;
|
|
14
|
+
readonly purpose: "model-call" | "aux-call";
|
|
15
|
+
}
|
|
16
|
+
export interface CredentialSource {
|
|
17
|
+
resolve(providerId: ProviderId, entryDigest: string, fields: readonly SecretField[], scope: ReleaseScope): Promise<SecretLease>;
|
|
18
|
+
}
|
|
19
|
+
/** Registry-signed `{account, placementId, epoch, recipientPkHash, exp <= 60 s}`. */
|
|
20
|
+
export interface EpochLeaseToken {
|
|
21
|
+
readonly token: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ReleaseRequest {
|
|
24
|
+
readonly accountId: string;
|
|
25
|
+
readonly providerId: ProviderId;
|
|
26
|
+
/** Must equal the head entry's. */
|
|
27
|
+
readonly entryDigest: string;
|
|
28
|
+
readonly fields: readonly SecretField[];
|
|
29
|
+
readonly lease: EpochLeaseToken;
|
|
30
|
+
readonly recipientPk: Uint8Array;
|
|
31
|
+
readonly scope: ReleaseScope;
|
|
32
|
+
}
|
|
33
|
+
export interface ReleaseConfigRequest {
|
|
34
|
+
readonly accountId: string;
|
|
35
|
+
readonly objectHash: string;
|
|
36
|
+
readonly lease: EpochLeaseToken;
|
|
37
|
+
readonly recipientPk: Uint8Array;
|
|
38
|
+
readonly scope: ReleaseScope;
|
|
39
|
+
}
|
|
40
|
+
export type ReleaseFailure = "stale_snapshot" | "epoch_mismatch" | "owner_revoked" | "owner_withdrawn" | "unknown_field" | "unresolved_field" | "key_destroyed" | "wrap_missing" | "unavailable" | "denied";
|
|
41
|
+
export interface HeadRef {
|
|
42
|
+
readonly version: number;
|
|
43
|
+
readonly objectHash: string;
|
|
44
|
+
}
|
|
45
|
+
export type ReleaseResult = {
|
|
46
|
+
readonly ok: true;
|
|
47
|
+
readonly items: readonly HpkeWrap[];
|
|
48
|
+
readonly head: HeadRef;
|
|
49
|
+
} | {
|
|
50
|
+
readonly ok: false;
|
|
51
|
+
readonly code: ReleaseFailure;
|
|
52
|
+
readonly head?: HeadRef;
|
|
53
|
+
};
|
|
54
|
+
export interface Unsealer {
|
|
55
|
+
release(req: ReleaseRequest): Promise<ReleaseResult>;
|
|
56
|
+
/** One item: the ProviderConfigPlain sealed to recipientPk. K_cfg and K_proj are never released. */
|
|
57
|
+
releaseConfig(req: ReleaseConfigRequest): Promise<ReleaseResult>;
|
|
58
|
+
}
|
|
59
|
+
export declare class SecretNotLeased extends Error {
|
|
60
|
+
readonly field: SecretField;
|
|
61
|
+
constructor(field: SecretField);
|
|
62
|
+
}
|
|
63
|
+
export type CredentialWaitReason = ReleaseFailure | "config-churn";
|
|
64
|
+
/**
|
|
65
|
+
* A sealed release that did not produce a value. It is never a plaintext fallback: the caller routes the step to a
|
|
66
|
+
* device or waits. `retryable` marks the refusals that clear on their own (custody design 3.3 and the L844 rule).
|
|
67
|
+
*/
|
|
68
|
+
export declare class CredentialWait extends Error {
|
|
69
|
+
readonly reason: CredentialWaitReason;
|
|
70
|
+
readonly retryable: boolean;
|
|
71
|
+
constructor(reason: CredentialWaitReason, retryable: boolean);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class SecretNotLeased extends Error {
|
|
2
|
+
constructor(field) {
|
|
3
|
+
super(`secret not leased: ${field}`);
|
|
4
|
+
this.name = "SecretNotLeased";
|
|
5
|
+
this.field = field;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A sealed release that did not produce a value. It is never a plaintext fallback: the caller routes the step to a
|
|
10
|
+
* device or waits. `retryable` marks the refusals that clear on their own (custody design 3.3 and the L844 rule).
|
|
11
|
+
*/
|
|
12
|
+
export class CredentialWait extends Error {
|
|
13
|
+
constructor(reason, retryable) {
|
|
14
|
+
super(`sealed credential unavailable: ${reason}`);
|
|
15
|
+
this.name = "CredentialWait";
|
|
16
|
+
this.reason = reason;
|
|
17
|
+
this.retryable = retryable;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Why a provider must stay on the device whatever the sidecar asks for (custody gate H1, M1).
|
|
3
3
|
*
|
|
4
4
|
* The models.json schema accepts unknown keys at every level, so the walk here applies
|
|
5
|
-
* `
|
|
5
|
+
* `modelsJsonFieldClasses()` to the concrete provider object with whitelist semantics: a key the
|
|
6
6
|
* table does not name, at any depth, keeps the provider on the device instead of reaching the brain.
|
|
7
7
|
*/
|
|
8
8
|
import type { ModelsJsonProvider } from "../model-config-schema.ts";
|
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
* Why a provider must stay on the device whatever the sidecar asks for (custody gate H1, M1).
|
|
3
3
|
*
|
|
4
4
|
* The models.json schema accepts unknown keys at every level, so the walk here applies
|
|
5
|
-
* `
|
|
5
|
+
* `modelsJsonFieldClasses()` to the concrete provider object with whitelist semantics: a key the
|
|
6
6
|
* table does not name, at any depth, keeps the provider on the device instead of reaching the brain.
|
|
7
7
|
*/
|
|
8
|
-
import { classifyModelsJsonField,
|
|
8
|
+
import { classifyModelsJsonField, modelsJsonFieldClasses, MODELS_JSON_TYPE_ONLY_FIELDS, } from "./classify.js";
|
|
9
9
|
import { splitEndpoint } from "./endpoint.js";
|
|
10
|
-
const STOPS_WALK =
|
|
10
|
+
const STOPS_WALK = ["sealed", "device-only"];
|
|
11
11
|
/** Every path in the tables plus each of its ancestors (`a.b[].c` -> `a`, `a.b`, `a.b[]`, `a.b[].c`). */
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
function knownPaths(classes) {
|
|
13
|
+
return new Set([...Object.keys(classes), ...Object.keys(MODELS_JSON_TYPE_ONLY_FIELDS)].flatMap((path) => [
|
|
14
|
+
...[...path.matchAll(/[.[]/g)].map((boundary) => path.slice(0, boundary.index)),
|
|
15
|
+
path,
|
|
16
|
+
]));
|
|
17
|
+
}
|
|
16
18
|
/** A property name that would read as path syntax (`a.b`, `m[]`, `*`, `{key}`) is never a declared field. */
|
|
17
19
|
const PATH_SYNTAX = /[.[\]*{}]/;
|
|
18
20
|
function isPlainObject(value) {
|
|
19
21
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
22
|
}
|
|
21
|
-
function walk(value, path, reasons) {
|
|
22
|
-
const fieldClass = classifyModelsJsonField(path);
|
|
23
|
+
function walk(value, path, reasons, known, classes) {
|
|
24
|
+
const fieldClass = classifyModelsJsonField(path, classes);
|
|
23
25
|
if (fieldClass === "forces-device") {
|
|
24
26
|
const sampling = path.endsWith("samplingParams.*");
|
|
25
27
|
if (!sampling)
|
|
@@ -28,11 +30,11 @@ function walk(value, path, reasons) {
|
|
|
28
30
|
reasons.add("sampling-params");
|
|
29
31
|
return;
|
|
30
32
|
}
|
|
31
|
-
if (fieldClass !== undefined && STOPS_WALK.
|
|
33
|
+
if (fieldClass !== undefined && STOPS_WALK.some((stop) => stop === fieldClass))
|
|
32
34
|
return;
|
|
33
35
|
if (Array.isArray(value)) {
|
|
34
36
|
for (const item of value)
|
|
35
|
-
walk(item, `${path}[]`, reasons);
|
|
37
|
+
walk(item, `${path}[]`, reasons, known, classes);
|
|
36
38
|
return;
|
|
37
39
|
}
|
|
38
40
|
if (!isPlainObject(value)) {
|
|
@@ -40,11 +42,11 @@ function walk(value, path, reasons) {
|
|
|
40
42
|
reasons.add("undeclared-field");
|
|
41
43
|
return;
|
|
42
44
|
}
|
|
43
|
-
const isRecord = classifyModelsJsonField(`${path}.{key}
|
|
45
|
+
const isRecord = classifyModelsJsonField(`${path}.{key}`, classes) !== undefined;
|
|
44
46
|
for (const [key, child] of Object.entries(value)) {
|
|
45
47
|
const childPath = isRecord ? `${path}.*` : `${path}.${key}`;
|
|
46
|
-
if ((isRecord || !PATH_SYNTAX.test(key)) &&
|
|
47
|
-
walk(child, childPath, reasons);
|
|
48
|
+
if ((isRecord || !PATH_SYNTAX.test(key)) && known.has(childPath))
|
|
49
|
+
walk(child, childPath, reasons, known, classes);
|
|
48
50
|
else
|
|
49
51
|
reasons.add("undeclared-field");
|
|
50
52
|
}
|
|
@@ -63,7 +65,8 @@ function hasModelHeaderCollision(provider) {
|
|
|
63
65
|
/** Empty when sealed custody may serve the provider. */
|
|
64
66
|
export function deviceCustodyReasons(provider) {
|
|
65
67
|
const reasons = new Set();
|
|
66
|
-
|
|
68
|
+
const classes = modelsJsonFieldClasses();
|
|
69
|
+
walk(provider, "providers.*", reasons, knownPaths(classes), classes);
|
|
67
70
|
if (provider.baseUrl !== undefined && !splitEndpoint(provider.baseUrl).ok)
|
|
68
71
|
reasons.add("unsplittable-base-url");
|
|
69
72
|
for (const model of provider.models ?? []) {
|