@sema-agent/client-core 0.77.1 → 0.77.2

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.
Files changed (382) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +5 -4
  3. package/dist/abortableSleep.d.ts +0 -28
  4. package/dist/abortableSleep.js +0 -28
  5. package/dist/adapt/arms.d.ts +0 -46
  6. package/dist/adapt/arms.js +9 -544
  7. package/dist/adapt/ids.d.ts +0 -58
  8. package/dist/adapt/ids.js +0 -63
  9. package/dist/adapt/instanceLedger.d.ts +0 -25
  10. package/dist/adapt/instanceLedger.js +0 -20
  11. package/dist/adapt/panelTasks.d.ts +0 -69
  12. package/dist/adapt/panelTasks.js +0 -95
  13. package/dist/adapt/textSegmentAuthority.d.ts +1 -137
  14. package/dist/adapt/textSegmentAuthority.js +0 -54
  15. package/dist/adapt/textStream.d.ts +0 -252
  16. package/dist/adapt/textStream.js +2 -281
  17. package/dist/adapt/toolCards.d.ts +0 -46
  18. package/dist/adapt/toolCards.js +0 -23
  19. package/dist/adapt/turnFlags.d.ts +0 -54
  20. package/dist/adapt/turnFlags.js +1 -17
  21. package/dist/adapt/wireShapes.d.ts +0 -92
  22. package/dist/adapt/wireShapes.js +0 -83
  23. package/dist/adapt.d.ts +0 -55
  24. package/dist/adapt.js +1 -120
  25. package/dist/adapter/activeRunSelfHeal.d.ts +22 -515
  26. package/dist/adapter/activeRunSelfHeal.js +10 -625
  27. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -305
  28. package/dist/adapter/downstream/eventToSdkMessage.js +2 -867
  29. package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -314
  30. package/dist/adapter/downstream/terminalToSdkResult.js +13 -560
  31. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +0 -95
  32. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -31
  33. package/dist/adapter/runStream.d.ts +0 -206
  34. package/dist/adapter/runStream.js +6 -596
  35. package/dist/adapter/types.d.ts +0 -111
  36. package/dist/adapter/types.js +0 -29
  37. package/dist/agentSession/backgroundView.d.ts +0 -106
  38. package/dist/agentSession/backgroundView.js +3 -49
  39. package/dist/agentSession/contract.d.ts +0 -98
  40. package/dist/agentSession/contract.js +0 -12
  41. package/dist/agentsWireCaps.d.ts +0 -72
  42. package/dist/agentsWireCaps.js +4 -72
  43. package/dist/approvalsStreamLiveCapability.d.ts +0 -25
  44. package/dist/approvalsStreamLiveCapability.js +0 -31
  45. package/dist/argvFlagValue.d.ts +0 -33
  46. package/dist/argvFlagValue.js +3 -35
  47. package/dist/attachmentsWireCaps.d.ts +0 -127
  48. package/dist/attachmentsWireCaps.js +0 -144
  49. package/dist/autoModeUnavailable.d.ts +0 -120
  50. package/dist/autoModeUnavailable.js +0 -144
  51. package/dist/classifierStatus.d.ts +0 -72
  52. package/dist/classifierStatus.js +0 -167
  53. package/dist/classifierVerdictWire.d.ts +0 -54
  54. package/dist/classifierVerdictWire.js +0 -133
  55. package/dist/clientContextWireCaps.d.ts +0 -37
  56. package/dist/clientContextWireCaps.js +0 -36
  57. package/dist/clientSlice.d.ts +0 -63
  58. package/dist/clientSlice.js +0 -45
  59. package/dist/cloudConfigWireCaps.d.ts +0 -86
  60. package/dist/cloudConfigWireCaps.js +2 -65
  61. package/dist/compensations.d.ts +0 -52
  62. package/dist/compensations.js +2 -63
  63. package/dist/controlRouter.d.ts +2 -208
  64. package/dist/controlRouter.js +1 -129
  65. package/dist/coreValuePorts.d.ts +0 -84
  66. package/dist/coreValuePorts.js +0 -29
  67. package/dist/decideReceipt.d.ts +0 -110
  68. package/dist/decideReceipt.js +0 -84
  69. package/dist/detachWire.d.ts +0 -130
  70. package/dist/detachWire.js +1 -130
  71. package/dist/deviceExecutorManagementCapability.d.ts +2 -35
  72. package/dist/deviceExecutorManagementCapability.js +1 -37
  73. package/dist/diagnostics.d.ts +0 -8
  74. package/dist/diagnostics.js +0 -8
  75. package/dist/diff/patch.d.ts +0 -17
  76. package/dist/diff/patch.js +0 -19
  77. package/dist/effectiveFacts.d.ts +0 -40
  78. package/dist/effectiveFacts.js +0 -22
  79. package/dist/effortWire.d.ts +0 -11
  80. package/dist/effortWire.js +0 -12
  81. package/dist/engineAgentPanelStore.d.ts +0 -169
  82. package/dist/engineAgentPanelStore.js +13 -293
  83. package/dist/engineCapReader.d.ts +0 -62
  84. package/dist/engineCapReader.js +1 -43
  85. package/dist/engineCapsCache.d.ts +0 -177
  86. package/dist/engineCapsCache.js +0 -199
  87. package/dist/engineCapsGenerationGuard.d.ts +0 -2
  88. package/dist/engineCapsGenerationGuard.js +0 -11
  89. package/dist/engineErrorCodes.d.ts +1 -316
  90. package/dist/engineErrorCodes.js +0 -427
  91. package/dist/engineHttpTools.d.ts +0 -29
  92. package/dist/engineHttpTools.js +0 -29
  93. package/dist/engineIdentity.d.ts +0 -83
  94. package/dist/engineIdentity.js +0 -88
  95. package/dist/engineInlineTaskStats.d.ts +0 -57
  96. package/dist/engineInlineTaskStats.js +1 -42
  97. package/dist/engineNoticeCodes.d.ts +0 -190
  98. package/dist/engineNoticeCodes.js +0 -182
  99. package/dist/engineSessionParam.d.ts +0 -30
  100. package/dist/engineSessionParam.js +0 -52
  101. package/dist/engineToolLabelStore.d.ts +0 -29
  102. package/dist/engineToolLabelStore.js +0 -31
  103. package/dist/engineWireSdk.d.ts +0 -90
  104. package/dist/engineWireSdk.js +0 -74
  105. package/dist/engineWireTarget.d.ts +0 -14
  106. package/dist/engineWireTarget.js +0 -39
  107. package/dist/env/localeGeo.d.ts +0 -12
  108. package/dist/env/localeGeo.js +2 -77
  109. package/dist/env/localeTag.d.ts +0 -34
  110. package/dist/env/localeTag.js +0 -32
  111. package/dist/env/uiLanguage.d.ts +0 -13
  112. package/dist/env/uiLanguage.js +0 -25
  113. package/dist/envFlag.d.ts +0 -37
  114. package/dist/envFlag.js +0 -40
  115. package/dist/executionLaneCapability.d.ts +0 -48
  116. package/dist/executionLaneCapability.js +0 -54
  117. package/dist/finalVerifyWire.d.ts +0 -67
  118. package/dist/finalVerifyWire.js +3 -43
  119. package/dist/fleet/fleetLedger.d.ts +0 -308
  120. package/dist/fleet/fleetLedger.js +10 -429
  121. package/dist/fleet/fleetProjection.d.ts +0 -240
  122. package/dist/fleet/fleetProjection.js +0 -189
  123. package/dist/fleet/fleetRowAgentType.d.ts +0 -6
  124. package/dist/fleet/fleetRowAgentType.js +1 -32
  125. package/dist/fleet/workflowSizeWarning.d.ts +0 -47
  126. package/dist/fleet/workflowSizeWarning.js +1 -46
  127. package/dist/fleetAgentPanelProjection.d.ts +0 -48
  128. package/dist/fleetAgentPanelProjection.js +8 -173
  129. package/dist/fleetTaskDesc.d.ts +0 -39
  130. package/dist/fleetTaskDesc.js +0 -69
  131. package/dist/forkWireCaps.d.ts +0 -23
  132. package/dist/forkWireCaps.js +1 -24
  133. package/dist/gateOutcome.d.ts +0 -140
  134. package/dist/gateOutcome.js +0 -85
  135. package/dist/gateVocabulary.d.ts +0 -114
  136. package/dist/gateVocabulary.js +1 -161
  137. package/dist/goalStopHook.d.ts +0 -127
  138. package/dist/goalStopHook.js +0 -178
  139. package/dist/headlessPermissionModeWire.d.ts +0 -76
  140. package/dist/headlessPermissionModeWire.js +1 -155
  141. package/dist/headlessReconnectWire.d.ts +0 -84
  142. package/dist/headlessReconnectWire.js +13 -67
  143. package/dist/hitl/approvalDecisionNoteAudit.d.ts +0 -49
  144. package/dist/hitl/approvalDecisionNoteAudit.js +0 -56
  145. package/dist/hitl/approvalOutcomeNote.d.ts +0 -2
  146. package/dist/hitl/approvalOutcomeNote.js +0 -20
  147. package/dist/hitl/approvalResolution.d.ts +0 -113
  148. package/dist/hitl/approvalResolution.js +0 -66
  149. package/dist/hitl/approvalsFeed.d.ts +0 -183
  150. package/dist/hitl/approvalsFeed.js +12 -243
  151. package/dist/hitl/armedGateRegistry.d.ts +0 -55
  152. package/dist/hitl/armedGateRegistry.js +0 -146
  153. package/dist/hitl/askGateWire.d.ts +0 -86
  154. package/dist/hitl/askGateWire.js +1 -95
  155. package/dist/hitl/askParkRowRouting.d.ts +0 -123
  156. package/dist/hitl/askParkRowRouting.js +1 -89
  157. package/dist/hitl/crashConverged.d.ts +0 -148
  158. package/dist/hitl/crashConverged.js +0 -214
  159. package/dist/hitl/editedRuleTextPrecheck.d.ts +0 -109
  160. package/dist/hitl/editedRuleTextPrecheck.js +0 -71
  161. package/dist/hitl/frameRouter.d.ts +0 -134
  162. package/dist/hitl/frameRouter.js +6 -378
  163. package/dist/hitl/gateIdentity.d.ts +0 -39
  164. package/dist/hitl/gateIdentity.js +0 -41
  165. package/dist/hitl/gateLedger.d.ts +0 -267
  166. package/dist/hitl/gateLedger.js +0 -121
  167. package/dist/hitl/hitlBridge.d.ts +7 -431
  168. package/dist/hitl/hitlBridge.js +7 -476
  169. package/dist/hitl/hitlHostSurface.d.ts +0 -150
  170. package/dist/hitl/hitlHostSurface.js +0 -169
  171. package/dist/hitl/livePendingAsk.d.ts +0 -91
  172. package/dist/hitl/livePendingAsk.js +0 -74
  173. package/dist/hitl/localAllowRule.d.ts +0 -62
  174. package/dist/hitl/localAllowRule.js +1 -33
  175. package/dist/hitl/parkOwnership.d.ts +0 -56
  176. package/dist/hitl/parkOwnership.js +0 -22
  177. package/dist/hitl/parkResolver.d.ts +3 -88
  178. package/dist/hitl/parkResolver.js +8 -349
  179. package/dist/hitl/parkRowBirthWait.d.ts +2 -26
  180. package/dist/hitl/parkRowBirthWait.js +3 -93
  181. package/dist/hitl/persistedRulesWire.d.ts +13 -358
  182. package/dist/hitl/persistedRulesWire.js +0 -310
  183. package/dist/hitl/planReviewWire.d.ts +4 -176
  184. package/dist/hitl/planReviewWire.js +9 -312
  185. package/dist/hitl/resumeRunningCard.d.ts +0 -105
  186. package/dist/hitl/resumeRunningCard.js +0 -105
  187. package/dist/hitl/sessionPolicyWire.d.ts +11 -191
  188. package/dist/hitl/sessionPolicyWire.js +0 -149
  189. package/dist/hitl/suspendedReopen.d.ts +3 -24
  190. package/dist/hitl/suspendedReopen.js +0 -14
  191. package/dist/hitl/toolApprovalWire.d.ts +5 -1308
  192. package/dist/hitl/toolApprovalWire.js +5 -945
  193. package/dist/hooksWireCaps.d.ts +0 -38
  194. package/dist/hooksWireCaps.js +0 -190
  195. package/dist/host.d.ts +0 -105
  196. package/dist/host.js +0 -33
  197. package/dist/hostEnv.d.ts +0 -14
  198. package/dist/hostEnv.js +0 -13
  199. package/dist/imagesWireCaps.d.ts +0 -21
  200. package/dist/imagesWireCaps.js +0 -22
  201. package/dist/index.d.ts +0 -134
  202. package/dist/index.js +0 -476
  203. package/dist/interactiveHalt.d.ts +5 -153
  204. package/dist/interactiveHalt.js +0 -111
  205. package/dist/interactiveToolsWire.d.ts +0 -62
  206. package/dist/interactiveToolsWire.js +1 -67
  207. package/dist/leaderConflict.d.ts +0 -59
  208. package/dist/leaderConflict.js +0 -48
  209. package/dist/limitsWire.d.ts +0 -125
  210. package/dist/limitsWire.js +2 -120
  211. package/dist/liveInitToolFace.d.ts +0 -77
  212. package/dist/liveInitToolFace.js +1 -109
  213. package/dist/liveModelCatalog.d.ts +0 -52
  214. package/dist/liveModelCatalog.js +0 -48
  215. package/dist/liveQuestionStore.d.ts +0 -87
  216. package/dist/liveQuestionStore.js +1 -56
  217. package/dist/mcpLiveness.d.ts +0 -151
  218. package/dist/mcpLiveness.js +0 -122
  219. package/dist/mcpPanel.d.ts +0 -104
  220. package/dist/mcpPanel.js +0 -49
  221. package/dist/mcpReconnect.d.ts +0 -58
  222. package/dist/mcpReconnect.js +0 -69
  223. package/dist/mcpWireCaps.d.ts +0 -55
  224. package/dist/mcpWireCaps.js +1 -13
  225. package/dist/memoryComplianceCapability.d.ts +3 -57
  226. package/dist/memoryComplianceCapability.js +0 -57
  227. package/dist/memoryEntriesWire.d.ts +6 -198
  228. package/dist/memoryEntriesWire.js +0 -144
  229. package/dist/memoryOriginCapability.d.ts +3 -53
  230. package/dist/memoryOriginCapability.js +0 -50
  231. package/dist/memorySpecWire.d.ts +0 -116
  232. package/dist/memorySpecWire.js +0 -150
  233. package/dist/model/catalog.d.ts +0 -111
  234. package/dist/model/catalog.js +0 -87
  235. package/dist/model/catalogLoader.d.ts +0 -114
  236. package/dist/model/catalogLoader.js +2 -139
  237. package/dist/model/modelSupplyRules.d.ts +1 -55
  238. package/dist/model/modelSupplyRules.js +0 -62
  239. package/dist/model/providerAuth.d.ts +0 -103
  240. package/dist/model/providerAuth.js +2 -38
  241. package/dist/model/providerCatalog.d.ts +0 -45
  242. package/dist/model/providerCatalog.js +0 -37
  243. package/dist/model/providerPresets.d.ts +0 -33
  244. package/dist/model/providerPresets.js +2 -91
  245. package/dist/model/tierVocabulary.d.ts +0 -31
  246. package/dist/model/tierVocabulary.js +0 -27
  247. package/dist/modelBudgetRule.d.ts +0 -39
  248. package/dist/modelBudgetRule.js +0 -39
  249. package/dist/modelCapabilityProbe.d.ts +0 -175
  250. package/dist/modelCapabilityProbe.js +0 -147
  251. package/dist/modelWireCaps.d.ts +0 -13
  252. package/dist/modelWireCaps.js +0 -13
  253. package/dist/notifications.d.ts +0 -233
  254. package/dist/notifications.js +14 -492
  255. package/dist/oneShotWireCaps.d.ts +0 -34
  256. package/dist/oneShotWireCaps.js +0 -35
  257. package/dist/ownKey.d.ts +0 -33
  258. package/dist/ownKey.js +0 -33
  259. package/dist/panelRunningHistory.d.ts +0 -28
  260. package/dist/panelRunningHistory.js +0 -43
  261. package/dist/peerFrames.d.ts +0 -71
  262. package/dist/peerFrames.js +0 -168
  263. package/dist/peerLaneCapability.d.ts +0 -44
  264. package/dist/peerLaneCapability.js +0 -52
  265. package/dist/permissionRuleIssue.d.ts +0 -30
  266. package/dist/permissionRuleIssue.js +0 -78
  267. package/dist/permissionRulesWriteCapability.d.ts +0 -46
  268. package/dist/permissionRulesWriteCapability.js +0 -54
  269. package/dist/permissionWireCaps.d.ts +0 -37
  270. package/dist/permissionWireCaps.js +0 -37
  271. package/dist/postureKnob.d.ts +0 -71
  272. package/dist/postureKnob.js +0 -86
  273. package/dist/principalWire.d.ts +0 -17
  274. package/dist/principalWire.js +0 -17
  275. package/dist/printToolResultFrame.d.ts +0 -100
  276. package/dist/printToolResultFrame.js +0 -33
  277. package/dist/promptProfileWireCaps.d.ts +0 -13
  278. package/dist/promptProfileWireCaps.js +0 -13
  279. package/dist/readFacePosture.d.ts +0 -43
  280. package/dist/readFacePosture.js +0 -46
  281. package/dist/request/printNotification.d.ts +0 -20
  282. package/dist/request/printNotification.js +0 -55
  283. package/dist/request/taskRequest.d.ts +0 -249
  284. package/dist/request/taskRequest.js +6 -498
  285. package/dist/resumeRefusalCopy.d.ts +0 -136
  286. package/dist/resumeRefusalCopy.js +1 -117
  287. package/dist/retainBackgroundWireCaps.d.ts +0 -48
  288. package/dist/retainBackgroundWireCaps.js +0 -48
  289. package/dist/retryStatus.d.ts +2 -221
  290. package/dist/retryStatus.js +0 -107
  291. package/dist/rewindWireCaps.d.ts +0 -27
  292. package/dist/rewindWireCaps.js +0 -24
  293. package/dist/runCancelContext.d.ts +1 -20
  294. package/dist/runCancelContext.js +0 -34
  295. package/dist/runTerminal.d.ts +0 -273
  296. package/dist/runTerminal.js +0 -177
  297. package/dist/sandboxWire.d.ts +0 -38
  298. package/dist/sandboxWire.js +0 -82
  299. package/dist/scenarioWire.d.ts +0 -60
  300. package/dist/scenarioWire.js +0 -68
  301. package/dist/scratchpadWireCaps.d.ts +0 -11
  302. package/dist/scratchpadWireCaps.js +0 -32
  303. package/dist/sdkWireTransit.d.ts +0 -38
  304. package/dist/sdkWireTransit.js +0 -30
  305. package/dist/seam.d.ts +18 -853
  306. package/dist/seam.js +0 -52
  307. package/dist/seatContract.d.ts +0 -555
  308. package/dist/seatContract.js +5 -304
  309. package/dist/selfOrchestrationDenial.d.ts +0 -189
  310. package/dist/selfOrchestrationDenial.js +0 -162
  311. package/dist/selfOrchestrationWireCaps.d.ts +0 -38
  312. package/dist/selfOrchestrationWireCaps.js +0 -38
  313. package/dist/sessionMap.d.ts +0 -60
  314. package/dist/sessionMap.js +0 -37
  315. package/dist/sessionMemoryStatus.d.ts +11 -114
  316. package/dist/sessionMemoryStatus.js +0 -112
  317. package/dist/sessionModelLatch.d.ts +0 -29
  318. package/dist/sessionModelLatch.js +0 -40
  319. package/dist/sessionPolicyCapability.d.ts +3 -53
  320. package/dist/sessionPolicyCapability.js +0 -52
  321. package/dist/sessionSlot.d.ts +0 -26
  322. package/dist/sessionSlot.js +0 -17
  323. package/dist/skillsWireCaps.d.ts +0 -87
  324. package/dist/skillsWireCaps.js +0 -38
  325. package/dist/sqlEngineCapability.d.ts +0 -118
  326. package/dist/sqlEngineCapability.js +0 -134
  327. package/dist/sseIdleTriage.d.ts +0 -79
  328. package/dist/sseIdleTriage.js +1 -80
  329. package/dist/steering.d.ts +0 -54
  330. package/dist/steering.js +0 -63
  331. package/dist/subagent/engineCompactWire.d.ts +0 -34
  332. package/dist/subagent/engineCompactWire.js +4 -134
  333. package/dist/subagent/engineDelegatedPrompt.d.ts +0 -31
  334. package/dist/subagent/engineDelegatedPrompt.js +1 -103
  335. package/dist/subagent/engineRowStopGate.d.ts +0 -20
  336. package/dist/subagent/engineRowStopGate.js +0 -49
  337. package/dist/subagent/engineSubagentOutput.d.ts +0 -7
  338. package/dist/subagent/engineSubagentOutput.js +1 -51
  339. package/dist/subagent/engineSubagentResume.d.ts +2 -279
  340. package/dist/subagent/engineSubagentResume.js +2 -129
  341. package/dist/subagent/engineSubagentSteer.d.ts +0 -26
  342. package/dist/subagent/engineSubagentSteer.js +0 -63
  343. package/dist/subagent/engineSubagentTail.d.ts +0 -38
  344. package/dist/subagent/engineSubagentTail.js +2 -110
  345. package/dist/subagent/engineTaskHandleWire.d.ts +6 -67
  346. package/dist/subagent/engineTaskHandleWire.js +0 -126
  347. package/dist/subagent/subagentOwnerAbsence.d.ts +0 -2
  348. package/dist/subagent/subagentOwnerAbsence.js +0 -25
  349. package/dist/subagentContentStore.d.ts +3 -260
  350. package/dist/subagentContentStore.js +7 -540
  351. package/dist/systemReminderTag.d.ts +0 -49
  352. package/dist/systemReminderTag.js +0 -61
  353. package/dist/toolResult.d.ts +1 -211
  354. package/dist/toolResult.js +1 -358
  355. package/dist/toolRoster.d.ts +0 -140
  356. package/dist/toolRoster.js +0 -66
  357. package/dist/typePins.d.ts +0 -46
  358. package/dist/types/engineState.d.ts +0 -71
  359. package/dist/types/engineState.js +0 -16
  360. package/dist/ultracodeWireCaps.d.ts +0 -75
  361. package/dist/ultracodeWireCaps.js +0 -92
  362. package/dist/unrefTimer.d.ts +0 -27
  363. package/dist/webSearchBackendCapability.d.ts +0 -72
  364. package/dist/webSearchBackendCapability.js +0 -79
  365. package/dist/webSearchWireCaps.d.ts +0 -37
  366. package/dist/webSearchWireCaps.js +0 -34
  367. package/dist/websearch/searchProviderPresets.d.ts +0 -81
  368. package/dist/websearch/searchProviderPresets.js +0 -27
  369. package/dist/wireErrorTriage.d.ts +4 -160
  370. package/dist/wireErrorTriage.js +0 -171
  371. package/dist/wireRefusalCopy.d.ts +0 -28
  372. package/dist/wireRefusalCopy.js +0 -28
  373. package/dist/workflow.d.ts +0 -40
  374. package/dist/workflow.js +0 -52
  375. package/dist/workflowClient.d.ts +0 -122
  376. package/dist/workflowClient.js +8 -360
  377. package/dist/workflowMonitor.d.ts +2 -72
  378. package/dist/workflowMonitor.js +0 -26
  379. package/dist/writeProtectionCapability.d.ts +0 -112
  380. package/dist/writeProtectionCapability.js +0 -109
  381. package/docs/INTEGRATION-CLIENTS.md +30 -1
  382. package/package.json +1 -1
@@ -1,135 +1,36 @@
1
- /**
2
- * catalog.ts — **模型 provider 目录的三层源解析**(design/160 需求②,2026-07-31)。
3
- *
4
- * ## 它解决什么
5
- *
6
- * `providerPresets.json` 是**编译进包的静态表**:加一家 provider、改一个 model 的 cap,都得发一次
7
- * client-core。而三端(CLI / web / 桌面)要的是同一份目录、可在线更新、离线仍能用。本模块把
8
- * 设计档 §需求② 的三层源做成一个**纯解析器**:
9
- *
10
- * ```
11
- * ① 线上目录(URL 由调用方传入 —— 本文件零默认地址,见下「为什么不写死 URL」)
12
- * ↓ 拉取失败 / 离线 / 校验不过(整份弃用)
13
- * ② 包内兜底 = PROVIDER_PRESETS(零改动即兜底)
14
- * ↓
15
- * ③ 用户本地覆盖(自定义 provider,合并语义:同 id 用户 > 线上 > 包内)
16
- * ```
17
- *
18
- * ## 四条设计纪律(每条都在 pure 门 MC 段有断言)
19
- *
20
- * 1. **零 Node、零自发网络**:本文件不 import 任何 `node:*`,也**不碰全局 `fetch`** ——
21
- * 网络能力由调用方注入 `fetchJson` 端口。宿主没给 ⇒ 线上腿整条不启用(`reason: 'no-fetch-port'`),
22
- * 而不是「偷偷换个方式做」(与 host.ts 的缺席语义同一条纪律)。
23
- * ⇒ 桌面渲染进程 / 浏览器 / TUI 用同一份代码,各自注入自己的传输。
24
- * 2. **绝不半解析**(设计档明写):`schemaVersion` 超出支持区间、`providers` 不是数组、
25
- * **任何一行**形状不合格 ⇒ **整份**线上目录弃用走兜底。半解析 = 用户拿到一张自己也说不清
26
- * 是哪一版的表。
27
- * 3. **来源标注是产品位不是调试位**:返回值恒带 `source` 与 `online.{ok,reason}`。端据此渲
28
- * 「目录为内置版本(离线)」——「静默用兜底」在本层必须是**可观测**的,否则用户会以为看到的
29
- * 是最新表([honest-absence-not-fabricated-zero])。
30
- * 4. **诚实缺席**:`staleness` 只在真吃到线上目录时在场;`ageMs` 只在调用方给了 `nowMs`
31
- * 且 `generatedAt` 可解析时在场。不知道就是键缺席,绝不 `?? 0`,也绝不偷读时钟
32
- * (时钟是宿主资产,与 `AdapterContext.now` 同一条口径)。
33
- *
34
- * ## 为什么不写死线上 URL
35
- *
36
- * 目录仓位(设计档待裁点 3:`sema-agent/model-catalog` 公开仓 or release asset)**候 clay 裁**。
37
- * 机制先行、地址后填:URL 由调用方从配置/settings 传入。本文件里出现任何默认地址,都会让
38
- * 「还没定的仓位」提前变成事实契约。https-only 是硬校验(目录是会被下载并影响**出站地址**的
39
- * 数据,明文信道下可被改写成钓鱼网关)。
40
- *
41
- * ## 本批不做(留口注释,别当遗漏)
42
- *
43
- * · **缓存与 ETag**:`~/.sema/cache/model-catalog.json` + ETag/304 + 新鲜窗 + `localGeneratedAt`
44
- * 防降级(设计档 pi 调研节)。落盘是宿主能力(fs 在 host.ts 的 `FsPort`),所以缓存层应当是
45
- * **本模块之上**的一层:调用方拿 `resolveModelCatalog` 的结果自行落盘,并把上次的 `generatedAt`
46
- * 与新拉到的比较后决定是否替换。⇒ 加缓存时**不需要**改本文件的形状,只需在 `fetchJson` 注入
47
- * 处做 ETag,并在外层加一个「旧远端压不过新包」的比较。
48
- * · **签名 / sha256**:同上,属传输层与目录产出方的约定(设计档待裁点 3)。
49
- * · **`oauth` / `subscribe` 字段**:设计档待裁点 3b。本批只加纯链接位 `consoleUrl`/`signupUrl`
50
- * (见 providerPresets.ts),授权码流/设备码流一律不进。
51
- *
52
- * ## probe 复用面评估(设计档 §需求②-C「复用面」;只评估不搬,搬迁下一批做)
53
- *
54
- * 桌面端 onboard 要「选 provider → 填 key → 探活」,探活那一步现在只在壳树。按
55
- * [multiclient-migration-batch-discipline](模块级状态与读写口同包)逐个评估,结论如下 ——
56
- * 这是下一批的搬迁清单,坐标为壳树 `src/sema/onboard/`:
57
- *
58
- * | 文件 | 结论 | 依据 |
59
- * |---|---|---|
60
- * | `probePlan.ts`(139 行) | ✅ **整搬,零改造** | 零 import、零模块级状态、纯函数四件(`buildVerdictRequest` / `extractApiError` / `looksLikeModelError` / `judgeMessagesProbe`)。判决表本身就是「三端必须一致」的那部分。 |
61
- * | `probeProvider.ts`(223 行) | ⚠️ **拆搬**:判定+请求编排进包、传输与 TLS 留端 | ①裸 `fetch`/`AbortController`/`setTimeout` ⇒ 改注入 `fetchImpl`(本包既有姿势:`limitsWire`/`detachWire`/`liveInitToolFace` 的 `opts.fetchImpl`);②`ensureProxyBootstrap()` 动态 import 壳的 `utils/proxy.js`(`configureGlobalAgents`)= **Node undici 专属**,浏览器无此概念 ⇒ 留端,做成可选的「拨号前置钩子」端口;③`isCertError`/`applySystemTlsTrust`(壳 `tlsTrust.ts`,读系统钥匙串 + 设 `NODE_EXTRA_CA_CERTS`)= 纯 Node ⇒ 留端,做成可选的「一次性重试钩子」;④`nearestListed()` 与 `unwrapFetchError()` 是纯函数 ⇒ 直接进包。搬后包内出口 ≈ `probeProvider({ baseUrl, api, apiKey, modelId }, { fetchImpl, beforeDial?, retryOnCertError? })`。 |
62
- * | `detectSources.ts`(524 行) | ❌ **本批不搬** | 它整个是**宿主文件系统扫描器**:`node:fs`(existsSync/readdirSync/readFileSync/statSync)+ `node:os` homedir + `node:path` + `process.env` + 两个外部解析器(`jsonc-parser`/`yaml`)+ 壳内 `ccConfigFallback`。可搬的只有「读到的配置 → `ImportableProvider` 的分类/归一逻辑」那一小半,而它与扫描代码是逐行交织的。⇒ 要搬得先在壳里把「扫描(IO)」与「分类(纯)」拆开,是独立一批的量。**桌面端不阻塞**:桌面 onboard 的导入源探测本就该是主进程的活(与 CLI 同为 Node 侧),复用价值远低于 probe 两件。 |
63
- * | `onboardZeroModel.ts`(2.8K) | 🔶 **顺路可搬** | 已有独立单测(`onboardZeroModel.test.ts`),看形状是纯判定;搬前需确认零壳态依赖。 |
64
- * | `applyOnboard.ts` / `OnboardWizard.tsx` / `BigStepTitle.tsx` / `ccSwitchReader.ts` | ❌ 属端 | 落盘编排 / Ink 渲染 / 读 cc-switch sqlite —— 宿主辖区,桌面端各写各的渲染器(设计档 §C 与 pi 的 `AuthInteraction` seam 同一心智)。 |
65
- *
66
- * 搬迁批建议顺序:`probePlan`(零风险打头,先让包里有判决表)→ `probeProvider` 拆搬(带
67
- * fetchImpl 注入 + 两个可选钩子端口)→ `onboardZeroModel` → detectSources 拆分单列一批。
68
- */
69
1
  import { type ProviderPreset } from './providerPresets.js';
70
- /** 支持的目录 schemaVersion 区间(闭区间)。产目录那一方按这个区间发版。 */
71
2
  export declare const CATALOG_SCHEMA_VERSION_MIN = 1;
72
3
  export declare const CATALOG_SCHEMA_VERSION_MAX = 1;
73
- /** 线上目录文档的信封形。`providers` 与包内表**同形**(ProviderPreset),所以两层可直接按 id 合并。 */
74
4
  export interface OnlineCatalogDoc {
75
5
  schemaVersion: number;
76
- /** 目录生成时刻(ISO8601)。用于端渲新鲜度;不可解析也不弃用整份(它不是契约位)。 */
77
6
  generatedAt: string;
78
7
  providers: ProviderPreset[];
79
8
  }
80
- /**
81
- * 结果的来源标注 = **最高优先级的在场层**:
82
- * · `merged` —— 用户覆盖层真的贡献了行(不管线上腿成没成);
83
- * · `online` —— 线上目录被接受且无用户覆盖;
84
- * · `bundled` —— 只有包内表(离线 / 线上被拒 / 没配 URL)。
85
- */
86
9
  export type CatalogSource = 'online' | 'bundled' | 'merged';
87
- /** 线上腿被拒的**具体**理由(端可据此分诊:是没配、是离线、还是目录本身坏了)。 */
88
10
  export type CatalogRejectReason = 'no-online-url' | 'no-fetch-port' | 'insecure-url' | 'fetch-failed' | 'payload-not-object' | 'schema-version-missing' | 'schema-version-unsupported' | 'generated-at-missing' | 'providers-not-array' | 'provider-row-invalid';
89
- /** 线上腿的结局。`ok: true` 时不带 `reason`(枚举互斥)。 */
90
11
  export interface CatalogOnlineOutcome {
91
12
  ok: boolean;
92
13
  reason?: CatalogRejectReason;
93
- /**
94
- * 拒绝细节(人话,给分诊用)。🔴 只放判决相关的短语与被截断的错误 message,
95
- * **绝不回显载荷本身**([credential-error-path-leak]:错误路径是凭证外泄的经典入口;
96
- * 目录 URL 本身是公开物,但宿主注入的 fetchJson 可能带鉴权头,所以异常只取 message 前段)。
97
- */
98
14
  detail?: string;
99
15
  }
100
- /** 线上目录的新鲜度。只在真吃到线上目录时在场。 */
101
16
  export interface CatalogStaleness {
102
- /** 目录自述的生成时刻,原样透传(烂串也原样给端,由端决定怎么说)。 */
103
17
  generatedAt: string;
104
- /** 距今毫秒。只在调用方给了 `nowMs` 且 `generatedAt` 可解析时在场 —— 不知道就键缺席。 */
105
18
  ageMs?: number;
106
19
  }
107
20
  export interface ModelCatalogResult {
108
- /** 合并后的 provider 表(新数组;包内表绝不被就地改写)。 */
109
21
  providers: ProviderPreset[];
110
22
  source: CatalogSource;
111
23
  staleness?: CatalogStaleness;
112
24
  online: CatalogOnlineOutcome;
113
- /** 用户覆盖层真正贡献的 provider id(替换的 + 新增的)。无覆盖 ⇒ 空数组。 */
114
25
  overrideIds: string[];
115
26
  }
116
- /**
117
- * 注入式取 JSON 端口 —— **本包唯一的线上目录取数口**。
118
- * 约定:2xx ⇒ resolve 已解析的 JSON;其它一切(网络错 / 非 2xx / 解析失败)⇒ reject。
119
- * ETag/304、超时、代理、鉴权头全归宿主(它们各端形态不同,见文件头「本批不做」)。
120
- */
121
27
  export type CatalogFetchJson = (url: string) => Promise<unknown>;
122
28
  export interface ResolveModelCatalogOptions {
123
- /** 线上目录 URL。缺席 ⇒ 线上腿不启用(本包零默认地址)。必须是 https。 */
124
29
  onlineUrl?: string;
125
- /** 取数口。缺席 ⇒ 线上腿不启用(本包绝不自己碰 fetch)。 */
126
30
  fetchJson?: CatalogFetchJson;
127
- /** 用户本地覆盖(自定义 provider)。同 id 恒赢线上与包内。 */
128
31
  overrides?: readonly ProviderPreset[];
129
- /** 当前时刻(宿主时钟)。缺席 ⇒ 不算 ageMs(而不是自己读 Date.now)。 */
130
32
  nowMs?: number;
131
33
  }
132
- /** schemaVersion 是否落在支持区间内(非整数一律否)。 */
133
34
  export declare function isSupportedCatalogSchemaVersion(v: unknown): boolean;
134
35
  export type ValidateCatalogResult = {
135
36
  ok: true;
@@ -139,20 +40,8 @@ export type ValidateCatalogResult = {
139
40
  reason: CatalogRejectReason;
140
41
  detail?: string;
141
42
  };
142
- /**
143
- * 校验线上载荷 —— **纯同步**,端可以单用(比如「刷新目录」按钮先本地校验再落盘)。
144
- * 🔴 全或无:任何一条不合格 ⇒ 整份拒,绝不半解析。
145
- */
146
43
  export declare function validateOnlineCatalog(payload: unknown): ValidateCatalogResult;
147
- /**
148
- * 按 id 分层合并:**后来的层赢**,行序 = 首见序(包内序稳定在前,新家按层依次追加)。
149
- * 纯函数,端可以单用(比如只合并「包内 + 用户覆盖」的离线路径)。
150
- */
151
44
  export declare function mergeProviderLayers<T extends {
152
45
  id: string;
153
46
  }>(...layers: readonly (readonly T[])[]): T[];
154
- /**
155
- * 解析出一份可用的 provider 目录 —— 三层源 + 来源标注。**永不 reject**:线上腿的任何失败都
156
- * 收敛成 `online.ok === false` 并回落包内表(离线可用是硬需求)。
157
- */
158
47
  export declare function resolveModelCatalog(opts?: ResolveModelCatalogOptions): Promise<ModelCatalogResult>;
@@ -1,76 +1,6 @@
1
- /**
2
- * catalog.ts — **模型 provider 目录的三层源解析**(design/160 需求②,2026-07-31)。
3
- *
4
- * ## 它解决什么
5
- *
6
- * `providerPresets.json` 是**编译进包的静态表**:加一家 provider、改一个 model 的 cap,都得发一次
7
- * client-core。而三端(CLI / web / 桌面)要的是同一份目录、可在线更新、离线仍能用。本模块把
8
- * 设计档 §需求② 的三层源做成一个**纯解析器**:
9
- *
10
- * ```
11
- * ① 线上目录(URL 由调用方传入 —— 本文件零默认地址,见下「为什么不写死 URL」)
12
- * ↓ 拉取失败 / 离线 / 校验不过(整份弃用)
13
- * ② 包内兜底 = PROVIDER_PRESETS(零改动即兜底)
14
- * ↓
15
- * ③ 用户本地覆盖(自定义 provider,合并语义:同 id 用户 > 线上 > 包内)
16
- * ```
17
- *
18
- * ## 四条设计纪律(每条都在 pure 门 MC 段有断言)
19
- *
20
- * 1. **零 Node、零自发网络**:本文件不 import 任何 `node:*`,也**不碰全局 `fetch`** ——
21
- * 网络能力由调用方注入 `fetchJson` 端口。宿主没给 ⇒ 线上腿整条不启用(`reason: 'no-fetch-port'`),
22
- * 而不是「偷偷换个方式做」(与 host.ts 的缺席语义同一条纪律)。
23
- * ⇒ 桌面渲染进程 / 浏览器 / TUI 用同一份代码,各自注入自己的传输。
24
- * 2. **绝不半解析**(设计档明写):`schemaVersion` 超出支持区间、`providers` 不是数组、
25
- * **任何一行**形状不合格 ⇒ **整份**线上目录弃用走兜底。半解析 = 用户拿到一张自己也说不清
26
- * 是哪一版的表。
27
- * 3. **来源标注是产品位不是调试位**:返回值恒带 `source` 与 `online.{ok,reason}`。端据此渲
28
- * 「目录为内置版本(离线)」——「静默用兜底」在本层必须是**可观测**的,否则用户会以为看到的
29
- * 是最新表([honest-absence-not-fabricated-zero])。
30
- * 4. **诚实缺席**:`staleness` 只在真吃到线上目录时在场;`ageMs` 只在调用方给了 `nowMs`
31
- * 且 `generatedAt` 可解析时在场。不知道就是键缺席,绝不 `?? 0`,也绝不偷读时钟
32
- * (时钟是宿主资产,与 `AdapterContext.now` 同一条口径)。
33
- *
34
- * ## 为什么不写死线上 URL
35
- *
36
- * 目录仓位(设计档待裁点 3:`sema-agent/model-catalog` 公开仓 or release asset)**候 clay 裁**。
37
- * 机制先行、地址后填:URL 由调用方从配置/settings 传入。本文件里出现任何默认地址,都会让
38
- * 「还没定的仓位」提前变成事实契约。https-only 是硬校验(目录是会被下载并影响**出站地址**的
39
- * 数据,明文信道下可被改写成钓鱼网关)。
40
- *
41
- * ## 本批不做(留口注释,别当遗漏)
42
- *
43
- * · **缓存与 ETag**:`~/.sema/cache/model-catalog.json` + ETag/304 + 新鲜窗 + `localGeneratedAt`
44
- * 防降级(设计档 pi 调研节)。落盘是宿主能力(fs 在 host.ts 的 `FsPort`),所以缓存层应当是
45
- * **本模块之上**的一层:调用方拿 `resolveModelCatalog` 的结果自行落盘,并把上次的 `generatedAt`
46
- * 与新拉到的比较后决定是否替换。⇒ 加缓存时**不需要**改本文件的形状,只需在 `fetchJson` 注入
47
- * 处做 ETag,并在外层加一个「旧远端压不过新包」的比较。
48
- * · **签名 / sha256**:同上,属传输层与目录产出方的约定(设计档待裁点 3)。
49
- * · **`oauth` / `subscribe` 字段**:设计档待裁点 3b。本批只加纯链接位 `consoleUrl`/`signupUrl`
50
- * (见 providerPresets.ts),授权码流/设备码流一律不进。
51
- *
52
- * ## probe 复用面评估(设计档 §需求②-C「复用面」;只评估不搬,搬迁下一批做)
53
- *
54
- * 桌面端 onboard 要「选 provider → 填 key → 探活」,探活那一步现在只在壳树。按
55
- * [multiclient-migration-batch-discipline](模块级状态与读写口同包)逐个评估,结论如下 ——
56
- * 这是下一批的搬迁清单,坐标为壳树 `src/sema/onboard/`:
57
- *
58
- * | 文件 | 结论 | 依据 |
59
- * |---|---|---|
60
- * | `probePlan.ts`(139 行) | ✅ **整搬,零改造** | 零 import、零模块级状态、纯函数四件(`buildVerdictRequest` / `extractApiError` / `looksLikeModelError` / `judgeMessagesProbe`)。判决表本身就是「三端必须一致」的那部分。 |
61
- * | `probeProvider.ts`(223 行) | ⚠️ **拆搬**:判定+请求编排进包、传输与 TLS 留端 | ①裸 `fetch`/`AbortController`/`setTimeout` ⇒ 改注入 `fetchImpl`(本包既有姿势:`limitsWire`/`detachWire`/`liveInitToolFace` 的 `opts.fetchImpl`);②`ensureProxyBootstrap()` 动态 import 壳的 `utils/proxy.js`(`configureGlobalAgents`)= **Node undici 专属**,浏览器无此概念 ⇒ 留端,做成可选的「拨号前置钩子」端口;③`isCertError`/`applySystemTlsTrust`(壳 `tlsTrust.ts`,读系统钥匙串 + 设 `NODE_EXTRA_CA_CERTS`)= 纯 Node ⇒ 留端,做成可选的「一次性重试钩子」;④`nearestListed()` 与 `unwrapFetchError()` 是纯函数 ⇒ 直接进包。搬后包内出口 ≈ `probeProvider({ baseUrl, api, apiKey, modelId }, { fetchImpl, beforeDial?, retryOnCertError? })`。 |
62
- * | `detectSources.ts`(524 行) | ❌ **本批不搬** | 它整个是**宿主文件系统扫描器**:`node:fs`(existsSync/readdirSync/readFileSync/statSync)+ `node:os` homedir + `node:path` + `process.env` + 两个外部解析器(`jsonc-parser`/`yaml`)+ 壳内 `ccConfigFallback`。可搬的只有「读到的配置 → `ImportableProvider` 的分类/归一逻辑」那一小半,而它与扫描代码是逐行交织的。⇒ 要搬得先在壳里把「扫描(IO)」与「分类(纯)」拆开,是独立一批的量。**桌面端不阻塞**:桌面 onboard 的导入源探测本就该是主进程的活(与 CLI 同为 Node 侧),复用价值远低于 probe 两件。 |
63
- * | `onboardZeroModel.ts`(2.8K) | 🔶 **顺路可搬** | 已有独立单测(`onboardZeroModel.test.ts`),看形状是纯判定;搬前需确认零壳态依赖。 |
64
- * | `applyOnboard.ts` / `OnboardWizard.tsx` / `BigStepTitle.tsx` / `ccSwitchReader.ts` | ❌ 属端 | 落盘编排 / Ink 渲染 / 读 cc-switch sqlite —— 宿主辖区,桌面端各写各的渲染器(设计档 §C 与 pi 的 `AuthInteraction` seam 同一心智)。 |
65
- *
66
- * 搬迁批建议顺序:`probePlan`(零风险打头,先让包里有判决表)→ `probeProvider` 拆搬(带
67
- * fetchImpl 注入 + 两个可选钩子端口)→ `onboardZeroModel` → detectSources 拆分单列一批。
68
- */
69
1
  import { PROVIDER_PRESETS } from './providerPresets.js';
70
- /** 支持的目录 schemaVersion 区间(闭区间)。产目录那一方按这个区间发版。 */
71
2
  export const CATALOG_SCHEMA_VERSION_MIN = 1;
72
3
  export const CATALOG_SCHEMA_VERSION_MAX = 1;
73
- /** schemaVersion 是否落在支持区间内(非整数一律否)。 */
74
4
  export function isSupportedCatalogSchemaVersion(v) {
75
5
  return (typeof v === 'number' &&
76
6
  Number.isInteger(v) &&
@@ -89,10 +19,6 @@ function isProviderRow(v) {
89
19
  typeof r.authEnv === 'string' &&
90
20
  Array.isArray(r.models));
91
21
  }
92
- /**
93
- * 校验线上载荷 —— **纯同步**,端可以单用(比如「刷新目录」按钮先本地校验再落盘)。
94
- * 🔴 全或无:任何一条不合格 ⇒ 整份拒,绝不半解析。
95
- */
96
22
  export function validateOnlineCatalog(payload) {
97
23
  if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) {
98
24
  return { ok: false, reason: 'payload-not-object', detail: 'catalog payload is not a JSON object' };
@@ -119,7 +45,6 @@ export function validateOnlineCatalog(payload) {
119
45
  return {
120
46
  ok: false,
121
47
  reason: 'provider-row-invalid',
122
- // 只报**位置**不报内容:载荷是外部数据,回显 = 把不可信内容带进日志面。
123
48
  detail: `provider row #${bad} failed the shape gate (whole document rejected — no partial parse)`,
124
49
  };
125
50
  }
@@ -132,10 +57,6 @@ export function validateOnlineCatalog(payload) {
132
57
  },
133
58
  };
134
59
  }
135
- /**
136
- * 按 id 分层合并:**后来的层赢**,行序 = 首见序(包内序稳定在前,新家按层依次追加)。
137
- * 纯函数,端可以单用(比如只合并「包内 + 用户覆盖」的离线路径)。
138
- */
139
60
  export function mergeProviderLayers(...layers) {
140
61
  const order = [];
141
62
  const byId = new Map();
@@ -156,19 +77,13 @@ export function mergeProviderLayers(...layers) {
156
77
  }
157
78
  return out;
158
79
  }
159
- /** https-only(目录会影响出站地址,明文信道可被改写成钓鱼网关)。 */
160
80
  function isHttpsUrl(u) {
161
81
  return /^https:\/\/\S+$/i.test(u.trim());
162
82
  }
163
- /** 异常 → 短 detail(只取 message 前段,绝不带栈、绝不带载荷)。 */
164
83
  function shortError(e) {
165
84
  const msg = e instanceof Error ? e.message : String(e);
166
85
  return msg.slice(0, 160);
167
86
  }
168
- /**
169
- * 解析出一份可用的 provider 目录 —— 三层源 + 来源标注。**永不 reject**:线上腿的任何失败都
170
- * 收敛成 `online.ok === false` 并回落包内表(离线可用是硬需求)。
171
- */
172
87
  export async function resolveModelCatalog(opts) {
173
88
  const overrides = opts?.overrides ?? [];
174
89
  let onlineDoc = null;
@@ -181,11 +96,9 @@ export async function resolveModelCatalog(opts) {
181
96
  online = { ok: false, reason: 'no-fetch-port', detail: 'host did not install a fetchJson port' };
182
97
  }
183
98
  else if (!isHttpsUrl(url)) {
184
- // 🔴 校验在拨号**之前**:非 https 连请求都不发。
185
99
  online = { ok: false, reason: 'insecure-url', detail: 'online catalog URL must be https' };
186
100
  }
187
101
  else {
188
- // 单发不重试:重试/超时预算属宿主传输层(注入的 fetchJson 自己带)。
189
102
  let payload;
190
103
  let dialFailure = null;
191
104
  try {
@@ -1,164 +1,50 @@
1
- /**
2
- * catalogLoader.ts — **目录候选链的宿主 loader**(design/166 §1-§3,2026-08-04)。
3
- *
4
- * ## 它与 `catalog.ts` 的分工(🔴 委托,不平行重做)
5
- *
6
- * `catalog.ts` 已经是三层源解析器:`resolveModelCatalog`(线上→包内→用户覆盖三层合并)+
7
- * `validateOnlineCatalog`(schemaVersion 区间 / 逐行 `isProviderRow` / **绝不半解析** / 不回显载荷)
8
- * + `CatalogFetchJson` 注入端口 + `CatalogSource`·`CatalogRejectReason` 两张词表。
9
- * 本文件**只补 catalog.ts 声明不管的宿主面**,四件事:
10
- *
11
- * ① **候选链遍历**(`DEFAULT_CATALOG_SOURCES` = raw.githubusercontent → jsDelivr,可配);
12
- * ② **传输安全硬门**:https + 域白名单(拨号**之前**判,域外源连请求都不发)——
13
- * 而且**重定向目标过同一道门**(fetch 默认跟随重定向,不设门 = 白名单可被 302 绕过);
14
- * ③ **`catalog.sha256` 旁签**(同源同路径,SHA-256 hex 比对);
15
- * ④ **缓存**(`configHome/cache/model-catalog.json`)的信封与读回语义。
16
- *
17
- * 载荷面的判决(schemaVersion / 逐行形状 / 整份弃 / 不回显)**一行都不在这里重写** ——
18
- * 本文件拿到字节流之后做的唯一一件事是 `JSON.parse`,然后把结果交给 `resolveModelCatalog`,
19
- * 由它去 `validateOnlineCatalog`。UI 渲染也只认 `ModelCatalogResult.source` + `online.reason`
20
- * (+ 本文件加的 `cacheHit`),**不发明第二套 origin 词表**。
21
- *
22
- * ## 🔴 为什么缓存的**落盘动作**在宿主而不在这里(与设计档 §3 的偏差,记在这)
23
- *
24
- * 设计档 §3 写的是「loader 原子写(tmp+rename)」。但本包有一条机械门守着的硬法:
25
- * `src/**` 的 index 值级闭包**零 Node 内建**(`scripts/run-client-core-portability-test.mjs`
26
- * ①c 段),因为同一份代码要在浏览器/桌面渲染进程里跑。`node:fs` 一进来,那道门当场红。
27
- * ⇒ 落盘走**注入口** `CatalogCachePort`(与 `host.ts` 的 `FsPort`、`catalog.ts` 的
28
- * `CatalogFetchJson` 同一条纪律:能力由宿主注入,库不自己 `require('fs')`)。
29
- * **tmp+rename 的原子性是 `writeAtomic` 实现方的契约**,本文件在类型注释里把它写成要求;
30
- * Node 宿主的十行参考实现见 `CatalogCachePort.writeAtomic` 的注释。
31
- * 缺席该口 ⇒ 缓存腿整条不启用(`cacheHit` 键**缺席**,不是 `false` —— 「没查过」和「查过没用上」
32
- * 是两件事,[honest-absence-not-fabricated-zero])。
33
- *
34
- * ## 🔴 `forceRefresh` 为什么没有(与设计档 §1 签名的偏差)
35
- *
36
- * 本 loader **恒先走网络**,缓存只在候选链**全败**时顶上(设计档 §3 自己就是这么定的读时机)。
37
- * 也就是说没有任何一条「优先吃缓存」的路径可供 `forceRefresh` 去绕过 —— 收下这个参数只会
38
- * 得到一个恒为空操作的旋钮,而空操作的旋钮是**假 affordance**(调用方以为自己强制刷新了)。
39
- * 真要「手动刷新」,直接再调一次本函数就是最新语义。
40
- *
41
- * ## 时钟
42
- *
43
- * 与 `catalog.ts` 同一口径:**绝不偷读时钟**。`nowMs` 缺席 ⇒ 缓存信封不写 `fetchedAt`、
44
- * 陈旧判定不做(`cacheStale` 键缺席),而不是 `Date.now()` 兜底。
45
- */
46
1
  import { type EnvLike } from '../hostEnv.js';
47
2
  import { type ModelCatalogResult, type OnlineCatalogDoc } from './catalog.js';
48
3
  import type { ProviderPreset } from './providerPresets.js';
49
- /**
50
- * 默认候选链(design/166 §1;clay 裁「可配置,默认 github」)。
51
- * 第二跳 jsDelivr 对 gh 仓是被动 CDN、零接入成本 —— 这就是大陆可达性的零维护替身。
52
- * 🔴 顺序即优先级:逐源尝试,前一跳成了就不拨下一跳。
53
- */
54
4
  export declare const DEFAULT_CATALOG_SOURCES: readonly string[];
55
- /** 默认域白名单 = 默认链两跳的 host。用户显式配置的源 host 在运行期并入(用户自担)。 */
56
5
  export declare const CATALOG_DEFAULT_HOSTS: readonly string[];
57
- /** 候选链的 env 键(一键安装脚本改这里;settings.json `env` 块同名同义,见 design/166 §2)。 */
58
6
  export declare const CATALOG_SOURCES_ENV = "SEMA_CATALOG_SOURCES";
59
- /**
60
- * 单源的**传输层**结局。
61
- *
62
- * 🔴 它**不是**第二套 origin 词表:UI 渲染「目录从哪来」恒读 `ModelCatalogResult.source` +
63
- * `online.reason` + `cacheHit`。本词表只服务于 **doctor 的逐源分诊**(「两跳分别为什么没成」),
64
- * 那是 `catalog.ts` 的单 URL 视角在结构上说不出来的量 —— 它只有一个 `online` 结局位。
65
- */
66
7
  export type CatalogSourceOutcome = 'ok' | 'insecure-url' | 'host-not-allowed' | 'redirect-blocked' | 'redirect-opaque' | 'redirect-loop' | 'http-error' | 'network-error' | 'invalid-json' | 'sha-mismatch';
67
- /** 一次逐源尝试的留痕(doctor 用;🔴 绝不带载荷内容,只带判决与被截断的 message)。 */
68
8
  export interface CatalogSourceAttempt {
69
9
  url: string;
70
10
  outcome: CatalogSourceOutcome;
71
- /** HTTP 状态码(只在真收到响应时在场)。 */
72
11
  status?: number;
73
- /** 旁签是否**真的比对过**(只在 `outcome:'ok'` 时在场;false = sha 拿不到,已记 warn 放行)。 */
74
12
  shaChecked?: boolean;
75
- /** 人话细节(判决相关短语 / 被截断的错误 message)。 */
76
13
  detail?: string;
77
14
  }
78
- /** 缓存文件的信封(design/166 §3)。`fetchedAt` 缺席 = 写入时宿主没给时钟。 */
79
15
  export interface CatalogCacheEnvelope {
80
16
  fetchedAt?: number;
81
17
  sourceUrl: string;
82
18
  catalog: OnlineCatalogDoc;
83
19
  }
84
- /**
85
- * 缓存口 —— 宿主注入(本包零 `node:fs`,理由见文件头)。
86
- *
87
- * `writeAtomic` 的契约是**原子替换**(临时文件 + rename),不是 `writeFile` 的别名:
88
- * 半截文件会让下一次冷启动读到一份坏缓存。Node 宿主的参考实现:
89
- * ```js
90
- * async writeAtomic(path, text) {
91
- * await mkdir(dirname(path), { recursive: true })
92
- * const tmp = `${path}.${process.pid}.tmp`
93
- * await writeFile(tmp, text, 'utf8')
94
- * await rename(tmp, path) // 同目录 rename = 原子
95
- * }
96
- * ```
97
- * 两个动词都允许同步或异步实现;抛异常由 loader 收成 warning(缓存是纵深,不是主路径)。
98
- */
99
20
  export interface CatalogCachePort {
100
21
  read(path: string): string | null | Promise<string | null>;
101
22
  writeAtomic(path: string, text: string): void | Promise<void>;
102
23
  }
103
- /** `loadCatalogWithSources` 的入参。 */
104
24
  export interface LoadCatalogOptions {
105
- /** 缓存落点的根(`configHome/cache/model-catalog.json`)。缺席 ⇒ 缓存腿不启用。 */
106
25
  configHome?: string;
107
- /** 覆盖候选链(缺省 `DEFAULT_CATALOG_SOURCES`;env 恒赢本项,见 `resolveCatalogSources`)。 */
108
26
  sources?: readonly string[];
109
- /** 宿主 env(缺省 `hostEnv()`)。 */
110
27
  env?: EnvLike;
111
- /** 每源传输预算(缺省 `DEFAULT_CATALOG_TIMEOUT_MS`)。 */
112
28
  timeoutMs?: number;
113
- /** 宿主时钟。缺席 ⇒ 不算 ageMs、不写 fetchedAt、不判 stale(绝不偷读时钟)。 */
114
29
  nowMs?: number;
115
- /** 传输注入口(缺省全局 `fetch`;本包既有姿势 = limitsWire/detachWire 的 `fetchImpl`)。 */
116
30
  fetchImpl?: typeof fetch;
117
- /** 缓存口。缺席 ⇒ 缓存腿整条不启用(`cacheHit` 键缺席)。 */
118
31
  cache?: CatalogCachePort;
119
- /** 用户本地覆盖层,原样透传给 `resolveModelCatalog`。 */
120
32
  overrides?: readonly ProviderPreset[];
121
33
  }
122
- /**
123
- * 结果 = `ModelCatalogResult`(来源标注/新鲜度/合并表全归 catalog.ts)+ 宿主面四位。
124
- * 🔴 只**加**位不改位:端渲染仍读 `source` / `online.reason`。
125
- */
126
34
  export interface LoadedModelCatalog extends ModelCatalogResult {
127
- /** 真正被吃下的那一跳(线上成功或缓存自述的来源);全败 ⇒ 缺席。 */
128
35
  sourceUrl?: string;
129
- /** 这份线上载荷是不是从缓存顶上来的。**缓存口缺席 ⇒ 本键缺席**(没查过 ≠ 查过没用上)。 */
130
36
  cacheHit?: boolean;
131
- /** 缓存是否已过 30 天(照用但如实标)。只在 `cacheHit:true` 且宿主给了时钟时在场。 */
132
37
  cacheStale?: boolean;
133
- /** 逐源留痕(doctor 分诊用)。 */
134
38
  attempts: CatalogSourceAttempt[];
135
- /** 非致命的诚实记账(sha 拿不到 / 缓存读写失败 / 缓存半截)。 */
136
39
  warnings: string[];
137
40
  }
138
- /** `SEMA_CATALOG_SOURCES` 的逗号列表解析(去空白、丢空项;缺席 ⇒ 空列表)。 */
139
41
  export declare function parseCatalogSources(raw: string | undefined | null): string[];
140
- /** `resolveCatalogSources` 的入参。 */
141
42
  export interface ResolveCatalogSourcesOptions {
142
43
  env?: EnvLike;
143
44
  sources?: readonly string[];
144
45
  }
145
- /**
146
- * 候选链优先级(design/166 §2,高→低):env `SEMA_CATALOG_SOURCES` > 调用方(settings)> 默认链。
147
- * 🔴 「配了但解析出空列表」按**没配**处理:空链会把目录腿整条静默关掉,而调用方以为自己配了。
148
- */
149
46
  export declare function resolveCatalogSources(opts?: ResolveCatalogSourcesOptions): string[];
150
- /**
151
- * 传输面硬门:**https + host 在白名单内**。拨号之前判 —— 不合格的地址连请求都不发。
152
- * 🔴 白名单是**域**的门、https 是**协议**的门,两道都要过:白名单里的 host 走 http 照样拒
153
- * (明文信道下目录可被改写成钓鱼网关,而目录决定的正是出站地址)。
154
- */
155
47
  export declare function isAllowedCatalogUrl(url: string, allowedHosts: ReadonlySet<string>): boolean;
156
- /** 旁签地址 = 同源同路径换后缀(design/165 §4:`dist/catalog.sha256`)。 */
157
48
  export declare function catalogShaUrlFor(catalogUrl: string): string;
158
- /** 缓存文件绝对路径(design/166 §3)。POSIX 分隔符 —— Node 侧 `path.join` 对它是幂等的。 */
159
49
  export declare function catalogCachePath(configHome: string): string;
160
- /**
161
- * 解析出一份可用的 provider 目录 —— **候选链 + 传输硬门 + 旁签 + 缓存**,载荷判决全委托
162
- * `resolveModelCatalog`。🔴 **永不 reject**:onboard 不能因为网络死。
163
- */
164
50
  export declare function loadCatalogWithSources(opts?: LoadCatalogOptions): Promise<LoadedModelCatalog>;