@lqc123qwe/car-runtime 1.20.0 → 1.21.1
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/dist/SHA256SUMS +1 -1
- package/dist/car-runtime-1.21.1.tgz +0 -0
- package/dist/car-runtime-1.21.1.tgz.sig.bundle +1 -0
- package/dist/release-audit.jsonl +4 -4
- package/dist/runtime-core/chatStep.js +34 -1
- package/dist/runtime-core/llm.js +52 -6
- package/dist/runtime-core/types.d.ts +6 -0
- package/dist/sbom.json +6 -6
- package/dist/session/log.d.ts +1 -1
- package/dist/session/log.js +32 -2
- package/package.json +1 -1
- package/src/runtime-core/chatStep.ts +32 -1
- package/src/runtime-core/llm.ts +46 -5
- package/src/runtime-core/types.ts +8 -0
- package/src/session/log.ts +32 -2
- package/dist/car-runtime-1.20.0.tgz +0 -0
- package/dist/car-runtime-1.20.0.tgz.sig.bundle +0 -1
package/dist/SHA256SUMS
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
66bbea0d771ff0a416ece86c703d25f39a4e9e78af767610ba336b01bdb1c9ac car-runtime-1.21.1.tgz
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"base64Signature":"MEUCIQDKONgEM8eAPTGlklJnk7tc5wNDrs/vZpp39jeG81yWtwIgR+tCPl3Djrl8Nk9gpNSZJ+FPXI4ZFp7773VAdr+Fpck=","cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUc2RENDQm02Z0F3SUJBZ0lVZEJmS0N4OVhLZllnM3QrVExBMlQzQ3M3WHBJd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpZeE1URTBNRFF5TURNMldoY05Nall4TVRFME1EUXpNRE0yV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVSTG9jQzRXNFpuV0ZzMjIvYjA3cllRaW5LMHBVQWhLejFidW4KRFM4ZG02QlVhc2FqUHltK0VVcjBNZWQ5aUJlcjF5cXZuNHFiaHRJQWFkYmtpUXk1emFPQ0JZMHdnZ1dKTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWZCZ05WSFNNRUdEQVdnQlRmCjArblBWaVFSbHZtbzJPa29WYUxHTGhoa1B6QmlCZ05WSFJFQkFmOEVXREJXaGxSb2RIUndjem92TDJkcGRHaDEKWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHpMM0psYkdWaApjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakl4TGpFd09RWUtLd1lCQkFHRHZ6QUJBUVFyYUhSMGNITTZMeTkwCmIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBVkJnb3JCZ0VFQVlPL01BRUMKQkFkeVpXeGxZWE5sTURZR0Npc0dBUVFCZzc4d0FRTUVLRGc1TURObFpEQTJaVEJoTW1KallqYzVPV1V6TkdJMgpPREE0TldZellqUTFObUZoWWpFM09UZ3dGUVlLS3dZQkJBR0R2ekFCQkFRSGNtVnNaV0Z6WlRBZ0Jnb3JCZ0VFCkFZTy9NQUVGQkJKc2NXTTJNalF2WTJGeUxYSjFiblJwYldVd0hnWUtLd1lCQkFHRHZ6QUJCZ1FRY21WbWN5OTAKWVdkekx6RXVNakV1TVRBN0Jnb3JCZ0VFQVlPL01BRUlCQzBNSzJoMGRIQnpPaTh2ZEc5clpXNHVZV04wYVc5dQpjeTVuYVhSb2RXSjFjMlZ5WTI5dWRHVnVkQzVqYjIwd1pBWUtLd1lCQkFHRHZ6QUJDUVJXREZSb2RIUndjem92CkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHoKTDNKbGJHVmhjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakl4TGpFd09BWUtLd1lCQkFHRHZ6QUJDZ1FxRENnNApPVEF6WldRd05tVXdZVEppWTJJM09UbGxNelJpTmpnd09EVm1NMkkwTlRaaFlXSXhOems0TUIwR0Npc0dBUVFCCmc3OHdBUXNFRHd3TloybDBhSFZpTFdodmMzUmxaREExQmdvckJnRUVBWU8vTUFFTUJDY01KV2gwZEhCek9pOHYKWjJsMGFIVmlMbU52YlM5c2NXTTJNalF2WTJGeUxYSjFiblJwYldVd09BWUtLd1lCQkFHRHZ6QUJEUVFxRENnNApPVEF6WldRd05tVXdZVEppWTJJM09UbGxNelJpTmpnd09EVm1NMkkwTlRaaFlXSXhOems0TUNBR0Npc0dBUVFCCmc3OHdBUTRFRWd3UWNtVm1jeTkwWVdkekx6RXVNakV1TVRBYUJnb3JCZ0VFQVlPL01BRVBCQXdNQ2pFek5qRXgKT1RJM01UUXdLUVlLS3dZQkJBR0R2ekFCRUFRYkRCbG9kSFJ3Y3pvdkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMApNQmdHQ2lzR0FRUUJnNzh3QVJFRUNnd0lOamt5TXpRMU5qUXdaQVlLS3dZQkJBR0R2ekFCRWdSV0RGUm9kSFJ3CmN6b3ZMMmRwZEdoMVlpNWpiMjB2YkhGak5qSTBMMk5oY2kxeWRXNTBhVzFsTHk1bmFYUm9kV0l2ZDI5eWEyWnMKYjNkekwzSmxiR1ZoYzJVdWVXMXNRSEpsWm5NdmRHRm5jeTh4TGpJeExqRXdPQVlLS3dZQkJBR0R2ekFCRXdRcQpEQ2c0T1RBelpXUXdObVV3WVRKaVkySTNPVGxsTXpSaU5qZ3dPRFZtTTJJME5UWmhZV0l4TnprNE1CY0dDaXNHCkFRUUJnNzh3QVJRRUNRd0hjbVZzWldGelpUQlpCZ29yQmdFRUFZTy9NQUVWQkVzTVNXaDBkSEJ6T2k4dloybDAKYUhWaUxtTnZiUzlzY1dNMk1qUXZZMkZ5TFhKMWJuUnBiV1V2WVdOMGFXOXVjeTl5ZFc1ekx6UXpOVFUyTVRNNQpNak16TDJGMGRHVnRjSFJ6THpFd0ZnWUtLd1lCQkFHRHZ6QUJGZ1FJREFad2RXSnNhV013VUFZS0t3WUJCQUdECnZ6QUJHQVJDREVCeVpYQnZPbXh4WXpZeU5FQTJPVEl6TkRVMk5DOWpZWEl0Y25WdWRHbHRaVUF4TXpZeE1Ua3kKTnpFME9uSmxaanB5WldaekwzUmhaM012TVM0eU1TNHhNSUdMQmdvckJnRUVBZFo1QWdRQ0JIMEVld0I1QUhjQQozVDB3YXNiSEVUSmpHUjRjbVdjM0FxSktYcmplUEszL2g0cHlnQzhwN280QUFBR2gyRWtyQkFBQUJBTUFTREJHCkFpRUE0eUtpR25lWUhUS1JicjZjNHEwYmM4NXU5RU1FUU1obUtSZWprUlo2dytRQ0lRRFhQMGRRTEVjNEFhV1EKMkhXb002aEZKRE15a291aGJIajE3UHZnVHd5UGJEQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQk8vdU41VlRxQQpkb3YxcFFFQVFkR3hCNDVKZEw2VHRPRmNMbEd5d0RpWWdsT2RCYnZtZkdkdHlqaDF5V0dXVUtZQ01RQzcrSGJTCmttTHREeGNwOU5TMGZMZkFMNTg5eUtiMXNsOEtVR0FBdlFidEVjNVUvVWNWRmJheXp2c3FBSkZFZGNvPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","rekorBundle":{"SignedEntryTimestamp":"MEUCICgbmt4S7KuZIcHFx5zOZBAs/O7cmqRY9neWpULg0ib6AiEA/O0LtpinJBhb30rjXIzOagiD8H59yhnPAcUqQXIJwec=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2NmJiZWEwZDc3MWZmMGE0MTZlY2U4NmM3MDNkMjVmMzlhNGU5ZTc4YWY3Njc2MTBiYTMzNmIwMWJkYjFjOWFjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURLT05nRU04ZUFQVEdsa2xKbms3dGM1d05EcnMvdlpwcDM5amVHODF5V3R3SWdSK3RDUGwzRGpybDhOazlncE5TWkorRlBYSTRaRnA3NzczVkFkcitGcGNrPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVYzJSRU5EUW0wMlowRjNTVUpCWjBsVlpFSm1TME40T1ZoTFpsbG5NM1FyVkV4Qk1sUXpRM00zV0hCSmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFVUlRCTlJGRjVUVVJOTWxkb1kwNU5hbGw0VFZSRk1FMUVVWHBOUkUweVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZTVEc5alF6UlhORnB1VjBaek1qSXZZakEzY2xsUmFXNUxNSEJWUVdoTGVqRmlkVzRLUkZNNFpHMDJRbFZoYzJGcVVIbHRLMFZWY2pCTlpXUTVhVUpsY2pGNWNYWnVOSEZpYUhSSlFXRmtZbXRwVVhrMWVtRlBRMEpaTUhkbloxZEtUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFtbENaMDVXU0ZKRlFrRm1PRVZYUkVKWGFHeFNiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmlTRVpxVG1wSk1Fd3lUbWhqYVRGNVpGYzFNR0ZYTVd4TWVUVnVZVmhTYjJSWFNYWmtNamw1WVRKYWMySXpaSHBNTTBwc1lrZFdhQXBqTWxWMVpWY3hjMUZJU214YWJrMTJaRWRHYm1ONU9IaE1ha2w0VEdwRmQwOVJXVXRMZDFsQ1FrRkhSSFo2UVVKQlVWRnlZVWhTTUdOSVRUWk1lVGt3Q21JeWRHeGlhVFZvV1ROU2NHSXlOWHBNYldSd1pFZG9NVmx1Vm5wYVdFcHFZakkxTUZwWE5UQk1iVTUyWWxSQlZrSm5iM0pDWjBWRlFWbFBMMDFCUlVNS1FrRmtlVnBYZUd4WldFNXNUVVJaUjBOcGMwZEJVVkZDWnpjNGQwRlJUVVZMUkdjMVRVUk9iRnBFUVRKYVZFSm9UVzFLYWxscVl6VlBWMVY2VGtkSk1ncFBSRUUwVGxkWmVsbHFVVEZPYlVab1dXcEZNMDlVWjNkR1VWbExTM2RaUWtKQlIwUjJla0ZDUWtGUlNHTnRWbk5hVjBaNldsUkJaMEpuYjNKQ1owVkZDa0ZaVHk5TlFVVkdRa0pLYzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMGhuV1V0TGQxbENRa0ZIUkhaNlFVSkNaMUZSWTIxV2JXTjVPVEFLV1Zka2VreDZSWFZOYWtWMVRWUkJOMEpuYjNKQ1owVkZRVmxQTDAxQlJVbENRekJOU3pKb01HUklRbnBQYVRoMlpFYzVjbHBYTkhWWlYwNHdZVmM1ZFFwamVUVnVZVmhTYjJSWFNqRmpNbFo1V1RJNWRXUkhWblZrUXpWcVlqSXdkMXBCV1V0TGQxbENRa0ZIUkhaNlFVSkRVVkpYUkVaU2IyUklVbmRqZW05MkNrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUV3eVRtaGphVEY1WkZjMU1HRlhNV3hNZVRWdVlWaFNiMlJYU1haa01qbDVZVEphYzJJelpIb0tURE5LYkdKSFZtaGpNbFYxWlZjeGMxRklTbXhhYmsxMlpFZEdibU41T0hoTWFrbDRUR3BGZDA5QldVdExkMWxDUWtGSFJIWjZRVUpEWjFGeFJFTm5OQXBQVkVGNldsZFJkMDV0VlhkWlZFcHBXVEpKTTA5VWJHeE5lbEpwVG1wbmQwOUVWbTFOTWtrd1RsUmFhRmxYU1hoT2VtczBUVUl3UjBOcGMwZEJVVkZDQ21jM09IZEJVWE5GUkhkM1Rsb3liREJoU0ZacFRGZG9kbU16VW14YVJFRXhRbWR2Y2tKblJVVkJXVTh2VFVGRlRVSkRZMDFLVjJnd1pFaENlazlwT0hZS1dqSnNNR0ZJVm1sTWJVNTJZbE01YzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkVVVkZ4UkVObk5BcFBWRUY2V2xkUmQwNXRWWGRaVkVwcFdUSkpNMDlVYkd4TmVsSnBUbXBuZDA5RVZtMU5Na2t3VGxSYWFGbFhTWGhPZW1zMFRVTkJSME5wYzBkQlVWRkNDbWMzT0hkQlVUUkZSV2QzVVdOdFZtMWplVGt3V1Zka2VreDZSWFZOYWtWMVRWUkJZVUpuYjNKQ1owVkZRVmxQTDAxQlJWQkNRWGROUTJwRmVrNXFSWGdLVDFSSk0wMVVVWGRMVVZsTFMzZFpRa0pCUjBSMmVrRkNSVUZSWWtSQ2JHOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUFwTlFtZEhRMmx6UjBGUlVVSm5OemgzUVZKRlJVTm5kMGxPYW10NVRYcFJNVTVxVVhkYVFWbExTM2RaUWtKQlIwUjJla0ZDUldkU1YwUkdVbTlrU0ZKM0NtTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZa2hHYWs1cVNUQk1NazVvWTJreGVXUlhOVEJoVnpGc1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTUtZak5rZWt3elNteGlSMVpvWXpKVmRXVlhNWE5SU0Vwc1dtNU5kbVJIUm01amVUaDRUR3BKZUV4cVJYZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JYZFJjUXBFUTJjMFQxUkJlbHBYVVhkT2JWVjNXVlJLYVZreVNUTlBWR3hzVFhwU2FVNXFaM2RQUkZadFRUSkpNRTVVV21oWlYwbDRUbnByTkUxQ1kwZERhWE5IQ2tGUlVVSm5OemgzUVZKUlJVTlJkMGhqYlZaeldsZEdlbHBVUWxwQ1oyOXlRbWRGUlVGWlR5OU5RVVZXUWtWelRWTlhhREJrU0VKNlQyazRkbG95YkRBS1lVaFdhVXh0VG5aaVV6bHpZMWROTWsxcVVYWlpNa1o1VEZoS01XSnVVbkJpVjFWMldWZE9NR0ZYT1hWamVUbDVaRmMxZWt4NlVYcE9WRlV5VFZSTk5RcE5hazE2VERKR01HUkhWblJqU0ZKNlRIcEZkMFpuV1V0TGQxbENRa0ZIUkhaNlFVSkdaMUZKUkVGYWQyUlhTbk5oVjAxM1ZVRlpTMHQzV1VKQ1FVZEVDblo2UVVKSFFWSkRSRVZDZVZwWVFuWlBiWGg0V1hwWmVVNUZRVEpQVkVsNlRrUlZNazVET1dwWldFbDBZMjVXZFdSSGJIUmFWVUY0VFhwWmVFMVVhM2tLVG5wRk1FOXVTbXhhYW5CNVdsZGFla3d6VW1oYU0wMTJUVk0wZVUxVE5IaE5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVWbGQwSTFRVWhqUVFvelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIyZ3lSV3R5UWtGQlFVSkJUVUZUUkVKSENrRnBSVUUwZVV0cFIyNWxXVWhVUzFKaWNqWmpOSEV3WW1NNE5YVTVSVTFGVVUxb2JVdFNaV3ByVWxvMmR5dFJRMGxSUkZoUU1HUlJURVZqTkVGaFYxRUtNa2hYYjAwMmFFWktSRTE1YTI5MWFHSklhakUzVUhablZIZDVVR0pFUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRazh2ZFU0MVZsUnhRUXBrYjNZeGNGRkZRVkZrUjNoQ05EVktaRXcyVkhSUFJtTk1iRWQ1ZDBScFdXZHNUMlJDWW5adFprZGtkSGxxYURGNVYwZFhWVXRaUTAxUlF6Y3JTR0pUQ210dFRIUkVlR053T1U1VE1HWk1aa0ZNTlRnNWVVdGlNWE5zT0V0VlIwRkJkbEZpZEVWak5WVXZWV05XUm1KaGVYcDJjM0ZCU2taRlpHTnZQUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=","integratedTime":1794630037,"logIndex":3869485684,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}
|
package/dist/release-audit.jsonl
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{"stage":"archive","detail":"git archive HEAD → car-runtime-1.
|
|
2
|
-
{"stage":"sha256sums","detail":"SHA256SUMS
|
|
3
|
-
{"stage":"sbom","detail":"55 个组件(运行时依赖 0 项)","ts":
|
|
4
|
-
{"stage":"cosign-keyless","detail":"signed car-runtime-1.
|
|
1
|
+
{"stage":"archive","detail":"git archive HEAD → car-runtime-1.21.1.tgz(437655 bytes,树哈希锚定)","ts":1794630034700}
|
|
2
|
+
{"stage":"sha256sums","detail":"SHA256SUMS 66bbea0d771ff0a4…(裸字节复核通过)","ts":1794630034701}
|
|
3
|
+
{"stage":"sbom","detail":"55 个组件(运行时依赖 0 项)","ts":1794630034707}
|
|
4
|
+
{"stage":"cosign-keyless","detail":"signed car-runtime-1.21.1.tgz (keyless OIDC + Rekor)","ts":1794630037965}
|
|
@@ -21,13 +21,25 @@ export async function chatStep(opts) {
|
|
|
21
21
|
const messages = log.deriveMessages(undefined, { activeTurnId: turnId }).map(m => ({
|
|
22
22
|
role: m.role,
|
|
23
23
|
content: m.toolCall !== undefined
|
|
24
|
-
? {
|
|
24
|
+
? {
|
|
25
|
+
toolCall: m.toolCall,
|
|
26
|
+
// 1.21(R-TOKENHUB-1 / D-T3/D-T4):投影层附加的同 turn thinking 三元组随 toolCall
|
|
27
|
+
// 载荷透传(适配器回传消费——toAnthropic 前置 thinking 块;openai 形忽略该键)
|
|
28
|
+
...(m.thinking !== undefined
|
|
29
|
+
? { thinking: m.thinking }
|
|
30
|
+
: {}),
|
|
31
|
+
}
|
|
25
32
|
: m.content,
|
|
26
33
|
}));
|
|
27
34
|
// 4. 流式消费(3. 凭据解析在适配器首块前,A080001 由此传播)
|
|
28
35
|
const redactor = new StreamRedactor();
|
|
29
36
|
let text = '';
|
|
30
37
|
const calls = new Map();
|
|
38
|
+
// 1.21(R-TOKENHUB-1 / D-T1/D-T2):thinking 捕获累积——禁改写(回传签名完整性 > 脱敏
|
|
39
|
+
// 改写),provider 事实字节保真;redacted_thinking = data 全文单发覆盖
|
|
40
|
+
let thinkingText = '';
|
|
41
|
+
let thinkingSignature = '';
|
|
42
|
+
let thinkingRedacted;
|
|
31
43
|
let stopReason;
|
|
32
44
|
let errorDetail;
|
|
33
45
|
let usage;
|
|
@@ -67,6 +79,13 @@ export async function chatStep(opts) {
|
|
|
67
79
|
cur.argsBuf += chunk.toolCallDelta.argumentsDelta;
|
|
68
80
|
calls.set(idx, cur);
|
|
69
81
|
}
|
|
82
|
+
// 1.21(R-TOKENHUB-1 / D-T1):thinking 三面捕获(text/signature 增量累积、redacted 单发覆盖)
|
|
83
|
+
if (chunk.thinkingDelta !== undefined)
|
|
84
|
+
thinkingText += chunk.thinkingDelta;
|
|
85
|
+
if (chunk.thinkingSignatureDelta !== undefined)
|
|
86
|
+
thinkingSignature += chunk.thinkingSignatureDelta;
|
|
87
|
+
if (chunk.thinkingRedacted !== undefined)
|
|
88
|
+
thinkingRedacted = chunk.thinkingRedacted;
|
|
70
89
|
if (chunk.error)
|
|
71
90
|
errorDetail = chunk.error.message;
|
|
72
91
|
if (chunk.usage)
|
|
@@ -103,6 +122,20 @@ export async function chatStep(opts) {
|
|
|
103
122
|
providerRaw: usage.providerRaw,
|
|
104
123
|
});
|
|
105
124
|
}
|
|
125
|
+
// 5a. 1.21(R-TOKENHUB-1 / D-T2):thinking 事件落链(actor='model',先于 assistant/toolCall
|
|
126
|
+
// ——投影层按同 turn 首 toolCall 附加回传)。payload = thinking 原文禁改写(签名完整性 >
|
|
127
|
+
// 脱敏改写——改写即回传校验失败);secretsRedacted 仅计数留痕(审计信号,不复写);
|
|
128
|
+
// redacted 形态 payload = data 全文(meta.redacted=true)。无 thinking chunk = 零新事件
|
|
129
|
+
// (D-T5 字节兼容,链形态与 1.20 全等)。
|
|
130
|
+
if (thinkingText.length || thinkingRedacted !== undefined) {
|
|
131
|
+
const thinkingPayload = thinkingRedacted ?? thinkingText;
|
|
132
|
+
const secretsInThinking = scanSecrets(thinkingPayload).hits.length;
|
|
133
|
+
log.append('model', 'thinking', turnId, thinkingPayload, {
|
|
134
|
+
...(thinkingRedacted !== undefined ? { redacted: true } : {}),
|
|
135
|
+
...(thinkingSignature ? { signature: thinkingSignature } : {}),
|
|
136
|
+
...(secretsInThinking ? { secretsRedacted: secretsInThinking } : {}),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
106
139
|
// 5. assistant 文本落 M7(脱敏后 + 计数留痕;空文本不产事件)
|
|
107
140
|
// flush 后兜底复扫只计数不复写:流式遮蔽已生效,>0 即流式边界逃逸的审计信号
|
|
108
141
|
let secretsRedacted = 0;
|
package/dist/runtime-core/llm.js
CHANGED
|
@@ -606,12 +606,35 @@ function toAnthropic(req, apiKey, cache) {
|
|
|
606
606
|
turns.push({ role: 'user', content: pendingToolResults });
|
|
607
607
|
pendingToolResults = [];
|
|
608
608
|
};
|
|
609
|
+
// 1.21.1(R-TOKENHUB-1 二分实证):同轮拆分重放合并——投影形态 [assistant(text)][assistant(toolCall)…]
|
|
610
|
+
// 在 tools 声明在场时被 tokenhub 网关严格路径拒绝(400 reasoning_content must be passed back,
|
|
611
|
+
// 与 thinking 是否已在 wire 无关——P-B/P-C vs P-D 四探针二分定案);provider 原始回复 = 单条
|
|
612
|
+
// [thinking?, text?, tool_use…] 消息,合并重放(P-D)过审。合并口径:
|
|
613
|
+
// - 相邻 assistant(toolCall) 聚合(同 turn 多 tool_use 单条);thinking 取首条附加;
|
|
614
|
+
// - 紧邻前驱为 assistant 纯文本消息 → 弹回合并为 [thinking?, text, tool_use…];
|
|
615
|
+
// - 无相邻文本的 toolCall 消息形态不变([thinking?, tool_use])——非工具环链逐字节兼容(D-T5)。
|
|
616
|
+
let pendingTu = null;
|
|
617
|
+
const flushTu = () => {
|
|
618
|
+
if (!pendingTu)
|
|
619
|
+
return;
|
|
620
|
+
const prev = turns[turns.length - 1];
|
|
621
|
+
const { thinkingBlock, toolCalls } = pendingTu;
|
|
622
|
+
if (prev && prev.role === 'assistant' && typeof prev.content === 'string') {
|
|
623
|
+
turns.pop();
|
|
624
|
+
turns.push({ role: 'assistant', content: [...(thinkingBlock ? [thinkingBlock] : []), { type: 'text', text: prev.content }, ...toolCalls] });
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
turns.push({ role: 'assistant', content: [...(thinkingBlock ? [thinkingBlock] : []), ...toolCalls] });
|
|
628
|
+
}
|
|
629
|
+
pendingTu = null;
|
|
630
|
+
};
|
|
609
631
|
for (const m of req.messages) {
|
|
610
632
|
if (m.role === 'system') {
|
|
611
633
|
system.push(typeof m.content === 'string' ? m.content : JSON.stringify(m.content));
|
|
612
634
|
continue;
|
|
613
635
|
}
|
|
614
636
|
if (m.role === 'toolResult') {
|
|
637
|
+
flushTu(); // tool_result 前 = 同轮 assistant 消息收口([text?,tu…] 先于 tool_result 出站)
|
|
615
638
|
const p = m.content;
|
|
616
639
|
pendingToolResults.push({
|
|
617
640
|
type: 'tool_result',
|
|
@@ -621,15 +644,27 @@ function toAnthropic(req, apiKey, cache) {
|
|
|
621
644
|
});
|
|
622
645
|
continue;
|
|
623
646
|
}
|
|
624
|
-
flushToolResults();
|
|
625
647
|
if (m.role === 'assistant' && m.content != null && typeof m.content === 'object' && 'toolCall' in m.content) {
|
|
626
648
|
const tc = m.content.toolCall;
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
649
|
+
// 1.21(R-TOKENHUB-1 / D-T4):工具环回传——投影层附加的 thinking(同 turn 原始 assistant
|
|
650
|
+
// 消息的 thinking 块)前置重放。1.21.1:thinking 块随合并缓冲进同轮单条消息(见 flushTu 注记);
|
|
651
|
+
// 无 thinking = 1.20 形态。
|
|
652
|
+
const th = m.content.thinking;
|
|
653
|
+
const thinkingBlock = th?.text?.length
|
|
654
|
+
? th.redacted
|
|
655
|
+
? { type: 'redacted_thinking', data: th.text }
|
|
656
|
+
: { type: 'thinking', thinking: th.text, ...(th.signature ? { signature: th.signature } : {}) }
|
|
657
|
+
: undefined;
|
|
658
|
+
if (!pendingTu)
|
|
659
|
+
pendingTu = { toolCalls: [], ...(thinkingBlock ? { thinkingBlock } : {}) };
|
|
660
|
+
pendingTu.toolCalls.push({ type: 'tool_use', id: tc.id, name: tc.tool, input: tc.args ?? {} });
|
|
661
|
+
continue;
|
|
631
662
|
}
|
|
663
|
+
flushTu();
|
|
664
|
+
flushToolResults();
|
|
665
|
+
turns.push({ role: m.role, content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content) });
|
|
632
666
|
}
|
|
667
|
+
flushTu();
|
|
633
668
|
flushToolResults();
|
|
634
669
|
// 1.20-K1(D-48 P2):滚动断点在白名单命中时挂尾部消息(缺省 1 个)——system 断点(P1)
|
|
635
670
|
// 与消息断点独立,off 时两者俱灭(rollingCacheAllowed 内已连坐)
|
|
@@ -706,6 +741,10 @@ async function* parseAnthropicSseStream(body, model, adapterId) {
|
|
|
706
741
|
if (block?.type === 'tool_use') {
|
|
707
742
|
yield { toolCallDelta: { index: evt.index, id: block.id, name: block.name } };
|
|
708
743
|
}
|
|
744
|
+
else if (block?.type === 'redacted_thinking' && typeof block.data === 'string' && block.data.length) {
|
|
745
|
+
// 1.21(R-TOKENHUB-1 / D-T1):redacted_thinking 全文单发(回传形态 {type:'redacted_thinking',data})
|
|
746
|
+
yield { thinkingRedacted: block.data };
|
|
747
|
+
}
|
|
709
748
|
}
|
|
710
749
|
else if (type === 'content_block_delta') {
|
|
711
750
|
const d = evt.delta;
|
|
@@ -715,7 +754,14 @@ async function* parseAnthropicSseStream(body, model, adapterId) {
|
|
|
715
754
|
else if (d?.type === 'input_json_delta' && typeof d.partial_json === 'string' && d.partial_json.length) {
|
|
716
755
|
yield { toolCallDelta: { index: evt.index, argumentsDelta: d.partial_json } };
|
|
717
756
|
}
|
|
718
|
-
|
|
757
|
+
else if (d?.type === 'thinking_delta' && typeof d.thinking === 'string' && d.thinking.length) {
|
|
758
|
+
// 1.21(R-TOKENHUB-1 / D-T1):thinking 文本增量捕获(原容错跳过 → 落链 + 工具环回传)
|
|
759
|
+
yield { thinkingDelta: d.thinking };
|
|
760
|
+
}
|
|
761
|
+
else if (d?.type === 'signature_delta' && typeof d.signature === 'string' && d.signature.length) {
|
|
762
|
+
yield { thinkingSignatureDelta: d.signature };
|
|
763
|
+
}
|
|
764
|
+
// citations_delta 等其余非 CAR 消费面:容错跳过
|
|
719
765
|
}
|
|
720
766
|
else if (type === 'message_start') {
|
|
721
767
|
// 1.11-S1(D-33):input 侧采集(usage 嵌套在 message 下)
|
|
@@ -86,6 +86,12 @@ export interface LlmChunk {
|
|
|
86
86
|
};
|
|
87
87
|
/** 1.11-S1(D-33):每次请求最后一个 chunk 附带归一化用量;缺失 = provider 未回,禁补造 */
|
|
88
88
|
usage?: LlmUsage;
|
|
89
|
+
/** thinking 块文本增量(content_block_delta.thinking_delta) */
|
|
90
|
+
thinkingDelta?: string;
|
|
91
|
+
/** thinking 块签名增量(signature_delta——真 Anthropic thinking 块回传须携签名) */
|
|
92
|
+
thinkingSignatureDelta?: string;
|
|
93
|
+
/** redacted_thinking 块 data 全文(content_block_start 单发;回传形态 {type:'redacted_thinking',data}) */
|
|
94
|
+
thinkingRedacted?: string;
|
|
89
95
|
}
|
|
90
96
|
/** Provider 适配器(ACL,C-02):统一签名,消解 Provider 差异 */
|
|
91
97
|
export interface LlmAdapter {
|
package/dist/sbom.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CAR-SBOM",
|
|
3
3
|
"specVersion": "0.1",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.21.1",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
7
7
|
"type": "file",
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
{
|
|
162
162
|
"type": "file",
|
|
163
163
|
"path": "src/runtime-core/chatStep.ts",
|
|
164
|
-
"sha256": "
|
|
164
|
+
"sha256": "b7cf35ba06ebaae339a89da0e4df08b5ae310a60a97b5201de54f092fc8758ab"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"type": "file",
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
{
|
|
177
177
|
"type": "file",
|
|
178
178
|
"path": "src/runtime-core/llm.ts",
|
|
179
|
-
"sha256": "
|
|
179
|
+
"sha256": "9e481456aa224c468ccdf6b577ce1e1d0c2b91aeeaa2c0f195ee40c779b7da02"
|
|
180
180
|
},
|
|
181
181
|
{
|
|
182
182
|
"type": "file",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
{
|
|
202
202
|
"type": "file",
|
|
203
203
|
"path": "src/runtime-core/types.ts",
|
|
204
|
-
"sha256": "
|
|
204
|
+
"sha256": "d9ff638ea4de9b89d56238f2d7fd65c07dd29323fcb9906e72b6877618a360a6"
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
207
|
"type": "file",
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
{
|
|
252
252
|
"type": "file",
|
|
253
253
|
"path": "src/session/log.ts",
|
|
254
|
-
"sha256": "
|
|
254
|
+
"sha256": "9b3a081bfa60e046166cce11203848402f52d4e9b9d0f94ad2e9dc1f0ebadd9c"
|
|
255
255
|
},
|
|
256
256
|
{
|
|
257
257
|
"type": "file",
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
{
|
|
272
272
|
"type": "file",
|
|
273
273
|
"path": "package.json",
|
|
274
|
-
"sha256": "
|
|
274
|
+
"sha256": "707102222be862dbc4f2d6d5aa3168472401d186934edf95ef21d6cc950ca998"
|
|
275
275
|
},
|
|
276
276
|
{
|
|
277
277
|
"type": "file",
|
package/dist/session/log.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type EventKind = 'user' | 'assistant' | 'toolCall' | 'toolResult' | 'turnEnd' | 'goalUpdate' | 'hostRaw' | 'fork' | 'system' | 'usage' | 'compact' | 'routing' | 'memory';
|
|
1
|
+
export type EventKind = 'user' | 'assistant' | 'toolCall' | 'toolResult' | 'turnEnd' | 'goalUpdate' | 'hostRaw' | 'fork' | 'system' | 'usage' | 'compact' | 'routing' | 'memory' | 'thinking';
|
|
2
2
|
export type Actor = 'user' | 'model' | 'plugin' | 'runtime';
|
|
3
3
|
export interface SessionEvent {
|
|
4
4
|
seq: number;
|
package/dist/session/log.js
CHANGED
|
@@ -122,15 +122,45 @@ export class SessionLog {
|
|
|
122
122
|
const out = [];
|
|
123
123
|
if (compactEvent)
|
|
124
124
|
out.push({ role: 'system', content: (compactEvent.payload.summary) });
|
|
125
|
+
// 1.21(R-TOKENHUB-1 / D-T3):thinking 投影——同 turn 内 thinking 事件附加到首个后续
|
|
126
|
+
// toolCall 消息(原始 provider assistant 消息 = [thinking, ...tool_use] 的重放形态);
|
|
127
|
+
// standalone(无后续 toolCall)/ 被 user·system 隔断 / 跨 turn 不投影(实证:普通两轮
|
|
128
|
+
// 历史不要求回传);assistant(text) 同 turn 不隔断(链序 thinking→assistant→toolCall);
|
|
129
|
+
// 无 thinking 事件投影逐字节不变(D-T5 兼容线,N1 快照自洽)。
|
|
130
|
+
let pendingThinking = null;
|
|
125
131
|
for (const e of projected) {
|
|
132
|
+
if (pendingThinking && (e.turnId !== pendingThinking.turnId || e.kind === 'user' || e.kind === 'system'))
|
|
133
|
+
pendingThinking = null;
|
|
134
|
+
if (e.kind === 'thinking') {
|
|
135
|
+
const p = typeof e.payload === 'string' ? e.payload : '';
|
|
136
|
+
if (p.length || e.meta?.redacted === true) {
|
|
137
|
+
pendingThinking = {
|
|
138
|
+
turnId: e.turnId,
|
|
139
|
+
text: p,
|
|
140
|
+
...(typeof e.meta?.signature === 'string' && e.meta.signature ? { signature: e.meta.signature } : {}),
|
|
141
|
+
...(e.meta?.redacted === true ? { redacted: true } : {}),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
continue; // thinking 不单独成消息(无独立回传语义)
|
|
145
|
+
}
|
|
126
146
|
if (e.kind === 'system')
|
|
127
147
|
out.push({ role: 'system', content: e.payload });
|
|
128
148
|
else if (e.kind === 'user')
|
|
129
149
|
out.push({ role: 'user', content: e.payload });
|
|
130
150
|
else if (e.kind === 'assistant')
|
|
131
151
|
out.push({ role: 'assistant', content: e.payload });
|
|
132
|
-
else if (e.kind === 'toolCall')
|
|
133
|
-
|
|
152
|
+
else if (e.kind === 'toolCall') {
|
|
153
|
+
const msg = { role: 'assistant', toolCall: e.payload };
|
|
154
|
+
if (pendingThinking) {
|
|
155
|
+
msg.thinking = {
|
|
156
|
+
text: pendingThinking.text,
|
|
157
|
+
...(pendingThinking.signature ? { signature: pendingThinking.signature } : {}),
|
|
158
|
+
...(pendingThinking.redacted ? { redacted: true } : {}),
|
|
159
|
+
};
|
|
160
|
+
pendingThinking = null; // 首 toolCall 消费即清——同 turn 多 toolCall = 同一原始消息,单块重放
|
|
161
|
+
}
|
|
162
|
+
out.push(msg);
|
|
163
|
+
}
|
|
134
164
|
else if (e.kind === 'toolResult') {
|
|
135
165
|
const id = e.payload?.id;
|
|
136
166
|
if (typeof id === 'string' && lastSeqById.get(id) !== e.seq)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lqc123qwe/car-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.1",
|
|
4
4
|
"description": "Composable Agent Runtime (CAR) - microkernel plugin system with sandboxed PTC, append-only hashed session log, and MCP host bridge",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -81,7 +81,14 @@ export async function chatStep(opts: ChatStepOptions): Promise<ChatStepResult> {
|
|
|
81
81
|
const messages = log.deriveMessages(undefined, { activeTurnId: turnId }).map(m => ({
|
|
82
82
|
role: m.role as 'system' | 'user' | 'assistant' | 'toolResult',
|
|
83
83
|
content: (m as unknown as { toolCall?: unknown }).toolCall !== undefined
|
|
84
|
-
? {
|
|
84
|
+
? {
|
|
85
|
+
toolCall: (m as unknown as { toolCall: unknown }).toolCall,
|
|
86
|
+
// 1.21(R-TOKENHUB-1 / D-T3/D-T4):投影层附加的同 turn thinking 三元组随 toolCall
|
|
87
|
+
// 载荷透传(适配器回传消费——toAnthropic 前置 thinking 块;openai 形忽略该键)
|
|
88
|
+
...((m as unknown as { thinking?: unknown }).thinking !== undefined
|
|
89
|
+
? { thinking: (m as unknown as { thinking: unknown }).thinking }
|
|
90
|
+
: {}),
|
|
91
|
+
}
|
|
85
92
|
: m.content,
|
|
86
93
|
}))
|
|
87
94
|
|
|
@@ -89,6 +96,11 @@ export async function chatStep(opts: ChatStepOptions): Promise<ChatStepResult> {
|
|
|
89
96
|
const redactor = new StreamRedactor()
|
|
90
97
|
let text = ''
|
|
91
98
|
const calls = new Map<number, { id?: string; name?: string; argsBuf: string }>()
|
|
99
|
+
// 1.21(R-TOKENHUB-1 / D-T1/D-T2):thinking 捕获累积——禁改写(回传签名完整性 > 脱敏
|
|
100
|
+
// 改写),provider 事实字节保真;redacted_thinking = data 全文单发覆盖
|
|
101
|
+
let thinkingText = ''
|
|
102
|
+
let thinkingSignature = ''
|
|
103
|
+
let thinkingRedacted: string | undefined
|
|
92
104
|
let stopReason: ModelStep['stopReason'] | undefined
|
|
93
105
|
let errorDetail: string | undefined
|
|
94
106
|
let usage: LlmUsage | undefined
|
|
@@ -124,6 +136,10 @@ export async function chatStep(opts: ChatStepOptions): Promise<ChatStepResult> {
|
|
|
124
136
|
if (chunk.toolCallDelta.argumentsDelta) cur.argsBuf += chunk.toolCallDelta.argumentsDelta
|
|
125
137
|
calls.set(idx, cur)
|
|
126
138
|
}
|
|
139
|
+
// 1.21(R-TOKENHUB-1 / D-T1):thinking 三面捕获(text/signature 增量累积、redacted 单发覆盖)
|
|
140
|
+
if (chunk.thinkingDelta !== undefined) thinkingText += chunk.thinkingDelta
|
|
141
|
+
if (chunk.thinkingSignatureDelta !== undefined) thinkingSignature += chunk.thinkingSignatureDelta
|
|
142
|
+
if (chunk.thinkingRedacted !== undefined) thinkingRedacted = chunk.thinkingRedacted
|
|
127
143
|
if (chunk.error) errorDetail = chunk.error.message
|
|
128
144
|
if (chunk.usage) usage = chunk.usage // D-33:附着于最后一个 chunk——后到覆盖
|
|
129
145
|
if (chunk.finishReason !== undefined) stopReason = chunk.finishReason === 'aborted' ? 'error' : chunk.finishReason
|
|
@@ -157,6 +173,21 @@ export async function chatStep(opts: ChatStepOptions): Promise<ChatStepResult> {
|
|
|
157
173
|
})
|
|
158
174
|
}
|
|
159
175
|
|
|
176
|
+
// 5a. 1.21(R-TOKENHUB-1 / D-T2):thinking 事件落链(actor='model',先于 assistant/toolCall
|
|
177
|
+
// ——投影层按同 turn 首 toolCall 附加回传)。payload = thinking 原文禁改写(签名完整性 >
|
|
178
|
+
// 脱敏改写——改写即回传校验失败);secretsRedacted 仅计数留痕(审计信号,不复写);
|
|
179
|
+
// redacted 形态 payload = data 全文(meta.redacted=true)。无 thinking chunk = 零新事件
|
|
180
|
+
// (D-T5 字节兼容,链形态与 1.20 全等)。
|
|
181
|
+
if (thinkingText.length || thinkingRedacted !== undefined) {
|
|
182
|
+
const thinkingPayload = thinkingRedacted ?? thinkingText
|
|
183
|
+
const secretsInThinking = scanSecrets(thinkingPayload).hits.length
|
|
184
|
+
log.append('model', 'thinking', turnId, thinkingPayload, {
|
|
185
|
+
...(thinkingRedacted !== undefined ? { redacted: true } : {}),
|
|
186
|
+
...(thinkingSignature ? { signature: thinkingSignature } : {}),
|
|
187
|
+
...(secretsInThinking ? { secretsRedacted: secretsInThinking } : {}),
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
160
191
|
// 5. assistant 文本落 M7(脱敏后 + 计数留痕;空文本不产事件)
|
|
161
192
|
// flush 后兜底复扫只计数不复写:流式遮蔽已生效,>0 即流式边界逃逸的审计信号
|
|
162
193
|
let secretsRedacted = 0
|
package/src/runtime-core/llm.ts
CHANGED
|
@@ -655,12 +655,33 @@ function toAnthropic(req: LlmRequest, apiKey: string, cache: { rolling: boolean;
|
|
|
655
655
|
turns.push({ role: 'user', content: pendingToolResults })
|
|
656
656
|
pendingToolResults = []
|
|
657
657
|
}
|
|
658
|
+
// 1.21.1(R-TOKENHUB-1 二分实证):同轮拆分重放合并——投影形态 [assistant(text)][assistant(toolCall)…]
|
|
659
|
+
// 在 tools 声明在场时被 tokenhub 网关严格路径拒绝(400 reasoning_content must be passed back,
|
|
660
|
+
// 与 thinking 是否已在 wire 无关——P-B/P-C vs P-D 四探针二分定案);provider 原始回复 = 单条
|
|
661
|
+
// [thinking?, text?, tool_use…] 消息,合并重放(P-D)过审。合并口径:
|
|
662
|
+
// - 相邻 assistant(toolCall) 聚合(同 turn 多 tool_use 单条);thinking 取首条附加;
|
|
663
|
+
// - 紧邻前驱为 assistant 纯文本消息 → 弹回合并为 [thinking?, text, tool_use…];
|
|
664
|
+
// - 无相邻文本的 toolCall 消息形态不变([thinking?, tool_use])——非工具环链逐字节兼容(D-T5)。
|
|
665
|
+
let pendingTu: { toolCalls: Array<{ type: 'tool_use'; id: string; name: string; input: unknown }>; thinkingBlock?: Record<string, unknown> } | null = null
|
|
666
|
+
const flushTu = () => {
|
|
667
|
+
if (!pendingTu) return
|
|
668
|
+
const prev = turns[turns.length - 1]
|
|
669
|
+
const { thinkingBlock, toolCalls } = pendingTu
|
|
670
|
+
if (prev && prev.role === 'assistant' && typeof prev.content === 'string') {
|
|
671
|
+
turns.pop()
|
|
672
|
+
turns.push({ role: 'assistant', content: [...(thinkingBlock ? [thinkingBlock] : []), { type: 'text', text: prev.content }, ...toolCalls] })
|
|
673
|
+
} else {
|
|
674
|
+
turns.push({ role: 'assistant', content: [...(thinkingBlock ? [thinkingBlock] : []), ...toolCalls] })
|
|
675
|
+
}
|
|
676
|
+
pendingTu = null
|
|
677
|
+
}
|
|
658
678
|
for (const m of req.messages) {
|
|
659
679
|
if (m.role === 'system') {
|
|
660
680
|
system.push(typeof m.content === 'string' ? m.content : JSON.stringify(m.content))
|
|
661
681
|
continue
|
|
662
682
|
}
|
|
663
683
|
if (m.role === 'toolResult') {
|
|
684
|
+
flushTu() // tool_result 前 = 同轮 assistant 消息收口([text?,tu…] 先于 tool_result 出站)
|
|
664
685
|
const p = m.content as { id?: string; result?: unknown; error?: string }
|
|
665
686
|
pendingToolResults.push({
|
|
666
687
|
type: 'tool_result',
|
|
@@ -670,14 +691,26 @@ function toAnthropic(req: LlmRequest, apiKey: string, cache: { rolling: boolean;
|
|
|
670
691
|
})
|
|
671
692
|
continue
|
|
672
693
|
}
|
|
673
|
-
flushToolResults()
|
|
674
694
|
if (m.role === 'assistant' && m.content != null && typeof m.content === 'object' && 'toolCall' in (m.content as object)) {
|
|
675
695
|
const tc = (m.content as { toolCall: { id: string; tool: string; args: unknown } }).toolCall
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
696
|
+
// 1.21(R-TOKENHUB-1 / D-T4):工具环回传——投影层附加的 thinking(同 turn 原始 assistant
|
|
697
|
+
// 消息的 thinking 块)前置重放。1.21.1:thinking 块随合并缓冲进同轮单条消息(见 flushTu 注记);
|
|
698
|
+
// 无 thinking = 1.20 形态。
|
|
699
|
+
const th = (m.content as { thinking?: { text?: string; signature?: string; redacted?: boolean } }).thinking
|
|
700
|
+
const thinkingBlock = th?.text?.length
|
|
701
|
+
? th.redacted
|
|
702
|
+
? { type: 'redacted_thinking', data: th.text }
|
|
703
|
+
: { type: 'thinking', thinking: th.text, ...(th.signature ? { signature: th.signature } : {}) }
|
|
704
|
+
: undefined
|
|
705
|
+
if (!pendingTu) pendingTu = { toolCalls: [], ...(thinkingBlock ? { thinkingBlock } : {}) }
|
|
706
|
+
pendingTu.toolCalls.push({ type: 'tool_use', id: tc.id, name: tc.tool, input: tc.args ?? {} })
|
|
707
|
+
continue
|
|
679
708
|
}
|
|
709
|
+
flushTu()
|
|
710
|
+
flushToolResults()
|
|
711
|
+
turns.push({ role: m.role, content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content) })
|
|
680
712
|
}
|
|
713
|
+
flushTu()
|
|
681
714
|
flushToolResults()
|
|
682
715
|
// 1.20-K1(D-48 P2):滚动断点在白名单命中时挂尾部消息(缺省 1 个)——system 断点(P1)
|
|
683
716
|
// 与消息断点独立,off 时两者俱灭(rollingCacheAllowed 内已连坐)
|
|
@@ -746,6 +779,9 @@ async function* parseAnthropicSseStream(body: AsyncIterable<Uint8Array>, model:
|
|
|
746
779
|
const block = evt.content_block
|
|
747
780
|
if (block?.type === 'tool_use') {
|
|
748
781
|
yield { toolCallDelta: { index: evt.index, id: block.id, name: block.name } }
|
|
782
|
+
} else if (block?.type === 'redacted_thinking' && typeof block.data === 'string' && block.data.length) {
|
|
783
|
+
// 1.21(R-TOKENHUB-1 / D-T1):redacted_thinking 全文单发(回传形态 {type:'redacted_thinking',data})
|
|
784
|
+
yield { thinkingRedacted: block.data }
|
|
749
785
|
}
|
|
750
786
|
} else if (type === 'content_block_delta') {
|
|
751
787
|
const d = evt.delta
|
|
@@ -753,8 +789,13 @@ async function* parseAnthropicSseStream(body: AsyncIterable<Uint8Array>, model:
|
|
|
753
789
|
yield { delta: d.text }
|
|
754
790
|
} else if (d?.type === 'input_json_delta' && typeof d.partial_json === 'string' && d.partial_json.length) {
|
|
755
791
|
yield { toolCallDelta: { index: evt.index, argumentsDelta: d.partial_json } }
|
|
792
|
+
} else if (d?.type === 'thinking_delta' && typeof d.thinking === 'string' && d.thinking.length) {
|
|
793
|
+
// 1.21(R-TOKENHUB-1 / D-T1):thinking 文本增量捕获(原容错跳过 → 落链 + 工具环回传)
|
|
794
|
+
yield { thinkingDelta: d.thinking }
|
|
795
|
+
} else if (d?.type === 'signature_delta' && typeof d.signature === 'string' && d.signature.length) {
|
|
796
|
+
yield { thinkingSignatureDelta: d.signature }
|
|
756
797
|
}
|
|
757
|
-
//
|
|
798
|
+
// citations_delta 等其余非 CAR 消费面:容错跳过
|
|
758
799
|
} else if (type === 'message_start') {
|
|
759
800
|
// 1.11-S1(D-33):input 侧采集(usage 嵌套在 message 下)
|
|
760
801
|
const u = (evt.message as Record<string, unknown> | undefined)?.usage
|
|
@@ -76,6 +76,14 @@ export interface LlmChunk {
|
|
|
76
76
|
error?: { code: string; message: string }
|
|
77
77
|
/** 1.11-S1(D-33):每次请求最后一个 chunk 附带归一化用量;缺失 = provider 未回,禁补造 */
|
|
78
78
|
usage?: LlmUsage
|
|
79
|
+
// —— 1.21(R-TOKENHUB-1 / D-T1)thinking 捕获加法——anthropic SSE thinking 面捕获;
|
|
80
|
+
// 禁改写(回传签名完整性 > 脱敏改写);缺失 = provider 未发 thinking,禁补造
|
|
81
|
+
/** thinking 块文本增量(content_block_delta.thinking_delta) */
|
|
82
|
+
thinkingDelta?: string
|
|
83
|
+
/** thinking 块签名增量(signature_delta——真 Anthropic thinking 块回传须携签名) */
|
|
84
|
+
thinkingSignatureDelta?: string
|
|
85
|
+
/** redacted_thinking 块 data 全文(content_block_start 单发;回传形态 {type:'redacted_thinking',data}) */
|
|
86
|
+
thinkingRedacted?: string
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
/** Provider 适配器(ACL,C-02):统一签名,消解 Provider 差异 */
|
package/src/session/log.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { createHash } from 'node:crypto'
|
|
|
11
11
|
import { readFileSync } from 'node:fs'
|
|
12
12
|
import { decodeLogBuffer, splitJsonlLines } from './format.ts'
|
|
13
13
|
|
|
14
|
-
export type EventKind = 'user' | 'assistant' | 'toolCall' | 'toolResult' | 'turnEnd' | 'goalUpdate' | 'hostRaw' | 'fork' | 'system' | 'usage' | 'compact' | 'routing' | 'memory' // M3-S11 加法扩展:多宿主归一化降级通道(pattern 未命中留痕,零静默);M5-DEC4 加法扩展:跨宿主 fork 标记事件;1.4-S2 加法扩展:system prompt 落链(§3.5.5:新模型可见输入 = 新事件类型);1.11-S2 加法扩展:usage 计量事实(D-33,actor='runtime'、model_visible=0 不进模型消息流,deriveMessages 不投影);六值 TurnEndReason 不变;1.14-S2 加法扩展(K-MP-2 / D-40):历史压缩事件(actor='runtime',append-only 只追加——payload={summary, compactedUpTo, ...},投影按 compactedUpTo 前缀折叠为摘要,原事件链不改写);1.14-S4 加法扩展(K-POOL-1 / D-42):模型池路由决策(actor='runtime',payload.type='decide',selected/reason/retries/attempts——禁静默换模型;model_visible=0 不进模型消息流,deriveMessages 不投影——同 usage 纪律);1.15-S1 加法扩展(K-MEM-1 / D-46):白盒记忆操作事件(actor='user' 宿主代理用户操作,turnId='memory' 会话级标识同 'compaction' 先例,payload.type='write'|'edit'|'delete'|'rollback'——审计链同源差异化面,链即版本库〔rollback 恢复数据源=链上 payload.before/after 全文〕;model_visible=0 不进模型消息流——记忆注入走宿主装配层 system ctx 行,deriveMessages 不投影);
|
|
14
|
+
export type EventKind = 'user' | 'assistant' | 'toolCall' | 'toolResult' | 'turnEnd' | 'goalUpdate' | 'hostRaw' | 'fork' | 'system' | 'usage' | 'compact' | 'routing' | 'memory' | 'thinking' // M3-S11 加法扩展:多宿主归一化降级通道(pattern 未命中留痕,零静默);M5-DEC4 加法扩展:跨宿主 fork 标记事件;1.4-S2 加法扩展:system prompt 落链(§3.5.5:新模型可见输入 = 新事件类型);1.11-S2 加法扩展:usage 计量事实(D-33,actor='runtime'、model_visible=0 不进模型消息流,deriveMessages 不投影);六值 TurnEndReason 不变;1.14-S2 加法扩展(K-MP-2 / D-40):历史压缩事件(actor='runtime',append-only 只追加——payload={summary, compactedUpTo, ...},投影按 compactedUpTo 前缀折叠为摘要,原事件链不改写);1.14-S4 加法扩展(K-POOL-1 / D-42):模型池路由决策(actor='runtime',payload.type='decide',selected/reason/retries/attempts——禁静默换模型;model_visible=0 不进模型消息流,deriveMessages 不投影——同 usage 纪律);1.15-S1 加法扩展(K-MEM-1 / D-46):白盒记忆操作事件(actor='user' 宿主代理用户操作,turnId='memory' 会话级标识同 'compaction' 先例,payload.type='write'|'edit'|'delete'|'rollback'——审计链同源差异化面,链即版本库〔rollback 恢复数据源=链上 payload.before/after 全文〕;model_visible=0 不进模型消息流——记忆注入走宿主装配层 system ctx 行,deriveMessages 不投影);1.21 加法扩展(R-TOKENHUB-1 / D-T2):thinking 事件(actor='model',payload=thinking 原文禁改写,meta={signature?, redacted?, secretsRedacted?}——先于 assistant/toolCall 落链;投影 = 同 turn 首个 toolCall 消息附加回传(工具环 reasoning_content 契约,Anthropic thinking+tool_use 规范同款);standalone/隔断/跨 turn 不投影;无 thinking 事件链投影逐字节不变);
|
|
15
15
|
export type Actor = 'user' | 'model' | 'plugin' | 'runtime'
|
|
16
16
|
export interface SessionEvent {
|
|
17
17
|
seq: number
|
|
@@ -146,11 +146,41 @@ export class SessionLog {
|
|
|
146
146
|
}
|
|
147
147
|
const out: Array<{ role: string; [k: string]: unknown }> = []
|
|
148
148
|
if (compactEvent) out.push({ role: 'system', content: ((compactEvent.payload as { summary: string }).summary) })
|
|
149
|
+
// 1.21(R-TOKENHUB-1 / D-T3):thinking 投影——同 turn 内 thinking 事件附加到首个后续
|
|
150
|
+
// toolCall 消息(原始 provider assistant 消息 = [thinking, ...tool_use] 的重放形态);
|
|
151
|
+
// standalone(无后续 toolCall)/ 被 user·system 隔断 / 跨 turn 不投影(实证:普通两轮
|
|
152
|
+
// 历史不要求回传);assistant(text) 同 turn 不隔断(链序 thinking→assistant→toolCall);
|
|
153
|
+
// 无 thinking 事件投影逐字节不变(D-T5 兼容线,N1 快照自洽)。
|
|
154
|
+
let pendingThinking: { turnId: string; text: string; signature?: string; redacted?: boolean } | null = null
|
|
149
155
|
for (const e of projected) {
|
|
156
|
+
if (pendingThinking && (e.turnId !== pendingThinking.turnId || e.kind === 'user' || e.kind === 'system')) pendingThinking = null
|
|
157
|
+
if (e.kind === 'thinking') {
|
|
158
|
+
const p = typeof e.payload === 'string' ? e.payload : ''
|
|
159
|
+
if (p.length || e.meta?.redacted === true) {
|
|
160
|
+
pendingThinking = {
|
|
161
|
+
turnId: e.turnId,
|
|
162
|
+
text: p,
|
|
163
|
+
...(typeof e.meta?.signature === 'string' && e.meta.signature ? { signature: e.meta.signature } : {}),
|
|
164
|
+
...(e.meta?.redacted === true ? { redacted: true } : {}),
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
continue // thinking 不单独成消息(无独立回传语义)
|
|
168
|
+
}
|
|
150
169
|
if (e.kind === 'system') out.push({ role: 'system', content: e.payload })
|
|
151
170
|
else if (e.kind === 'user') out.push({ role: 'user', content: e.payload })
|
|
152
171
|
else if (e.kind === 'assistant') out.push({ role: 'assistant', content: e.payload })
|
|
153
|
-
else if (e.kind === 'toolCall')
|
|
172
|
+
else if (e.kind === 'toolCall') {
|
|
173
|
+
const msg: { role: string; [k: string]: unknown } = { role: 'assistant', toolCall: e.payload }
|
|
174
|
+
if (pendingThinking) {
|
|
175
|
+
msg.thinking = {
|
|
176
|
+
text: pendingThinking.text,
|
|
177
|
+
...(pendingThinking.signature ? { signature: pendingThinking.signature } : {}),
|
|
178
|
+
...(pendingThinking.redacted ? { redacted: true } : {}),
|
|
179
|
+
}
|
|
180
|
+
pendingThinking = null // 首 toolCall 消费即清——同 turn 多 toolCall = 同一原始消息,单块重放
|
|
181
|
+
}
|
|
182
|
+
out.push(msg)
|
|
183
|
+
}
|
|
154
184
|
else if (e.kind === 'toolResult') {
|
|
155
185
|
const id = (e.payload as { id?: unknown } | null)?.id
|
|
156
186
|
if (typeof id === 'string' && lastSeqById.get(id) !== e.seq) continue // D-23:后续有同 id 最终结果,本条为授权中间记录
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"base64Signature":"MEYCIQCbYahnJCIA6I3JiR78DqF448xO747Dj5VSDZa+DjrhBwIhAOWOh2Ax0tWvzwsaV+OjU2P/tU5+zZ63vwIRgHQ+gSD4","cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUc1ekNDQm0yZ0F3SUJBZ0lVQm5MRi9MSmhtbDh6b2p3Q3NIM1Z3aGtzWGJnd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpZeE1UQTNNRGMwTXpBMFdoY05Nall4TVRBM01EYzFNekEwV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUV2WkJzSDB0WlFzZkh0VzNhZUordVVKaVA2dWJKT0lVSlZnbisKRjFkaWNuK2xlQVo4Uk80UDFUVm5QemFMdlNVNkdaL3dZcGtZWjlPZ0RDOGt2bWk5SDZPQ0JZd3dnZ1dJTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWZCZ05WSFNNRUdEQVdnQlRmCjArblBWaVFSbHZtbzJPa29WYUxHTGhoa1B6QmlCZ05WSFJFQkFmOEVXREJXaGxSb2RIUndjem92TDJkcGRHaDEKWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHpMM0psYkdWaApjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakl3TGpBd09RWUtLd1lCQkFHRHZ6QUJBUVFyYUhSMGNITTZMeTkwCmIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBVkJnb3JCZ0VFQVlPL01BRUMKQkFkeVpXeGxZWE5sTURZR0Npc0dBUVFCZzc4d0FRTUVLR1l6TUdVME5qaGxNRFEyTkRjNVl6QmxOMkUyWm1VdwpaVFE0WVdNeVpUVmhNbUUzTlRoaVpEa3dGUVlLS3dZQkJBR0R2ekFCQkFRSGNtVnNaV0Z6WlRBZ0Jnb3JCZ0VFCkFZTy9NQUVGQkJKc2NXTTJNalF2WTJGeUxYSjFiblJwYldVd0hnWUtLd1lCQkFHRHZ6QUJCZ1FRY21WbWN5OTAKWVdkekx6RXVNakF1TURBN0Jnb3JCZ0VFQVlPL01BRUlCQzBNSzJoMGRIQnpPaTh2ZEc5clpXNHVZV04wYVc5dQpjeTVuYVhSb2RXSjFjMlZ5WTI5dWRHVnVkQzVqYjIwd1pBWUtLd1lCQkFHRHZ6QUJDUVJXREZSb2RIUndjem92CkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHoKTDNKbGJHVmhjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakl3TGpBd09BWUtLd1lCQkFHRHZ6QUJDZ1FxRENobQpNekJsTkRZNFpUQTBOalEzT1dNd1pUZGhObVpsTUdVME9HRmpNbVUxWVRKaE56VTRZbVE1TUIwR0Npc0dBUVFCCmc3OHdBUXNFRHd3TloybDBhSFZpTFdodmMzUmxaREExQmdvckJnRUVBWU8vTUFFTUJDY01KV2gwZEhCek9pOHYKWjJsMGFIVmlMbU52YlM5c2NXTTJNalF2WTJGeUxYSjFiblJwYldVd09BWUtLd1lCQkFHRHZ6QUJEUVFxRENobQpNekJsTkRZNFpUQTBOalEzT1dNd1pUZGhObVpsTUdVME9HRmpNbVUxWVRKaE56VTRZbVE1TUNBR0Npc0dBUVFCCmc3OHdBUTRFRWd3UWNtVm1jeTkwWVdkekx6RXVNakF1TURBYUJnb3JCZ0VFQVlPL01BRVBCQXdNQ2pFek5qRXgKT1RJM01UUXdLUVlLS3dZQkJBR0R2ekFCRUFRYkRCbG9kSFJ3Y3pvdkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMApNQmdHQ2lzR0FRUUJnNzh3QVJFRUNnd0lOamt5TXpRMU5qUXdaQVlLS3dZQkJBR0R2ekFCRWdSV0RGUm9kSFJ3CmN6b3ZMMmRwZEdoMVlpNWpiMjB2YkhGak5qSTBMMk5oY2kxeWRXNTBhVzFsTHk1bmFYUm9kV0l2ZDI5eWEyWnMKYjNkekwzSmxiR1ZoYzJVdWVXMXNRSEpsWm5NdmRHRm5jeTh4TGpJd0xqQXdPQVlLS3dZQkJBR0R2ekFCRXdRcQpEQ2htTXpCbE5EWTRaVEEwTmpRM09XTXdaVGRoTm1abE1HVTBPR0ZqTW1VMVlUSmhOelU0WW1RNU1CY0dDaXNHCkFRUUJnNzh3QVJRRUNRd0hjbVZzWldGelpUQlpCZ29yQmdFRUFZTy9NQUVWQkVzTVNXaDBkSEJ6T2k4dloybDAKYUhWaUxtTnZiUzlzY1dNMk1qUXZZMkZ5TFhKMWJuUnBiV1V2WVdOMGFXOXVjeTl5ZFc1ekx6UXlNelV5TkRJeApPRFl4TDJGMGRHVnRjSFJ6THpFd0ZnWUtLd1lCQkFHRHZ6QUJGZ1FJREFad2RXSnNhV013VUFZS0t3WUJCQUdECnZ6QUJHQVJDREVCeVpYQnZPbXh4WXpZeU5FQTJPVEl6TkRVMk5DOWpZWEl0Y25WdWRHbHRaVUF4TXpZeE1Ua3kKTnpFME9uSmxaanB5WldaekwzUmhaM012TVM0eU1DNHdNSUdLQmdvckJnRUVBZFo1QWdRQ0JId0VlZ0I0QUhZQQozVDB3YXNiSEVUSmpHUjRjbVdjM0FxSktYcmplUEszL2g0cHlnQzhwN280QUFBR2h0UFlEeXdBQUJBTUFSekJGCkFpRUFrQlNnbEJvOThmMVZNMFMyUGhaUnlQWG0yZ1pFWUFSREZnY1JsenlObXprQ0lDUWc2NUgxL1diUjJHUEkKYmk0MlFDVGdhKzlsMDduYU1rTG8zTm5NbDN6eE1Bb0dDQ3FHU000OUJBTURBMmdBTUdVQ01RRGxjdWNsQjhvTwpzVE0reGJ0ems3Z0hEbXhOZ2gzbEEwaHk4NUFaWUdIZG5PSUI5N0JLMGtjcWFWMnhPSUg1SVRnQ01FQTNmU293CkppaUUxbXNVNUlRSGc5V2pDcTB5dkpoNmc1VW5LVDFwY1RFN3FNSCtIYVU0WE0wWHVYK3dHWWpjNGc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","rekorBundle":{"SignedEntryTimestamp":"MEUCIQDB6YqP2KWVy4Fo7LbSrDV7nIEb4z/smHLueDq0QzfuQQIgc0BoLANFB0BT/TS7PHukqcqBjRM0g3tV9AA+Kbq5Jvo=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI0NTQ2ZWJjYzA2Y2NkYjlmMzM3NTRkMmQ5OGVlNDEzYjI1OTM3ZjYxZTZiZDNmZTA2YTZjZmY2MGZhN2FlNTQxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNiWWFobkpDSUE2STNKaVI3OERxRjQ0OHhPNzQ3RGo1VlNEWmErRGpyaEJ3SWhBT1dPaDJBeDB0V3Z6d3NhVitPalUyUC90VTUrelo2M3Z3SVJnSFErZ1NENCIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVYzFla05EUW0weVowRjNTVUpCWjBsVlFtNU1SaTlNU21odGJEaDZiMnAzUTNOSU0xWjNhR3R6V0dKbmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFVUVROTlJHTXdUWHBCTUZkb1kwNU5hbGw0VFZSQk0wMUVZekZOZWtFd1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVYyV2tKelNEQjBXbEZ6WmtoMFZ6TmhaVW9yZFZWS2FWQTJkV0pLVDBsVlNsWm5iaXNLUmpGa2FXTnVLMnhsUVZvNFVrODBVREZVVm01UWVtRk1kbE5WTmtkYUwzZFpjR3RaV2psUFowUkRPR3QyYldrNVNEWlBRMEpaZDNkbloxZEpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFtbENaMDVXU0ZKRlFrRm1PRVZYUkVKWGFHeFNiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmlTRVpxVG1wSk1Fd3lUbWhqYVRGNVpGYzFNR0ZYTVd4TWVUVnVZVmhTYjJSWFNYWmtNamw1WVRKYWMySXpaSHBNTTBwc1lrZFdhQXBqTWxWMVpWY3hjMUZJU214YWJrMTJaRWRHYm1ONU9IaE1ha2wzVEdwQmQwOVJXVXRMZDFsQ1FrRkhSSFo2UVVKQlVWRnlZVWhTTUdOSVRUWk1lVGt3Q21JeWRHeGlhVFZvV1ROU2NHSXlOWHBNYldSd1pFZG9NVmx1Vm5wYVdFcHFZakkxTUZwWE5UQk1iVTUyWWxSQlZrSm5iM0pDWjBWRlFWbFBMMDFCUlVNS1FrRmtlVnBYZUd4WldFNXNUVVJaUjBOcGMwZEJVVkZDWnpjNGQwRlJUVVZMUjFsNlRVZFZNRTVxYUd4TlJGRXlUa1JqTlZsNlFteE9Na1V5V20xVmR3cGFWRkUwV1ZkTmVWcFVWbWhOYlVVelRsUm9hVnBFYTNkR1VWbExTM2RaUWtKQlIwUjJla0ZDUWtGUlNHTnRWbk5hVjBaNldsUkJaMEpuYjNKQ1owVkZDa0ZaVHk5TlFVVkdRa0pLYzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMGhuV1V0TGQxbENRa0ZIUkhaNlFVSkNaMUZSWTIxV2JXTjVPVEFLV1Zka2VreDZSWFZOYWtGMVRVUkJOMEpuYjNKQ1owVkZRVmxQTDAxQlJVbENRekJOU3pKb01HUklRbnBQYVRoMlpFYzVjbHBYTkhWWlYwNHdZVmM1ZFFwamVUVnVZVmhTYjJSWFNqRmpNbFo1V1RJNWRXUkhWblZrUXpWcVlqSXdkMXBCV1V0TGQxbENRa0ZIUkhaNlFVSkRVVkpYUkVaU2IyUklVbmRqZW05MkNrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUV3eVRtaGphVEY1WkZjMU1HRlhNV3hNZVRWdVlWaFNiMlJYU1haa01qbDVZVEphYzJJelpIb0tURE5LYkdKSFZtaGpNbFYxWlZjeGMxRklTbXhhYmsxMlpFZEdibU41T0hoTWFrbDNUR3BCZDA5QldVdExkMWxDUWtGSFJIWjZRVUpEWjFGeFJFTm9iUXBOZWtKc1RrUlpORnBVUVRCT2FsRXpUMWROZDFwVVpHaE9iVnBzVFVkVk1FOUhSbXBOYlZVeFdWUkthRTU2VlRSWmJWRTFUVUl3UjBOcGMwZEJVVkZDQ21jM09IZEJVWE5GUkhkM1Rsb3liREJoU0ZacFRGZG9kbU16VW14YVJFRXhRbWR2Y2tKblJVVkJXVTh2VFVGRlRVSkRZMDFLVjJnd1pFaENlazlwT0hZS1dqSnNNR0ZJVm1sTWJVNTJZbE01YzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkVVVkZ4UkVOb2JRcE5la0pzVGtSWk5GcFVRVEJPYWxFelQxZE5kMXBVWkdoT2JWcHNUVWRWTUU5SFJtcE5iVlV4V1ZSS2FFNTZWVFJaYlZFMVRVTkJSME5wYzBkQlVWRkNDbWMzT0hkQlVUUkZSV2QzVVdOdFZtMWplVGt3V1Zka2VreDZSWFZOYWtGMVRVUkJZVUpuYjNKQ1owVkZRVmxQTDAxQlJWQkNRWGROUTJwRmVrNXFSWGdLVDFSSk0wMVVVWGRMVVZsTFMzZFpRa0pCUjBSMmVrRkNSVUZSWWtSQ2JHOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUFwTlFtZEhRMmx6UjBGUlVVSm5OemgzUVZKRlJVTm5kMGxPYW10NVRYcFJNVTVxVVhkYVFWbExTM2RaUWtKQlIwUjJla0ZDUldkU1YwUkdVbTlrU0ZKM0NtTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZa2hHYWs1cVNUQk1NazVvWTJreGVXUlhOVEJoVnpGc1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTUtZak5rZWt3elNteGlSMVpvWXpKVmRXVlhNWE5SU0Vwc1dtNU5kbVJIUm01amVUaDRUR3BKZDB4cVFYZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JYZFJjUXBFUTJodFRYcENiRTVFV1RSYVZFRXdUbXBSTTA5WFRYZGFWR1JvVG0xYWJFMUhWVEJQUjBacVRXMVZNVmxVU21oT2VsVTBXVzFSTlUxQ1kwZERhWE5IQ2tGUlVVSm5OemgzUVZKUlJVTlJkMGhqYlZaeldsZEdlbHBVUWxwQ1oyOXlRbWRGUlVGWlR5OU5RVVZXUWtWelRWTlhhREJrU0VKNlQyazRkbG95YkRBS1lVaFdhVXh0VG5aaVV6bHpZMWROTWsxcVVYWlpNa1o1VEZoS01XSnVVbkJpVjFWMldWZE9NR0ZYT1hWamVUbDVaRmMxZWt4NlVYbE5lbFY1VGtSSmVBcFBSRmw0VERKR01HUkhWblJqU0ZKNlRIcEZkMFpuV1V0TGQxbENRa0ZIUkhaNlFVSkdaMUZKUkVGYWQyUlhTbk5oVjAxM1ZVRlpTMHQzV1VKQ1FVZEVDblo2UVVKSFFWSkRSRVZDZVZwWVFuWlBiWGg0V1hwWmVVNUZRVEpQVkVsNlRrUlZNazVET1dwWldFbDBZMjVXZFdSSGJIUmFWVUY0VFhwWmVFMVVhM2tLVG5wRk1FOXVTbXhhYW5CNVdsZGFla3d6VW1oYU0wMTJUVk0wZVUxRE5IZE5TVWRMUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJZDBWbFowSTBRVWhaUVFvelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIyaDBVRmxFZVhkQlFVSkJUVUZTZWtKR0NrRnBSVUZyUWxObmJFSnZPVGhtTVZaTk1GTXlVR2hhVW5sUVdHMHlaMXBGV1VGU1JFWm5ZMUpzZW5sT2JYcHJRMGxEVVdjMk5VZ3hMMWRpVWpKSFVFa0tZbWswTWxGRFZHZGhLemxzTURkdVlVMXJURzh6VG01TmJETjZlRTFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbWRCVFVkVlEwMVJSR3hqZFdOc1FqaHZUd3B6VkUwcmVHSjBlbXMzWjBoRWJYaE9aMmd6YkVFd2FIazROVUZhV1VkSVpHNVBTVUk1TjBKTE1HdGpjV0ZXTW5oUFNVZzFTVlJuUTAxRlFUTm1VMjkzQ2twcGFVVXhiWE5WTlVsUlNHYzVWMnBEY1RCNWRrcG9ObWMxVlc1TFZERndZMVJGTjNGTlNDdElZVlUwV0Uwd1dIVllLM2RIV1dwak5HYzlQUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=","integratedTime":1794037384,"logIndex":3732640096,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}
|