@lqc123qwe/car-runtime 1.14.0 → 1.15.0
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/README.md +12 -1
- package/dist/SHA256SUMS +1 -1
- package/dist/car-runtime-1.15.0.tgz +0 -0
- package/dist/car-runtime-1.15.0.tgz.sig.bundle +1 -0
- package/dist/loop/stop.js +3 -1
- package/dist/memory/store.d.ts +67 -0
- package/dist/memory/store.js +263 -0
- package/dist/release-audit.jsonl +4 -4
- package/dist/runtime-core/chatStep.d.ts +8 -0
- package/dist/runtime-core/chatStep.js +6 -1
- package/dist/sbom.json +17 -7
- package/dist/seam.d.ts +17 -0
- package/dist/seam.js +19 -0
- package/dist/session/log.d.ts +21 -5
- package/dist/session/log.js +34 -7
- package/dist/session/steer.d.ts +35 -0
- package/dist/session/steer.js +19 -0
- package/package.json +1 -1
- package/src/loop/stop.ts +3 -1
- package/src/memory/store.ts +288 -0
- package/src/runtime-core/chatStep.ts +12 -1
- package/src/seam.ts +19 -0
- package/src/session/log.ts +38 -8
- package/src/session/steer.ts +48 -0
- package/dist/car-runtime-1.14.0.tgz +0 -0
- package/dist/car-runtime-1.14.0.tgz.sig.bundle +0 -1
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' // 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
|
|
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 不投影);
|
|
15
15
|
export type Actor = 'user' | 'model' | 'plugin' | 'runtime'
|
|
16
16
|
export interface SessionEvent {
|
|
17
17
|
seq: number
|
|
@@ -32,6 +32,12 @@ const canonical = (e: Omit<SessionEvent, 'hash'>) =>
|
|
|
32
32
|
export interface ModelSnapshot {
|
|
33
33
|
/** 快照对应日志前缀边界(事件数),断言时逐字节比对前缀投影 */
|
|
34
34
|
atSeq: number
|
|
35
|
+
/**
|
|
36
|
+
* 1.15-S2(K-STEER-1 / D-47):快照时宿主声明的活跃 turn——提供时快照投影 = 边界内
|
|
37
|
+
* 「活跃 turn 起点之后落链的他 turn user 事件被过滤」口径(与请求投影同构,N1 逐字节
|
|
38
|
+
* 自洽);缺席 = 全量前缀投影(1.14.1 形态,行为零变化)。
|
|
39
|
+
*/
|
|
40
|
+
activeTurnId?: string
|
|
35
41
|
request: unknown[]
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -67,9 +73,15 @@ export class SessionLog {
|
|
|
67
73
|
return full
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
/** 模型请求发起时调用(agent-loop
|
|
71
|
-
snapshotModelRequest(): ModelSnapshot {
|
|
72
|
-
const
|
|
76
|
+
/** 模型请求发起时调用(agent-loop 集成点):登记「请求时快照」;opts.activeTurnId 见 ModelSnapshot 注记 */
|
|
77
|
+
snapshotModelRequest(opts?: { activeTurnId?: string }): ModelSnapshot {
|
|
78
|
+
const filter = opts?.activeTurnId ? { activeTurnId: opts.activeTurnId } : undefined
|
|
79
|
+
const snap: ModelSnapshot = {
|
|
80
|
+
atSeq: this.events.length,
|
|
81
|
+
// 1.15-S2:口径必须随快照落盘——assert 重算时以同口径投影逐字节比对(漏存 = 口径丢失 → N1 假红)
|
|
82
|
+
...(filter ? { activeTurnId: filter.activeTurnId } : {}),
|
|
83
|
+
request: structuredClone(this.deriveMessages(this.events.length, filter)),
|
|
84
|
+
}
|
|
73
85
|
this.#snapshots.push(snap)
|
|
74
86
|
return snap
|
|
75
87
|
}
|
|
@@ -95,8 +107,14 @@ export class SessionLog {
|
|
|
95
107
|
* 其 compactedUpTo 前缀折叠为单条 system 摘要(事件原文不改写,仅投影层折叠);compact 之前的
|
|
96
108
|
* 请求快照(atSeq ≤ compact.seq)不含 compact 事件 → 投影仍为全量形态(N1 不变量自洽——
|
|
97
109
|
* 「请求时发出 = 日志前缀投影」逐快照成立);无 compact 事件的日志投影与 1.13 逐字节一致。
|
|
110
|
+
* 1.15-S2(K-STEER-1 / D-47)投影隔离:opts.activeTurnId 提供时,跳过「turn 进行中落链的
|
|
111
|
+
* 他 turn user 事件」(特征 = kind='user' 且 seq > 活跃 turn 首事件 seq 且 turnId ≠ 活跃
|
|
112
|
+
* turnId——引导排队事件的链上形态)——**引导 ≠ 注入当前 turn 上下文**;不采用 turn 开始
|
|
113
|
+
* 快照(快照会误杀 turn 内落的 toolResult——agent loop 依赖实时投影),过滤口径精确匹配
|
|
114
|
+
* 「turn 外增量不进、turn 内增量照进」;无引导事件时过滤零命中,投影与 1.14.1 逐字节一致
|
|
115
|
+
* (兼容线)。缺省(无 opts)= 1.14.1 行为零变化。
|
|
98
116
|
*/
|
|
99
|
-
deriveMessages(upTo?: number): Array<{ role: string; [k: string]: unknown }> {
|
|
117
|
+
deriveMessages(upTo?: number, opts?: { activeTurnId?: string }): Array<{ role: string; [k: string]: unknown }> {
|
|
100
118
|
const scoped = upTo !== undefined ? this.events.slice(0, upTo) : this.events
|
|
101
119
|
let compactEvent: SessionEvent | undefined
|
|
102
120
|
for (const e of scoped) { if (e.kind === 'compact') compactEvent = e } // last-wins
|
|
@@ -108,7 +126,18 @@ export class SessionLog {
|
|
|
108
126
|
}
|
|
109
127
|
compactedUpTo = cp.compactedUpTo // 折叠边界 = payload 声明的前缀边界(非 compact 事件自身 seq)
|
|
110
128
|
}
|
|
111
|
-
|
|
129
|
+
// 1.15-S2 投影隔离(D-47):活跃 turn 首事件 seq 之后落链的他 turn user 事件 → 跳过
|
|
130
|
+
let steerSkip: ((e: SessionEvent) => boolean) | undefined
|
|
131
|
+
if (opts?.activeTurnId) {
|
|
132
|
+
let turnStartSeq = -1
|
|
133
|
+
for (const e of scoped) {
|
|
134
|
+
if (e.turnId === opts.activeTurnId) { turnStartSeq = e.seq; break }
|
|
135
|
+
}
|
|
136
|
+
if (turnStartSeq >= 0) {
|
|
137
|
+
steerSkip = (e: SessionEvent) => e.kind === 'user' && e.turnId !== opts.activeTurnId && e.seq > turnStartSeq
|
|
138
|
+
} // 活跃 turn 无链上事件(异常形态)→ 不过滤(fail-safe 退化为 1.14.1 全量投影)
|
|
139
|
+
}
|
|
140
|
+
const projected = compactedUpTo !== undefined ? scoped.filter(e => e.seq >= compactedUpTo! && !(steerSkip?.(e) ?? false)) : scoped.filter(e => !(steerSkip?.(e) ?? false))
|
|
112
141
|
const lastSeqById = new Map<string, number>()
|
|
113
142
|
for (const e of projected) {
|
|
114
143
|
if (e.kind !== 'toolResult') continue
|
|
@@ -131,10 +160,11 @@ export class SessionLog {
|
|
|
131
160
|
return out
|
|
132
161
|
}
|
|
133
162
|
|
|
134
|
-
/** N1 不变量断言(CI
|
|
163
|
+
/** N1 不变量断言(CI 门禁雏形):全部快照必须与当前日志前缀投影逐字节一致(快照口径含 1.15-S2 activeTurnId 过滤) */
|
|
135
164
|
assertModelVisibleLogged(): { ok: boolean; failedAt?: number } {
|
|
136
165
|
for (const s of this.#snapshots) {
|
|
137
|
-
|
|
166
|
+
const filter = s.activeTurnId ? { activeTurnId: s.activeTurnId } : undefined
|
|
167
|
+
if (JSON.stringify(s.request) !== JSON.stringify(this.deriveMessages(s.atSeq, filter))) {
|
|
138
168
|
return { ok: false, failedAt: s.atSeq }
|
|
139
169
|
}
|
|
140
170
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 1.15-S2 · 引导消息排队扫描(K-STEER-1 / D-V02-9 / D-47 ②)
|
|
3
|
+
*
|
|
4
|
+
* 口径(红线先立后码):
|
|
5
|
+
* - **消费契约**:内核出排队扫描查询面(未消费 user 事件按 seq 序枚举),FIFO 续跑调度
|
|
6
|
+
* 在宿主装配层(turn 收口 → 扫描 → 逐条以事件自身 turnId 调 runTurn)——内核不改
|
|
7
|
+
* runTurn 调度语义(D-40 同款宿主装配层纪律);
|
|
8
|
+
* - **pending 判定**:kind='user' 且该 turnId 无 turnEnd 事件(未闭合)。当前执行中 turn
|
|
9
|
+
* 也未闭合但正在消费——由 opts.excludeTurnId 排除(宿主传活跃 turnId);已消费(turnEnd
|
|
10
|
+
* 已落)/ 已被 recover 补记 interrupted(turnEnd 已落,R-8 定性:消息已发未跑,重启后
|
|
11
|
+
* 不重复消费)均不算 pending;
|
|
12
|
+
* - **逐条成 turn 不合并**:每条 pending 条目 = 一条 user 事件(含 turnId 与发出时刻 ts/
|
|
13
|
+
* seq)——宿主逐条消费;同 turnId 多条 user 事件逐条报出(宿主守规形态 = 每条引导消息
|
|
14
|
+
* append 时分配独立 turnId);
|
|
15
|
+
* - **发出时刻落链**:引导 append 本身零包装(SessionLog.append 任意时刻可调——执行中
|
|
16
|
+
* append 无需内核加「允许」逻辑,D-47 ④);**投影隔离红线**(引导不进当前 turn 投影)
|
|
17
|
+
* 在 log.ts deriveMessages activeTurnId 口径落地,非本文件职责;
|
|
18
|
+
* - **model_visible=0**:pending user 事件在其所属 turn 被消费前不进任何模型请求
|
|
19
|
+
* (消费后以正常 user 事件身份进该 turn 投影——Model-visible means logged 由构造保证)。
|
|
20
|
+
*/
|
|
21
|
+
import type { SessionLog } from './log.ts'
|
|
22
|
+
|
|
23
|
+
export interface PendingSteerTurn {
|
|
24
|
+
/** 引导 user 事件 seq(发出时刻链上位置——FIFO 序) */
|
|
25
|
+
seq: number
|
|
26
|
+
/** 引导 user 事件 ts(发出时刻时间戳——链序校验口径) */
|
|
27
|
+
ts: number
|
|
28
|
+
/** 引导事件 turnId(发出时分配的新 turnId——消费时宿主以同 turnId 调 runTurn) */
|
|
29
|
+
turnId: string
|
|
30
|
+
/** 引导消息正文(user 事件 payload 原样) */
|
|
31
|
+
text: unknown
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 排队扫描:未闭合 user 事件按 seq 序枚举(未消费引导队列——宿主 FIFO 续跑消费面) */
|
|
35
|
+
export function pendingSteerTurns(log: SessionLog, opts: { /** 排除当前执行中 turn(其 user 事件也未闭合但正在消费) */ excludeTurnId?: string } = {}): PendingSteerTurn[] {
|
|
36
|
+
const closed = new Set<string>()
|
|
37
|
+
for (const e of log.events) {
|
|
38
|
+
if (e.kind === 'turnEnd') closed.add(e.turnId)
|
|
39
|
+
}
|
|
40
|
+
const out: PendingSteerTurn[] = []
|
|
41
|
+
for (const e of log.events) {
|
|
42
|
+
if (e.kind !== 'user') continue
|
|
43
|
+
if (closed.has(e.turnId)) continue // 已消费 / 已 recover 补记 interrupted——不算 pending
|
|
44
|
+
if (opts.excludeTurnId && e.turnId === opts.excludeTurnId) continue // 当前执行中 turn
|
|
45
|
+
out.push({ seq: e.seq, ts: e.ts, turnId: e.turnId, text: e.payload })
|
|
46
|
+
}
|
|
47
|
+
return out
|
|
48
|
+
}
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"base64Signature":"MEQCIG6L65Cw/EJuDjO6HFYCTaYCu8OOGPkVkVDoPVft3cWUAiAXMhPi5i0bbyhPkqysB2s1G4D1ElUz1xWDe4doxmWOkg==","cert":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUc2RENDQm02Z0F3SUJBZ0lVSGEya1N2UWhCTHFtcGNrcWg3K0lSYUhnRHJBd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpZeE1ERTRNRGd4T1RReFdoY05Nall4TURFNE1EZ3lPVFF4V2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVsa29IQkJmWGsyWXFOdEwzQkN4ZlZRaVkweFcxMWh6aGlwTFAKaXY3UWliKzFpTjBnWkR3amJVZFVBNC90Tm1jSXpya1JIQmRiaE9DL2VFR0pJMXlCcWFPQ0JZMHdnZ1dKTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWZCZ05WSFNNRUdEQVdnQlRmCjArblBWaVFSbHZtbzJPa29WYUxHTGhoa1B6QmlCZ05WSFJFQkFmOEVXREJXaGxSb2RIUndjem92TDJkcGRHaDEKWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHpMM0psYkdWaApjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakUwTGpBd09RWUtLd1lCQkFHRHZ6QUJBUVFyYUhSMGNITTZMeTkwCmIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBVkJnb3JCZ0VFQVlPL01BRUMKQkFkeVpXeGxZWE5sTURZR0Npc0dBUVFCZzc4d0FRTUVLRGt5WVRNMU9UQTBZelV4TnpsaE9UbGpaR0kyT1dRNApNalUwTWprMU0yWTRNbVppT1RJd1ltRXdGUVlLS3dZQkJBR0R2ekFCQkFRSGNtVnNaV0Z6WlRBZ0Jnb3JCZ0VFCkFZTy9NQUVGQkJKc2NXTTJNalF2WTJGeUxYSjFiblJwYldVd0hnWUtLd1lCQkFHRHZ6QUJCZ1FRY21WbWN5OTAKWVdkekx6RXVNVFF1TURBN0Jnb3JCZ0VFQVlPL01BRUlCQzBNSzJoMGRIQnpPaTh2ZEc5clpXNHVZV04wYVc5dQpjeTVuYVhSb2RXSjFjMlZ5WTI5dWRHVnVkQzVqYjIwd1pBWUtLd1lCQkFHRHZ6QUJDUVJXREZSb2RIUndjem92CkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMEwyTmhjaTF5ZFc1MGFXMWxMeTVuYVhSb2RXSXZkMjl5YTJac2IzZHoKTDNKbGJHVmhjMlV1ZVcxc1FISmxabk12ZEdGbmN5OHhMakUwTGpBd09BWUtLd1lCQkFHRHZ6QUJDZ1FxRENnNQpNbUV6TlRrd05HTTFNVGM1WVRrNVkyUmlOamxrT0RJMU5ESTVOVE5tT0RKbVlqa3lNR0poTUIwR0Npc0dBUVFCCmc3OHdBUXNFRHd3TloybDBhSFZpTFdodmMzUmxaREExQmdvckJnRUVBWU8vTUFFTUJDY01KV2gwZEhCek9pOHYKWjJsMGFIVmlMbU52YlM5c2NXTTJNalF2WTJGeUxYSjFiblJwYldVd09BWUtLd1lCQkFHRHZ6QUJEUVFxRENnNQpNbUV6TlRrd05HTTFNVGM1WVRrNVkyUmlOamxrT0RJMU5ESTVOVE5tT0RKbVlqa3lNR0poTUNBR0Npc0dBUVFCCmc3OHdBUTRFRWd3UWNtVm1jeTkwWVdkekx6RXVNVFF1TURBYUJnb3JCZ0VFQVlPL01BRVBCQXdNQ2pFek5qRXgKT1RJM01UUXdLUVlLS3dZQkJBR0R2ekFCRUFRYkRCbG9kSFJ3Y3pvdkwyZHBkR2gxWWk1amIyMHZiSEZqTmpJMApNQmdHQ2lzR0FRUUJnNzh3QVJFRUNnd0lOamt5TXpRMU5qUXdaQVlLS3dZQkJBR0R2ekFCRWdSV0RGUm9kSFJ3CmN6b3ZMMmRwZEdoMVlpNWpiMjB2YkhGak5qSTBMMk5oY2kxeWRXNTBhVzFsTHk1bmFYUm9kV0l2ZDI5eWEyWnMKYjNkekwzSmxiR1ZoYzJVdWVXMXNRSEpsWm5NdmRHRm5jeTh4TGpFMExqQXdPQVlLS3dZQkJBR0R2ekFCRXdRcQpEQ2c1TW1Fek5Ua3dOR00xTVRjNVlUazVZMlJpTmpsa09ESTFOREk1TlRObU9ESm1Zamt5TUdKaE1CY0dDaXNHCkFRUUJnNzh3QVJRRUNRd0hjbVZzWldGelpUQlpCZ29yQmdFRUFZTy9NQUVWQkVzTVNXaDBkSEJ6T2k4dloybDAKYUhWaUxtTnZiUzlzY1dNMk1qUXZZMkZ5TFhKMWJuUnBiV1V2WVdOMGFXOXVjeTl5ZFc1ekx6TTVNVEV4TURBeApOemN6TDJGMGRHVnRjSFJ6THpFd0ZnWUtLd1lCQkFHRHZ6QUJGZ1FJREFad2RXSnNhV013VUFZS0t3WUJCQUdECnZ6QUJHQVJDREVCeVpYQnZPbXh4WXpZeU5FQTJPVEl6TkRVMk5DOWpZWEl0Y25WdWRHbHRaVUF4TXpZeE1Ua3kKTnpFME9uSmxaanB5WldaekwzUmhaM012TVM0eE5DNHdNSUdMQmdvckJnRUVBZFo1QWdRQ0JIMEVld0I1QUhjQQozVDB3YXNiSEVUSmpHUjRjbVdjM0FxSktYcmplUEszL2g0cHlnQzhwN280QUFBR2hUaGhaYmdBQUJBTUFTREJHCkFpRUFxZkN4Nnh6R3V0T1NveVRLSDdsVFN4dFRMMHBmNGtQR1REMlliWEtISmxJQ0lRQ01CZ1ZaR0dZR3pPa0IKSk1VL2JENWxMMXA4S3lWYkR0ZlNBRWl0NDN0cFpqQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQkx5a0dvTHp3dwpVZXF5SmZad1IrOTR6bWsxRzZRR0swVWtpSUtsUEM0eWxtNUlueXhBT1pwaWpIZ25aUHl2VTZNQ01RRHI4Mm10CmpKemEwRXd2NDFubkxpUDBEVy9qYW1MOXF3aC93ak54VmxrclVGakQzcGcyNk5ybThCVVhQZzZqTE1JPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","rekorBundle":{"SignedEntryTimestamp":"MEUCIG4EQ9bsQTzIrNCFQRZJmPPk2dKTOUsPeM6kNbcaPbYCAiEApBqdeQqsIRei7A1LULq4t5e1lBrMT5oBf+nC0GoPyzM=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjYjQzZWMwYjliMWY3YWQ0MzY1ZGMxYTMwZGJkYzZiNDFlYzY1YTViMjMzMjZjOTdmNDJiMmQ0ODZiMjAxNjdkIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRzZMNjVDdy9FSnVEak82SEZZQ1RhWUN1OE9PR1BrVmtWRG9QVmZ0M2NXVUFpQVhNaFBpNWkwYmJ5aFBrcXlzQjJzMUc0RDFFbFV6MXhXRGU0ZG94bVdPa2c9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVYzJSRU5EUW0wMlowRjNTVUpCWjBsVlNHRXlhMU4yVVdoQ1RIRnRjR05yY1dnM0swbFNZVWhuUkhKQmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFFUlRSTlJHZDRUMVJSZUZkb1kwNU5hbGw0VFVSRk5FMUVaM2xQVkZGNFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZzYTI5SVFrSm1XR3N5V1hGT2RFd3pRa040WmxaUmFWa3dlRmN4TVdoNmFHbHdURkFLYVhZM1VXbGlLekZwVGpCbldrUjNhbUpWWkZWQk5DOTBUbTFqU1hweWExSklRbVJpYUU5REwyVkZSMHBKTVhsQ2NXRlBRMEpaTUhkbloxZEtUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFtbENaMDVXU0ZKRlFrRm1PRVZYUkVKWGFHeFNiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmlTRVpxVG1wSk1Fd3lUbWhqYVRGNVpGYzFNR0ZYTVd4TWVUVnVZVmhTYjJSWFNYWmtNamw1WVRKYWMySXpaSHBNTTBwc1lrZFdhQXBqTWxWMVpWY3hjMUZJU214YWJrMTJaRWRHYm1ONU9IaE1ha1V3VEdwQmQwOVJXVXRMZDFsQ1FrRkhSSFo2UVVKQlVWRnlZVWhTTUdOSVRUWk1lVGt3Q21JeWRHeGlhVFZvV1ROU2NHSXlOWHBNYldSd1pFZG9NVmx1Vm5wYVdFcHFZakkxTUZwWE5UQk1iVTUyWWxSQlZrSm5iM0pDWjBWRlFWbFBMMDFCUlVNS1FrRmtlVnBYZUd4WldFNXNUVVJaUjBOcGMwZEJVVkZDWnpjNGQwRlJUVVZMUkd0NVdWUk5NVTlVUVRCWmVsVjRUbnBzYUU5VWJHcGFSMGt5VDFkUk5BcE5hbFV3VFdwck1VMHlXVFJOYlZwcFQxUkpkMWx0UlhkR1VWbExTM2RaUWtKQlIwUjJla0ZDUWtGUlNHTnRWbk5hVjBaNldsUkJaMEpuYjNKQ1owVkZDa0ZaVHk5TlFVVkdRa0pLYzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMGhuV1V0TGQxbENRa0ZIUkhaNlFVSkNaMUZSWTIxV2JXTjVPVEFLV1Zka2VreDZSWFZOVkZGMVRVUkJOMEpuYjNKQ1owVkZRVmxQTDAxQlJVbENRekJOU3pKb01HUklRbnBQYVRoMlpFYzVjbHBYTkhWWlYwNHdZVmM1ZFFwamVUVnVZVmhTYjJSWFNqRmpNbFo1V1RJNWRXUkhWblZrUXpWcVlqSXdkMXBCV1V0TGQxbENRa0ZIUkhaNlFVSkRVVkpYUkVaU2IyUklVbmRqZW05MkNrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUV3eVRtaGphVEY1WkZjMU1HRlhNV3hNZVRWdVlWaFNiMlJYU1haa01qbDVZVEphYzJJelpIb0tURE5LYkdKSFZtaGpNbFYxWlZjeGMxRklTbXhhYmsxMlpFZEdibU41T0hoTWFrVXdUR3BCZDA5QldVdExkMWxDUWtGSFJIWjZRVUpEWjFGeFJFTm5OUXBOYlVWNlRsUnJkMDVIVFRGTlZHTTFXVlJyTlZreVVtbE9hbXhyVDBSSk1VNUVTVFZPVkU1dFQwUktiVmxxYTNsTlIwcG9UVUl3UjBOcGMwZEJVVkZDQ21jM09IZEJVWE5GUkhkM1Rsb3liREJoU0ZacFRGZG9kbU16VW14YVJFRXhRbWR2Y2tKblJVVkJXVTh2VFVGRlRVSkRZMDFLVjJnd1pFaENlazlwT0hZS1dqSnNNR0ZJVm1sTWJVNTJZbE01YzJOWFRUSk5hbEYyV1RKR2VVeFlTakZpYmxKd1lsZFZkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkVVVkZ4UkVObk5RcE5iVVY2VGxScmQwNUhUVEZOVkdNMVdWUnJOVmt5VW1sT2FteHJUMFJKTVU1RVNUVk9WRTV0VDBSS2JWbHFhM2xOUjBwb1RVTkJSME5wYzBkQlVWRkNDbWMzT0hkQlVUUkZSV2QzVVdOdFZtMWplVGt3V1Zka2VreDZSWFZOVkZGMVRVUkJZVUpuYjNKQ1owVkZRVmxQTDAxQlJWQkNRWGROUTJwRmVrNXFSWGdLVDFSSk0wMVVVWGRMVVZsTFMzZFpRa0pCUjBSMmVrRkNSVUZSWWtSQ2JHOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaVNFWnFUbXBKTUFwTlFtZEhRMmx6UjBGUlVVSm5OemgzUVZKRlJVTm5kMGxPYW10NVRYcFJNVTVxVVhkYVFWbExTM2RaUWtKQlIwUjJla0ZDUldkU1YwUkdVbTlrU0ZKM0NtTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZa2hHYWs1cVNUQk1NazVvWTJreGVXUlhOVEJoVnpGc1RIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTUtZak5rZWt3elNteGlSMVpvWXpKVmRXVlhNWE5SU0Vwc1dtNU5kbVJIUm01amVUaDRUR3BGTUV4cVFYZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JYZFJjUXBFUTJjMVRXMUZlazVVYTNkT1IwMHhUVlJqTlZsVWF6VlpNbEpwVG1wc2EwOUVTVEZPUkVrMVRsUk9iVTlFU20xWmFtdDVUVWRLYUUxQ1kwZERhWE5IQ2tGUlVVSm5OemgzUVZKUlJVTlJkMGhqYlZaeldsZEdlbHBVUWxwQ1oyOXlRbWRGUlVGWlR5OU5RVVZXUWtWelRWTlhhREJrU0VKNlQyazRkbG95YkRBS1lVaFdhVXh0VG5aaVV6bHpZMWROTWsxcVVYWlpNa1o1VEZoS01XSnVVbkJpVjFWMldWZE9NR0ZYT1hWamVUbDVaRmMxZWt4NlRUVk5WRVY0VFVSQmVBcE9lbU42VERKR01HUkhWblJqU0ZKNlRIcEZkMFpuV1V0TGQxbENRa0ZIUkhaNlFVSkdaMUZKUkVGYWQyUlhTbk5oVjAxM1ZVRlpTMHQzV1VKQ1FVZEVDblo2UVVKSFFWSkRSRVZDZVZwWVFuWlBiWGg0V1hwWmVVNUZRVEpQVkVsNlRrUlZNazVET1dwWldFbDBZMjVXZFdSSGJIUmFWVUY0VFhwWmVFMVVhM2tLVG5wRk1FOXVTbXhhYW5CNVdsZGFla3d6VW1oYU0wMTJUVk0wZUU1RE5IZE5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVWbGQwSTFRVWhqUVFvelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIyaFVhR2hhWW1kQlFVSkJUVUZUUkVKSENrRnBSVUZ4WmtONE5uaDZSM1YwVDFOdmVWUkxTRGRzVkZONGRGUk1NSEJtTkd0UVIxUkVNbGxpV0V0SVNteEpRMGxSUTAxQ1oxWmFSMGRaUjNwUGEwSUtTazFWTDJKRU5XeE1NWEE0UzNsV1lrUjBabE5CUldsME5ETjBjRnBxUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRa3g1YTBkdlRIcDNkd3BWWlhGNVNtWmFkMUlyT1RSNmJXc3hSelpSUjBzd1ZXdHBTVXRzVUVNMGVXeHROVWx1ZVhoQlQxcHdhV3BJWjI1YVVIbDJWVFpOUTAxUlJISTRNbTEwQ21wS2VtRXdSWGQyTkRGdWJreHBVREJFVnk5cVlXMU1PWEYzYUM5M2FrNTRWbXhyY2xWR2FrUXpjR2N5Tms1eWJUaENWVmhRWnpacVRFMUpQUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=","integratedTime":1792311581,"logIndex":3308757191,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}}}
|