@cartanova/qgrid-cli 2.2.1 → 2.3.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.
- package/bundle/dist/application/qgrid/conv-routing.js +2 -6
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +74 -43
- package/bundle/dist/application/qgrid/token-subscriber.js +14 -1
- package/bundle/dist/application/qgrid/tool-emulation.js +25 -20
- package/bundle/dist/application/request-log/request-log.model.js +54 -8
- package/bundle/dist/sonamu.config.js +11 -2
- package/bundle/dist/testing/global.js +5 -2
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +30 -0
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +215 -0
- package/bundle/dist/utils/providers/anthropic/claude-session.js +220 -0
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +177 -0
- package/bundle/dist/utils/providers/common/model-cost.js +35 -18
- package/bundle/dist/utils/providers/openai/openai-refresh.js +21 -9
- package/bundle/src/application/qgrid/conv-routing.test.ts +85 -0
- package/bundle/src/application/qgrid/conv-routing.ts +3 -2
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +110 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +112 -64
- package/bundle/src/application/qgrid/token-subscriber.ts +23 -1
- package/bundle/src/application/qgrid/tool-emulation.test.ts +46 -0
- package/bundle/src/application/qgrid/tool-emulation.ts +15 -3
- package/bundle/src/application/request-log/request-log.model.ts +98 -13
- package/bundle/src/sonamu.config.ts +13 -2
- package/bundle/src/testing/global.ts +16 -2
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +38 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +564 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +365 -0
- package/bundle/src/utils/providers/anthropic/claude-session.test.ts +263 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +327 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +373 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +344 -0
- package/bundle/src/utils/providers/common/model-cost.test.ts +39 -0
- package/bundle/src/utils/providers/common/model-cost.ts +107 -19
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +13 -2
- package/bundle/src/utils/providers/openai/openai-refresh.ts +34 -9
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import "../../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
//#region src/utils/providers/anthropic/stream-json-adapter.ts
|
|
3
|
+
function userInputToText(input) {
|
|
4
|
+
return input.filter((i) => i.type === "text").map((i) => i.text).join("\n");
|
|
5
|
+
}
|
|
6
|
+
function textBlock(text) {
|
|
7
|
+
return [{
|
|
8
|
+
type: "text",
|
|
9
|
+
text
|
|
10
|
+
}];
|
|
11
|
+
}
|
|
12
|
+
function asObject(v) {
|
|
13
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : null;
|
|
14
|
+
}
|
|
15
|
+
function responseItemText(item) {
|
|
16
|
+
const content = item.content;
|
|
17
|
+
if (!Array.isArray(content)) return "";
|
|
18
|
+
return content.map((c) => {
|
|
19
|
+
const obj = asObject(c);
|
|
20
|
+
return obj && typeof obj.text === "string" ? obj.text : "";
|
|
21
|
+
}).filter(Boolean).join("\n");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* cold history(codex ResponseItem[])를 **단일 평탄 텍스트**로 변환한다.
|
|
25
|
+
* user/assistant/tool 모두 라벨 붙은 한 덩어리로 — 실행되지 않는 assistant context 로 들어간다.
|
|
26
|
+
* (cold 의 user/tool-output 을 type:"user" 로 내보내면 새 prompt 로 재실행되므로 금지.)
|
|
27
|
+
*/
|
|
28
|
+
function flattenColdHistory(coldHistory) {
|
|
29
|
+
const parts = [];
|
|
30
|
+
for (const raw of coldHistory) {
|
|
31
|
+
const item = asObject(raw);
|
|
32
|
+
if (!item) continue;
|
|
33
|
+
if (item.type === "message" && item.role === "assistant") parts.push(`Assistant: ${responseItemText(item)}`);
|
|
34
|
+
else if (item.type === "message" && item.role === "user") parts.push(`User: ${responseItemText(item)}`);
|
|
35
|
+
else if (item.type === "function_call") {
|
|
36
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
37
|
+
const args = typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {});
|
|
38
|
+
parts.push(`Tool call: ${name}(${args})`);
|
|
39
|
+
} else if (item.type === "function_call_output") {
|
|
40
|
+
const output = typeof item.output === "string" ? item.output : JSON.stringify(item.output ?? "");
|
|
41
|
+
parts.push(`Tool result: ${output}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return parts.join("\n");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 서버 GenerateRequest payload 를 Claude stream-json JSONL 라인 배열로 변환한다.
|
|
48
|
+
*
|
|
49
|
+
* @param opts.coldHistory cold 경로의 codex ResponseItem 배열(JsonValue[]). resume 경로면 미사용.
|
|
50
|
+
* @param opts.input 실행할 input — cold 면 coldInput, resume 면 reuseInput.
|
|
51
|
+
* @param opts.isResume resume 경로 여부. true 면 history 재주입 없이 input(delta)만.
|
|
52
|
+
*
|
|
53
|
+
* 출력 규칙:
|
|
54
|
+
* - 실행 가능한 `type:"user"` 줄은 **항상 정확히 1개** — 마지막 input.
|
|
55
|
+
* - resume: user(delta) 1줄만. thread 가 이전 turn 을 누적하므로 history 미포함.
|
|
56
|
+
* - cold: coldHistory 전체를 **단일 assistant context 텍스트**로 평탄화(실행 안 됨) + user(input) 1줄.
|
|
57
|
+
* user/assistant/tool 모두 평탄화되므로 과거 user/tool-output 이 재실행되지 않는다.
|
|
58
|
+
* full-fidelity role replay 가 필요하면 session resume 또는 JSONL backstop(범위 밖).
|
|
59
|
+
* - tool(function_call/output): native 블록 없이 평탄 텍스트로.
|
|
60
|
+
*/
|
|
61
|
+
function buildStreamJsonInput(opts) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
if (!opts.isResume && opts.coldHistory && opts.coldHistory.length > 0) {
|
|
64
|
+
const flattened = flattenColdHistory(opts.coldHistory);
|
|
65
|
+
if (flattened) lines.push({
|
|
66
|
+
type: "assistant",
|
|
67
|
+
message: {
|
|
68
|
+
role: "assistant",
|
|
69
|
+
content: textBlock(`Prior conversation context:\n${flattened}`)
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
lines.push({
|
|
74
|
+
type: "user",
|
|
75
|
+
message: {
|
|
76
|
+
role: "user",
|
|
77
|
+
content: textBlock(userInputToText(opts.input))
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return lines;
|
|
81
|
+
}
|
|
82
|
+
function serializeStreamJsonInput(lines) {
|
|
83
|
+
return lines.map((l) => JSON.stringify(l)).join("\n") + "\n";
|
|
84
|
+
}
|
|
85
|
+
function toUsageBreakdown(u) {
|
|
86
|
+
const input = u.input_tokens ?? 0;
|
|
87
|
+
const cacheCreate = u.cache_creation_input_tokens ?? 0;
|
|
88
|
+
const cacheRead = u.cache_read_input_tokens ?? 0;
|
|
89
|
+
const output = u.output_tokens ?? 0;
|
|
90
|
+
const totalInput = input + cacheCreate + cacheRead;
|
|
91
|
+
return {
|
|
92
|
+
totalTokens: totalInput + output,
|
|
93
|
+
inputTokens: totalInput,
|
|
94
|
+
cachedInputTokens: cacheRead,
|
|
95
|
+
cacheCreationInputTokens: cacheCreate,
|
|
96
|
+
outputTokens: output,
|
|
97
|
+
reasoningOutputTokens: 0
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function stripCodeFence(s) {
|
|
101
|
+
return s.trim().replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "");
|
|
102
|
+
}
|
|
103
|
+
function structuredOutputToolUseText(j) {
|
|
104
|
+
const content = asObject(j.message)?.content;
|
|
105
|
+
if (!Array.isArray(content)) return void 0;
|
|
106
|
+
for (const raw of content) {
|
|
107
|
+
const block = asObject(raw);
|
|
108
|
+
if (!block) continue;
|
|
109
|
+
if (block.type === "tool_use" && block.name === "StructuredOutput" && block.input !== void 0) return JSON.stringify(block.input);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* stream-json 출력 라인 하나를 처리한다. 순수 함수 — side effect 는 onDelta 콜백뿐.
|
|
114
|
+
*
|
|
115
|
+
* @param opts.structuredOutput structured output(jsonSchema) 모드 여부.
|
|
116
|
+
* structured 모드에서 Claude 는 자연어 text_delta 와 input_json_delta.partial_json 을
|
|
117
|
+
* **함께** 흘릴 수 있다(PoC 확인). 이때 text_delta 를 그대로 onDelta 로 보내면 client 의
|
|
118
|
+
* streamObject 파서가 prose 를 JSON 앞에서 만나 깨진다. 그래서:
|
|
119
|
+
* - structured 모드: text_delta 무시, partial_json 만 onDelta.
|
|
120
|
+
* - text 모드: text_delta 만 onDelta (partial_json 은 안 옴).
|
|
121
|
+
*
|
|
122
|
+
* @returns result 이벤트면 ClaudeStreamResult, 그 외(delta/system 등)면 null.
|
|
123
|
+
* 호출부는 라인 스트림을 돌며 이 함수를 호출하고, non-null 이 나오면 종료.
|
|
124
|
+
*/
|
|
125
|
+
function handleStreamJsonLine(line, onDelta, opts) {
|
|
126
|
+
const structuredOutput = opts?.structuredOutput ?? false;
|
|
127
|
+
const state = opts?.state;
|
|
128
|
+
const trimmed = line.trim();
|
|
129
|
+
if (!trimmed) return null;
|
|
130
|
+
let j;
|
|
131
|
+
try {
|
|
132
|
+
j = JSON.parse(trimmed);
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
if (j.type === "stream_event") {
|
|
137
|
+
const event = asObject(j.event);
|
|
138
|
+
if (event && event.type === "content_block_delta") {
|
|
139
|
+
const delta = asObject(event.delta);
|
|
140
|
+
if (delta) {
|
|
141
|
+
if (structuredOutput) {
|
|
142
|
+
if (delta.type === "input_json_delta" && typeof delta.partial_json === "string") onDelta(delta.partial_json);
|
|
143
|
+
} else if (delta.type === "text_delta" && typeof delta.text === "string") onDelta(delta.text);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
if (j.type === "assistant" && structuredOutput && state && state.structuredOutputText === void 0) {
|
|
149
|
+
const text = structuredOutputToolUseText(j);
|
|
150
|
+
if (text !== void 0) state.structuredOutputText = text;
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
if (j.type === "result") {
|
|
154
|
+
let text;
|
|
155
|
+
const preservedStructuredOutput = structuredOutput ? state?.structuredOutputText : void 0;
|
|
156
|
+
if (preservedStructuredOutput !== void 0) text = preservedStructuredOutput;
|
|
157
|
+
else if (j.structured_output !== void 0) text = JSON.stringify(j.structured_output);
|
|
158
|
+
else text = stripCodeFence(typeof j.result === "string" ? j.result : "");
|
|
159
|
+
const usage = toUsageBreakdown(asObject(j.usage) ?? {});
|
|
160
|
+
const quotaExhausted = text.startsWith("You've hit");
|
|
161
|
+
const subtype = typeof j.subtype === "string" ? j.subtype : void 0;
|
|
162
|
+
const isError = !(preservedStructuredOutput !== void 0 && (subtype === "error_max_turns" || j.terminal_reason === "max_turns")) && (j.is_error === true || j.terminal_reason === "model_error" || subtype !== void 0 && subtype !== "success");
|
|
163
|
+
return {
|
|
164
|
+
text,
|
|
165
|
+
usage,
|
|
166
|
+
durationMs: typeof j.duration_ms === "number" ? j.duration_ms : 0,
|
|
167
|
+
costUsd: typeof j.total_cost_usd === "number" ? j.total_cost_usd : 0,
|
|
168
|
+
quotaExhausted,
|
|
169
|
+
isError
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
export { buildStreamJsonInput, handleStreamJsonLine, serializeStreamJsonInput };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyZWFtLWpzb24tYWRhcHRlci5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2FudGhyb3BpYy9zdHJlYW0tanNvbi1hZGFwdGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogc3RyZWFtLWpzb24g7Ja064yR7YSwIOKAlCBBbnRocm9waWMoQ2xhdWRlKSBwcm92aWRlciDsnZgg7J6F66ClL+y2nOugpSDrs4DtmZguXG4gKlxuICog7J20IOuqqOuTiOydgCDrtoDtmZzsnZgg7Jyg7J287ZWcIOuzuOyniOyggSDsi6Dqt5wg7L2U65Oc64ukLiDrkZAg67Cp7Zal7J2EIOu2hOumrOuQnCDsiJzsiJgg7ZWo7IiY66GcIOuRlOuLpDpcbiAqICAtIOyeheugpTog7ISc67KEIEdlbmVyYXRlUmVxdWVzdCBwYXlsb2FkKGNvbGRJbnB1dC9jb2xkSGlzdG9yeS9yZXVzZUlucHV0KVxuICogICAgICAgICAg4oaSIGBjbGF1ZGUgLXAgLS1pbnB1dC1mb3JtYXQgc3RyZWFtLWpzb25gIOydmCBKU09OTCDrnbzsnbguXG4gKiAgLSDstpzroKU6IGBjbGF1ZGUgLXAgLS1vdXRwdXQtZm9ybWF0IHN0cmVhbS1qc29uIC0tdmVyYm9zZWAg7J2YIEpTT05MIOudvOyduFxuICogICAgICAgICAg4oaSIHFncmlkIOyEnOuyhCBkZWx0YShvbkRlbHRhKSArIOy1nOyihSByZXN1bHQuIChVMywg6rCZ7J2AIO2MjOydvCDtlZjri6gpXG4gKlxuICog7KSR7JqU7ZWcIOqzhOyVvTpcbiAqICAtIOyeheugpeydgCBBSSBTREsgTGFuZ3VhZ2VNb2RlbFYzTWVzc2FnZVtdIOqwgCDslYTri4jrnbwgKirshJzrsoTsuKEgR2VuZXJhdGVSZXF1ZXN0Kiog64ukLlxuICogICAgYWktc2RrIOqwgCDsnbTrr7ggUXVlcnlJbnB1dC5oaXN0b3J5KEpzb25WYWx1ZVtdKSDroZwg67OA7ZmY7ZaI6rOgLCBkZWNpZGVDb252Um91dGluZyDsnbRcbiAqICAgIGNvbGRJbnB1dC9jb2xkSGlzdG9yeS9yZXVzZUlucHV0IOycvOuhnCDrp4zrk6Ag65KkIGRpc3BhdGNoZXIg7JeQIOuPhOuLrO2VnOuLpC5cbiAqICAtIGNvbnRlbnQg64qUIHVzZXIvYXNzaXN0YW50IOuqqOuRkCBibG9jayDrsLDsl7QgYFt7dHlwZTpcInRleHRcIix0ZXh0fV1gIOuhnCDsoJXqt5ztmZTtlZzri6QuXG4gKiAgICDrrLjsnpDsl7QgY29udGVudCDripQg7J2867aAIHVzZXIg64uo67Cc66eMIO2GteqzvO2VmOqzoCBoaXN0b3J5IHJlcGxheSDsl5DshJwg6rmo7KeE64ukXG4gKiAgICAoYFcgaXMgbm90IGFuIE9iamVjdCAoZXZhbHVhdGluZyAnXCJ0b29sX3VzZV9pZFwiIGluIFcnKWApLlxuICogIC0gc3RyZWFtLWpzb24g7J2YIHVzZXIvYXNzaXN0YW50IOuKlCDruYTrjIDsua3snbTri6Q6IGFzc2lzdGFudCDripQgaGlzdG9yeSBjb250ZXh0IOuhnCBwdXNoIOuQmOqzoFxuICogICAgKip1c2VyIOuKlCDsg4ggcHJvbXB0IOuhnCBlbnF1ZXVlKD3si6Ttlokp65Cc64ukLioqIOuUsOudvOyEnCBjb2xkIOqyveuhnOyXkOyEnCDqs7zqsbAg64yA7ZmUKHVzZXIvYXNzaXN0YW50L1xuICogICAgdG9vbCnrpbwg6re464yA66GcIOykhOuhnCDripjslrTrhpPsnLzrqbQg6rO86rGwIHVzZXIvdG9vbC1vdXRwdXQg7J20IOyLpO2WiSBwcm9tcHQg66GcIOyerOyLpO2WieuQnOuLpC4g7J2066W8IO2UvO2VmOugpFxuICogICAgY29sZCBoaXN0b3J5IOuKlCAqKuuLqOydvCBhc3Npc3RhbnQgY29udGV4dCDthY3siqTtirjroZwg7Y+J7YOE7ZmUKirtlZjqs6AsIOyLpO2WiSDqsIDriqXtlZwgYHR5cGU6XCJ1c2VyXCJgIOykhOydgFxuICogICAgKirrp4jsp4Drp4kgaW5wdXQg7ZWY64KY67+QKirsnbQg65CY64+E66GdIO2VnOuLpC4gZnVsbC1maWRlbGl0eSByb2xlIHJlcGxheSDqsIAg7ZWE7JqU7ZWY66m0IHNlc3Npb24gcmVzdW1lXG4gKiAgICAocmV1c2VJbnB1dCkg65iQ64qUIEpTT05MIGJhY2tzdG9wIOycvOuhnCDqsITri6QuXG4gKiAgLSB0b29sIOqysOqzvOuKlCBuYXRpdmUgQW50aHJvcGljIHRvb2xfcmVzdWx0IOu4lOuhneydhCDsg4jroZwg66eM65Ok7KeAIOyViuqzoCwg6riw7KG0IE9wZW5BSSDsmYBcbiAqICAgIOuPmeydvO2VmOqyjCDtj4ntg4TtmZTrkJwgdGV4dCDroZwg7LKY66as7ZWc64ukKGVtdWxhdGlvbiDqs7XthrUg6rOE7JW9KS5cbiAqL1xuXG5pbXBvcnQgeyB0eXBlIEpzb25WYWx1ZSB9IGZyb20gXCIuLi8uLi8uLi9jb2RleC1wcm90b2NvbC9zZXJkZV9qc29uL0pzb25WYWx1ZVwiO1xuaW1wb3J0IHsgdHlwZSBVc2VySW5wdXQgfSBmcm9tIFwiLi4vLi4vLi4vY29kZXgtcHJvdG9jb2wvdjIvVXNlcklucHV0XCI7XG5pbXBvcnQgeyB0eXBlIFByb3ZpZGVyVG9rZW5Vc2FnZUJyZWFrZG93biB9IGZyb20gXCIuLi9jb21tb24vcHJvdmlkZXItZGlzcGF0Y2hlclwiO1xuXG4vLyDilIDilIAg7J6F66ClIOyWtOuMke2EsCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLy8gQ2xhdWRlIHN0cmVhbS1qc29uIOyeheugpSDtlZwg7KSEKEpTT05MKS4gY29udGVudCDripQg7ZWt7IOBIGJsb2NrIOuwsOyXtC5cbi8vXG4vLyBTREsgZW52ZWxvcGUg7ZWE65OcKHV1aWQgLyBzZXNzaW9uX2lkIC8gcGFyZW50X3Rvb2xfdXNlX2lkKeuKlCAqKuyXrOq4sOyEnCDrp4zrk6Tsp4Ag7JWK64qU64ukKiouXG4vLyDqt7gg6rCS65Ok7J2AIOyEuOyFmOydhCDrsJzquIkv7IaM7Jyg7ZWY64qUIGNsYXVkZS1zZXNzaW9uIOydmCDssYXsnoTsnbTri6QuIOydtCDrqqjrk4jsnYAgcm9sZS9jb250ZW50IOuzgO2ZmOunjCDtlZjripRcbi8vIOyInOyImCDtlajsiJjroZwg65GQ6rOgLCBjbGF1ZGUtc2Vzc2lvbiDsnbQg7KeB66Cs7ZmUIOyngeyghOyXkCBlbnZlbG9wZSDrpbwgZGVjb3JhdGUg7ZWc64ukLiDssYXsnoQg67aE66asLlxuZXhwb3J0IGludGVyZmFjZSBDbGF1ZGVTdHJlYW1Kc29uTGluZSB7XG4gIHR5cGU6IFwidXNlclwiIHwgXCJhc3Npc3RhbnRcIjtcbiAgbWVzc2FnZToge1xuICAgIHJvbGU6IFwidXNlclwiIHwgXCJhc3Npc3RhbnRcIjtcbiAgICBjb250ZW50OiBBcnJheTx7IHR5cGU6IFwidGV4dFwiOyB0ZXh0OiBzdHJpbmcgfT47XG4gIH07XG59XG5cbi8vIFVzZXJJbnB1dFtdIOyXkOyEnCB0ZXh0IOunjCDrvZHslYQg7ZWY64KY7J2YIOusuOyekOyXtOuhnC4gKGltYWdlL3NraWxsL21lbnRpb24g65Ox7J2AIO2YhOyerCDrspTsnIQg67CWIOKAlCB0ZXh0IOychOyjvClcbmZ1bmN0aW9uIHVzZXJJbnB1dFRvVGV4dChpbnB1dDogQXJyYXk8VXNlcklucHV0Pik6IHN0cmluZyB7XG4gIHJldHVybiBpbnB1dFxuICAgIC5maWx0ZXIoKGkpOiBpIGlzIEV4dHJhY3Q8VXNlcklucHV0LCB7IHR5cGU6IFwidGV4dFwiIH0+ID0+IGkudHlwZSA9PT0gXCJ0ZXh0XCIpXG4gICAgLm1hcCgoaSkgPT4gaS50ZXh0KVxuICAgIC5qb2luKFwiXFxuXCIpO1xufVxuXG4vLyBjb250ZW50IOulvCDtla3sg4EgYmxvY2sg67Cw7Je066GcIOygleq3nO2ZlCjrrLjsnpDsl7QgY29udGVudCDripQgaGlzdG9yeSByZXBsYXkg7JeQ7IScIOq5qOynkCkuXG5mdW5jdGlvbiB0ZXh0QmxvY2sodGV4dDogc3RyaW5nKTogQXJyYXk8eyB0eXBlOiBcInRleHRcIjsgdGV4dDogc3RyaW5nIH0+IHtcbiAgcmV0dXJuIFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0IH1dO1xufVxuXG4vLyBjb2RleCBSZXNwb25zZUl0ZW0oY29sZEhpc3Rvcnkg7J2YIO2VnCDtla3rqqkpIO2Yle2DnCDtjJDrs4Tsmqkg7LWc7IaMIHNoYXBlLlxuLy8gZXh0cmFjdFByb21wdEFuZEhpc3RvcnkoYWktc2RrL3V0aWxzLnRzKSDqsIAg66eM65Oc64qUIO2YleyLnTpcbi8vICAgeyB0eXBlOlwibWVzc2FnZVwiLCByb2xlOlwidXNlclwiLCBjb250ZW50Olt7dHlwZTpcImlucHV0X3RleHRcIiwgdGV4dH1dIH1cbi8vICAgeyB0eXBlOlwibWVzc2FnZVwiLCByb2xlOlwiYXNzaXN0YW50XCIsIGNvbnRlbnQ6W3t0eXBlOlwib3V0cHV0X3RleHRcIiwgdGV4dH1dIH1cbi8vICAgeyB0eXBlOlwiZnVuY3Rpb25fY2FsbFwiLCBuYW1lLCBhcmd1bWVudHMsIGNhbGxfaWQgfVxuLy8gICB7IHR5cGU6XCJmdW5jdGlvbl9jYWxsX291dHB1dFwiLCBjYWxsX2lkLCBvdXRwdXQgfVxudHlwZSBSZXNwb25zZUl0ZW0gPSB7IFtrZXk6IHN0cmluZ106IEpzb25WYWx1ZSB8IHVuZGVmaW5lZCB9O1xuXG5mdW5jdGlvbiBhc09iamVjdCh2OiBKc29uVmFsdWUgfCB1bmRlZmluZWQpOiBSZXNwb25zZUl0ZW0gfCBudWxsIHtcbiAgcmV0dXJuIHR5cGVvZiB2ID09PSBcIm9iamVjdFwiICYmIHYgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkodikgPyAodiBhcyBSZXNwb25zZUl0ZW0pIDogbnVsbDtcbn1cblxuLy8gY29kZXggbWVzc2FnZSBjb250ZW50KFt7dHlwZTppbnB1dF90ZXh0fG91dHB1dF90ZXh0LCB0ZXh0fV0pIOyXkOyEnCB0ZXh0IOy2lOy2nC5cbi8vIOyXrOufrCBjb250ZW50IOu4lOuhneydgCDspITrsJTqv4jsnLzroZwg6rWs67aEKHRva2VuLWFkamFjZW50IOu2meydjCDrsKnsp4ApLlxuZnVuY3Rpb24gcmVzcG9uc2VJdGVtVGV4dChpdGVtOiBSZXNwb25zZUl0ZW0pOiBzdHJpbmcge1xuICBjb25zdCBjb250ZW50ID0gaXRlbS5jb250ZW50O1xuICBpZiAoIUFycmF5LmlzQXJyYXkoY29udGVudCkpIHJldHVybiBcIlwiO1xuICByZXR1cm4gY29udGVudFxuICAgIC5tYXAoKGMpID0+IHtcbiAgICAgIGNvbnN0IG9iaiA9IGFzT2JqZWN0KGMpO1xuICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2Ygb2JqLnRleHQgPT09IFwic3RyaW5nXCIgPyBvYmoudGV4dCA6IFwiXCI7XG4gICAgfSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgLmpvaW4oXCJcXG5cIik7XG59XG5cbi8qKlxuICogY29sZCBoaXN0b3J5KGNvZGV4IFJlc3BvbnNlSXRlbVtdKeulvCAqKuuLqOydvCDtj4ntg4Qg7YWN7Iqk7Yq4KirroZwg67OA7ZmY7ZWc64ukLlxuICogdXNlci9hc3Npc3RhbnQvdG9vbCDrqqjrkZAg652867KoIOu2meydgCDtlZwg642p7Ja066as66GcIOKAlCDsi6TtlonrkJjsp4Ag7JWK64qUIGFzc2lzdGFudCBjb250ZXh0IOuhnCDrk6TslrTqsITri6QuXG4gKiAoY29sZCDsnZggdXNlci90b29sLW91dHB1dCDsnYQgdHlwZTpcInVzZXJcIiDroZwg64K067O064K066m0IOyDiCBwcm9tcHQg66GcIOyerOyLpO2WieuQmOuvgOuhnCDquIjsp4AuKVxuICovXG5mdW5jdGlvbiBmbGF0dGVuQ29sZEhpc3RvcnkoY29sZEhpc3Rvcnk6IEFycmF5PEpzb25WYWx1ZT4pOiBzdHJpbmcge1xuICBjb25zdCBwYXJ0czogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICBmb3IgKGNvbnN0IHJhdyBvZiBjb2xkSGlzdG9yeSkge1xuICAgIGNvbnN0IGl0ZW0gPSBhc09iamVjdChyYXcpO1xuICAgIGlmICghaXRlbSkgY29udGludWU7XG5cbiAgICBpZiAoaXRlbS50eXBlID09PSBcIm1lc3NhZ2VcIiAmJiBpdGVtLnJvbGUgPT09IFwiYXNzaXN0YW50XCIpIHtcbiAgICAgIHBhcnRzLnB1c2goYEFzc2lzdGFudDogJHtyZXNwb25zZUl0ZW1UZXh0KGl0ZW0pfWApO1xuICAgIH0gZWxzZSBpZiAoaXRlbS50eXBlID09PSBcIm1lc3NhZ2VcIiAmJiBpdGVtLnJvbGUgPT09IFwidXNlclwiKSB7XG4gICAgICBwYXJ0cy5wdXNoKGBVc2VyOiAke3Jlc3BvbnNlSXRlbVRleHQoaXRlbSl9YCk7XG4gICAgfSBlbHNlIGlmIChpdGVtLnR5cGUgPT09IFwiZnVuY3Rpb25fY2FsbFwiKSB7XG4gICAgICBjb25zdCBuYW1lID0gdHlwZW9mIGl0ZW0ubmFtZSA9PT0gXCJzdHJpbmdcIiA/IGl0ZW0ubmFtZSA6IFwiXCI7XG4gICAgICBjb25zdCBhcmdzID1cbiAgICAgICAgdHlwZW9mIGl0ZW0uYXJndW1lbnRzID09PSBcInN0cmluZ1wiID8gaXRlbS5hcmd1bWVudHMgOiBKU09OLnN0cmluZ2lmeShpdGVtLmFyZ3VtZW50cyA/PyB7fSk7XG4gICAgICBwYXJ0cy5wdXNoKGBUb29sIGNhbGw6ICR7bmFtZX0oJHthcmdzfSlgKTtcbiAgICB9IGVsc2UgaWYgKGl0ZW0udHlwZSA9PT0gXCJmdW5jdGlvbl9jYWxsX291dHB1dFwiKSB7XG4gICAgICBjb25zdCBvdXRwdXQgPVxuICAgICAgICB0eXBlb2YgaXRlbS5vdXRwdXQgPT09IFwic3RyaW5nXCIgPyBpdGVtLm91dHB1dCA6IEpTT04uc3RyaW5naWZ5KGl0ZW0ub3V0cHV0ID8/IFwiXCIpO1xuICAgICAgcGFydHMucHVzaChgVG9vbCByZXN1bHQ6ICR7b3V0cHV0fWApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcGFydHMuam9pbihcIlxcblwiKTtcbn1cblxuLyoqXG4gKiDshJzrsoQgR2VuZXJhdGVSZXF1ZXN0IHBheWxvYWQg66W8IENsYXVkZSBzdHJlYW0tanNvbiBKU09OTCDrnbzsnbgg67Cw7Je066GcIOuzgO2ZmO2VnOuLpC5cbiAqXG4gKiBAcGFyYW0gb3B0cy5jb2xkSGlzdG9yeSAgY29sZCDqsr3roZzsnZggY29kZXggUmVzcG9uc2VJdGVtIOuwsOyXtChKc29uVmFsdWVbXSkuIHJlc3VtZSDqsr3roZzrqbQg66+47IKs7JqpLlxuICogQHBhcmFtIG9wdHMuaW5wdXQgICAgICAgIOyLpO2Wie2VoCBpbnB1dCDigJQgY29sZCDrqbQgY29sZElucHV0LCByZXN1bWUg66m0IHJldXNlSW5wdXQuXG4gKiBAcGFyYW0gb3B0cy5pc1Jlc3VtZSAgICAgcmVzdW1lIOqyveuhnCDsl6zrtoAuIHRydWUg66m0IGhpc3Rvcnkg7J6s7KO87J6FIOyXhuydtCBpbnB1dChkZWx0YSnrp4wuXG4gKlxuICog7Lac66ClIOq3nOy5mTpcbiAqICAtIOyLpO2WiSDqsIDriqXtlZwgYHR5cGU6XCJ1c2VyXCJgIOykhOydgCAqKu2VreyDgSDsoJXtmZXtnoggMeqwnCoqIOKAlCDrp4jsp4Drp4kgaW5wdXQuXG4gKiAgLSByZXN1bWU6IHVzZXIoZGVsdGEpIDHspITrp4wuIHRocmVhZCDqsIAg7J207KCEIHR1cm4g7J2EIOuIhOygge2VmOuvgOuhnCBoaXN0b3J5IOuvuO2PrO2VqC5cbiAqICAtIGNvbGQ6IGNvbGRIaXN0b3J5IOyghOyytOulvCAqKuuLqOydvCBhc3Npc3RhbnQgY29udGV4dCDthY3siqTtirgqKuuhnCDtj4ntg4TtmZQo7Iuk7ZaJIOyViCDrkKgpICsgdXNlcihpbnB1dCkgMeykhC5cbiAqICAgICAgICAgIHVzZXIvYXNzaXN0YW50L3Rvb2wg66qo65GQIO2Pie2DhO2ZlOuQmOuvgOuhnCDqs7zqsbAgdXNlci90b29sLW91dHB1dCDsnbQg7J6s7Iuk7ZaJ65CY7KeAIOyViuuKlOuLpC5cbiAqICAgICAgICAgIGZ1bGwtZmlkZWxpdHkgcm9sZSByZXBsYXkg6rCAIO2VhOyalO2VmOuptCBzZXNzaW9uIHJlc3VtZSDrmJDripQgSlNPTkwgYmFja3N0b3Ao67KU7JyEIOuwlikuXG4gKiAgLSB0b29sKGZ1bmN0aW9uX2NhbGwvb3V0cHV0KTogbmF0aXZlIOu4lOuhnSDsl4bsnbQg7Y+J7YOEIO2FjeyKpO2KuOuhnC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkU3RyZWFtSnNvbklucHV0KG9wdHM6IHtcbiAgY29sZEhpc3Rvcnk/OiBBcnJheTxKc29uVmFsdWU+O1xuICBpbnB1dDogQXJyYXk8VXNlcklucHV0PjtcbiAgaXNSZXN1bWU6IGJvb2xlYW47XG59KTogQXJyYXk8Q2xhdWRlU3RyZWFtSnNvbkxpbmU+IHtcbiAgY29uc3QgbGluZXM6IEFycmF5PENsYXVkZVN0cmVhbUpzb25MaW5lPiA9IFtdO1xuXG4gIC8vIGNvbGQg6rK966GcOiBoaXN0b3J5IOulvCDri6jsnbwgYXNzaXN0YW50IGNvbnRleHQg66GcIO2Pie2DhO2ZlCjsi6Ttlokg7JWIIOuQqCkuXG4gIGlmICghb3B0cy5pc1Jlc3VtZSAmJiBvcHRzLmNvbGRIaXN0b3J5ICYmIG9wdHMuY29sZEhpc3RvcnkubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGZsYXR0ZW5lZCA9IGZsYXR0ZW5Db2xkSGlzdG9yeShvcHRzLmNvbGRIaXN0b3J5KTtcbiAgICBpZiAoZmxhdHRlbmVkKSB7XG4gICAgICBsaW5lcy5wdXNoKHtcbiAgICAgICAgdHlwZTogXCJhc3Npc3RhbnRcIixcbiAgICAgICAgbWVzc2FnZToge1xuICAgICAgICAgIHJvbGU6IFwiYXNzaXN0YW50XCIsXG4gICAgICAgICAgY29udGVudDogdGV4dEJsb2NrKGBQcmlvciBjb252ZXJzYXRpb24gY29udGV4dDpcXG4ke2ZsYXR0ZW5lZH1gKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOyLpO2Wie2VoCBpbnB1dCDigJQgcmVzdW1lL2NvbGQg6rO17Ya1LCDtla3sg4Eg66eI7KeA66eJ7J2YIOuLqOydvCB1c2VyIOykhC5cbiAgbGluZXMucHVzaCh7XG4gICAgdHlwZTogXCJ1c2VyXCIsXG4gICAgbWVzc2FnZTogeyByb2xlOiBcInVzZXJcIiwgY29udGVudDogdGV4dEJsb2NrKHVzZXJJbnB1dFRvVGV4dChvcHRzLmlucHV0KSkgfSxcbiAgfSk7XG5cbiAgcmV0dXJuIGxpbmVzO1xufVxuXG4vLyBKU09OTCDrrLjsnpDsl7QoY2xhdWRlIHN0ZGluIOycvOuhnCDtnZjrprQg7ZiV7YOcKeuhnCDsp4HroKztmZQuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplU3RyZWFtSnNvbklucHV0KGxpbmVzOiBBcnJheTxDbGF1ZGVTdHJlYW1Kc29uTGluZT4pOiBzdHJpbmcge1xuICByZXR1cm4gbGluZXMubWFwKChsKSA9PiBKU09OLnN0cmluZ2lmeShsKSkuam9pbihcIlxcblwiKSArIFwiXFxuXCI7XG59XG5cbi8vIOKUgOKUgCDstpzroKUg7Ja064yR7YSwIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLy9cbi8vIGNsYXVkZSAtcCAtLW91dHB1dC1mb3JtYXQgc3RyZWFtLWpzb24gLS12ZXJib3NlIOydmCBzdGRvdXQoSlNPTkwp7J2EXG4vLyBxZ3JpZCDshJzrsoQgZGVsdGEob25EZWx0YSkgKyDstZzsooUgcmVzdWx0IOuhnCDrs4DtmZjtlZzri6QuXG4vL1xuLy8g6rOE7JW9OlxuLy8gIC0g7J20IOyWtOuMke2EsOuKlCBxZ3JpZCAqKuyEnOuyhCoqIOqzhOy4teydtOuLpC4gQUkgU0RLIHN0cmVhbSBwYXJ0KHRleHQtZGVsdGEg65OxKeuKlFxuLy8gICAgcGFja2FnZXMvYWktc2RrKGNsaWVudCBwcm92aWRlcinqsIAg66eM65Og64ukIOKAlCDsl6zquLDshJwg66eM65Ok7KeAIOyViuuKlOuLpC5cbi8vICAtIHRleHRfZGVsdGEg4oaSIG9uRGVsdGEodGV4dCkuIHN0cnVjdHVyZWQgb3V0cHV0IOydvCDrlYwgaW5wdXRfanNvbl9kZWx0YS5wYXJ0aWFsX2pzb25cbi8vICAgIOyhsOqwgeuPhCBvbkRlbHRhKHRleHQpIOuhnCDtnZjrprDri6QoY2xpZW50IHByb3ZpZGVyIOqwgCBwYXJ0aWFsT2JqZWN0U3RyZWFtIOycvOuhnCDriITsoIEpLlxuLy8gIC0g7LWc7KKFIHJlc3VsdCDihpIgc3RydWN0dXJlZF9vdXRwdXQo7Jqw7ISgKSDrmJDripQgcmVzdWx0KO2PtOuwsSwg7J6Q7Jew7Ja0IOqwgOuKpSkgKyB1c2FnZSArIOyiheujjC5cbi8vICAtIHVzYWdlIOuKlCBpbnB1dC9jYWNoZV9jcmVhdGlvbi9jYWNoZV9yZWFkL291dHB1dCA0IOy5tO2FjOqzoOumrOulvCDrsJvslYQgVG9rZW5Vc2FnZUJyZWFrZG93biDsnLzroZwuXG4vLyAgICBwYXlsb2FkIO2BrOq4sCDruYTqtZDripQgMyDsubTthYzqs6Drpqwg7ZWp7Jy866GcKOqzvOqxsCDtlZnsirUg4oCUIGlucHV0IOuLqOuPhSDruYTqtZAg66y07J2Y66+4KS5cblxuLy8gY2xhdWRlIHN0cmVhbS1qc29uIOy2nOugpeyXkOyEnCDsmrDrpqzqsIAg67O064qUIHVzYWdlIHNoYXBlKOu2gOu2hCkuIEFudGhyb3BpYyDrhKTsnbTti7DruIwg7ZWE65OcLlxuaW50ZXJmYWNlIENsYXVkZVVzYWdlIHtcbiAgaW5wdXRfdG9rZW5zPzogbnVtYmVyO1xuICBvdXRwdXRfdG9rZW5zPzogbnVtYmVyO1xuICBjYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnM/OiBudW1iZXI7XG4gIGNhY2hlX3JlYWRfaW5wdXRfdG9rZW5zPzogbnVtYmVyO1xufVxuXG4vLyDstZzsooUgcmVzdWx0IO2MjOyLsSDsgrDstpzrrLwuIGRpc3BhdGNoZXIoVTEp6rCAIEdlbmVyYXRlUmVzdWx0IOyhsOumveyXkCDsk7Tri6QuXG5leHBvcnQgaW50ZXJmYWNlIENsYXVkZVN0cmVhbVJlc3VsdCB7XG4gIHRleHQ6IHN0cmluZztcbiAgdXNhZ2U6IFByb3ZpZGVyVG9rZW5Vc2FnZUJyZWFrZG93bjtcbiAgZHVyYXRpb25NczogbnVtYmVyO1xuICBjb3N0VXNkOiBudW1iZXI7XG4gIC8vIHF1b3RhIOyGjOynhChcIllvdSd2ZSBoaXQgLi4uXCIpIOqwkOyngC4gZGlzcGF0Y2hlciDqsIAgUXVvdGFFcnJvciDroZwg67OA7ZmYLlxuICBxdW90YUV4aGF1c3RlZDogYm9vbGVhbjtcbiAgLy8gcmVzdWx0LmlzX2Vycm9yIC8gdGVybWluYWwgbW9kZWxfZXJyb3Ig65OxLiBkaXNwYXRjaGVyIOqwgCDsl5Drn6zroZwg67OA7ZmYLlxuICBpc0Vycm9yOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENsYXVkZVN0cmVhbUpzb25TdGF0ZSB7XG4gIHN0cnVjdHVyZWRPdXRwdXRUZXh0Pzogc3RyaW5nO1xufVxuXG4vLyBBbnRocm9waWMgdXNhZ2UgNCDsubTthYzqs6Drpqwg4oaSIFRva2VuVXNhZ2VCcmVha2Rvd24uXG4vLyBBbnRocm9waWMgbmF0aXZlIHVzYWdlIOuKlCBpbnB1dC9jYWNoZV9jcmVhdGlvbi9jYWNoZV9yZWFkIOulvCDshJzroZwg67Cw7YOA7KCB7J24IOy5tO2FjOqzoOumrOuhnCDspIDri6QuXG4vLyDrsJjrqbQgcWdyaWQg64K067aAIO2RnOykgChUb2tlblVzYWdlQnJlYWtkb3duKeqzvCBjb3N0IOqzhOyCsOydgCBpbnB1dFRva2VucyDrpbwgXCLsoITssrQg7J6F66ClXG4vLyAoPSBub24tY2FjaGUgaW5wdXQgKyBjYWNoZSBjcmVhdGlvbiArIGNhY2hlIHJlYWQpXCIg7Jy866GcIOy3qOq4ie2VmOqzoCBjYWNoZWRJbnB1dFRva2Vucy9jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnNcbi8vIOulvCDqt7jspJEg6rCBIOuqq+ycvOuhnCDri6Tsi5wg7ZGc7Iuc7ZWc64ukKE9wZW5BSS9Db2RleCB1c2FnZSDsmYAg6rCZ7J2AIOydmOuvuCkuIOuUsOudvOyEnCDsl6zquLDshJwg7ZWp7LOQIO2RnOykgO2ZlO2VnOuLpC5cbmZ1bmN0aW9uIHRvVXNhZ2VCcmVha2Rvd24odTogQ2xhdWRlVXNhZ2UpOiBQcm92aWRlclRva2VuVXNhZ2VCcmVha2Rvd24ge1xuICBjb25zdCBpbnB1dCA9IHUuaW5wdXRfdG9rZW5zID8/IDA7XG4gIGNvbnN0IGNhY2hlQ3JlYXRlID0gdS5jYWNoZV9jcmVhdGlvbl9pbnB1dF90b2tlbnMgPz8gMDtcbiAgY29uc3QgY2FjaGVSZWFkID0gdS5jYWNoZV9yZWFkX2lucHV0X3Rva2VucyA/PyAwO1xuICBjb25zdCBvdXRwdXQgPSB1Lm91dHB1dF90b2tlbnMgPz8gMDtcbiAgY29uc3QgdG90YWxJbnB1dCA9IGlucHV0ICsgY2FjaGVDcmVhdGUgKyBjYWNoZVJlYWQ7XG4gIHJldHVybiB7XG4gICAgdG90YWxUb2tlbnM6IHRvdGFsSW5wdXQgKyBvdXRwdXQsXG4gICAgaW5wdXRUb2tlbnM6IHRvdGFsSW5wdXQsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IGNhY2hlUmVhZCxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IGNhY2hlQ3JlYXRlLFxuICAgIG91dHB1dFRva2Vuczogb3V0cHV0LFxuICAgIHJlYXNvbmluZ091dHB1dFRva2VuczogMCxcbiAgfTtcbn1cblxuLy8gcmVzdWx0LnJlc3VsdCDsnZgg7L2U65Oc7Y6c7IqkKGBgYGpzb24gLi4uIGBgYCkg7KCc6rGwLiBzdHJ1Y3R1cmVkX291dHB1dCDsnbQg7JeG7J2EIOuVjOunjCDsk7Tri6QuXG4vLyDslZ7rkqQg6rO167CxL+qwnO2WieydhCDrqLzsoIAgdHJpbSDtlbQgYFxcbmBgYGpzb25cXG4uLi5cXG5gYGBcXG5gIOqwmeydgCDtmJXtg5zrj4Qg6rmo64GX7J20IOygnOqxsC5cbmZ1bmN0aW9uIHN0cmlwQ29kZUZlbmNlKHM6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBzXG4gICAgLnRyaW0oKVxuICAgIC5yZXBsYWNlKC9eYGBgKD86anNvbik/XFxzKlxcbj8vaSwgXCJcIilcbiAgICAucmVwbGFjZSgvXFxuP2BgYFxccyokL2ksIFwiXCIpO1xufVxuXG5mdW5jdGlvbiBzdHJ1Y3R1cmVkT3V0cHV0VG9vbFVzZVRleHQoajogUmVzcG9uc2VJdGVtKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgbWVzc2FnZSA9IGFzT2JqZWN0KGoubWVzc2FnZSk7XG4gIGNvbnN0IGNvbnRlbnQgPSBtZXNzYWdlPy5jb250ZW50O1xuICBpZiAoIUFycmF5LmlzQXJyYXkoY29udGVudCkpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgZm9yIChjb25zdCByYXcgb2YgY29udGVudCkge1xuICAgIGNvbnN0IGJsb2NrID0gYXNPYmplY3QocmF3KTtcbiAgICBpZiAoIWJsb2NrKSBjb250aW51ZTtcbiAgICBpZiAoYmxvY2sudHlwZSA9PT0gXCJ0b29sX3VzZVwiICYmIGJsb2NrLm5hbWUgPT09IFwiU3RydWN0dXJlZE91dHB1dFwiICYmIGJsb2NrLmlucHV0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShibG9jay5pbnB1dCk7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogc3RyZWFtLWpzb24g7Lac66ClIOudvOyduCDtlZjrgpjrpbwg7LKY66as7ZWc64ukLiDsiJzsiJgg7ZWo7IiYIOKAlCBzaWRlIGVmZmVjdCDripQgb25EZWx0YSDsvZzrsLHrv5AuXG4gKlxuICogQHBhcmFtIG9wdHMuc3RydWN0dXJlZE91dHB1dCAgc3RydWN0dXJlZCBvdXRwdXQoanNvblNjaGVtYSkg66qo65OcIOyXrOu2gC5cbiAqICAgc3RydWN0dXJlZCDrqqjrk5zsl5DshJwgQ2xhdWRlIOuKlCDsnpDsl7DslrQgdGV4dF9kZWx0YSDsmYAgaW5wdXRfanNvbl9kZWx0YS5wYXJ0aWFsX2pzb24g7J2EXG4gKiAgICoq7ZWo6ruYKiog7Z2Y66a0IOyImCDsnojri6QoUG9DIO2ZleyduCkuIOydtOuVjCB0ZXh0X2RlbHRhIOulvCDqt7jrjIDroZwgb25EZWx0YSDroZwg67O064K066m0IGNsaWVudCDsnZhcbiAqICAgc3RyZWFtT2JqZWN0IO2MjOyEnOqwgCBwcm9zZSDrpbwgSlNPTiDslZ7sl5DshJwg66eM64KYIOq5qOynhOuLpC4g6re4656Y7IScOlxuICogICAgIC0gc3RydWN0dXJlZCDrqqjrk5w6IHRleHRfZGVsdGEg66y07IucLCBwYXJ0aWFsX2pzb24g66eMIG9uRGVsdGEuXG4gKiAgICAgLSB0ZXh0IOuqqOuTnDogdGV4dF9kZWx0YSDrp4wgb25EZWx0YSAocGFydGlhbF9qc29uIOydgCDslYgg7Ji0KS5cbiAqXG4gKiBAcmV0dXJucyByZXN1bHQg7J2067Kk7Yq466m0IENsYXVkZVN0cmVhbVJlc3VsdCwg6re4IOyZuChkZWx0YS9zeXN0ZW0g65OxKeuptCBudWxsLlxuICogICAgICAgICAg7Zi47Lac67aA64qUIOudvOyduCDsiqTtirjrprzsnYQg64+M66mwIOydtCDtlajsiJjrpbwg7Zi47Lac7ZWY6rOgLCBub24tbnVsbCDsnbQg64KY7Jik66m0IOyiheujjC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZVN0cmVhbUpzb25MaW5lKFxuICBsaW5lOiBzdHJpbmcsXG4gIG9uRGVsdGE6ICh0ZXh0OiBzdHJpbmcpID0+IHZvaWQsXG4gIG9wdHM/OiB7IHN0cnVjdHVyZWRPdXRwdXQ/OiBib29sZWFuOyBzdGF0ZT86IENsYXVkZVN0cmVhbUpzb25TdGF0ZSB9LFxuKTogQ2xhdWRlU3RyZWFtUmVzdWx0IHwgbnVsbCB7XG4gIGNvbnN0IHN0cnVjdHVyZWRPdXRwdXQgPSBvcHRzPy5zdHJ1Y3R1cmVkT3V0cHV0ID8/IGZhbHNlO1xuICBjb25zdCBzdGF0ZSA9IG9wdHM/LnN0YXRlO1xuICBjb25zdCB0cmltbWVkID0gbGluZS50cmltKCk7XG4gIGlmICghdHJpbW1lZCkgcmV0dXJuIG51bGw7XG5cbiAgbGV0IGo6IHsgW2tleTogc3RyaW5nXTogSnNvblZhbHVlIHwgdW5kZWZpbmVkIH07XG4gIHRyeSB7XG4gICAgaiA9IEpTT04ucGFyc2UodHJpbW1lZCkgYXMgeyBba2V5OiBzdHJpbmddOiBKc29uVmFsdWUgfCB1bmRlZmluZWQgfTtcbiAgfSBjYXRjaCB7XG4gICAgLy8g6rmo7KeEIEpTT04g65287J247J2AIGdyYWNlZnVsIHNraXAuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyDsoJDsp4QgZGVsdGE6IHN0cmVhbV9ldmVudCA+IGNvbnRlbnRfYmxvY2tfZGVsdGEgPiB7dGV4dF9kZWx0YSB8IGlucHV0X2pzb25fZGVsdGF9LlxuICBpZiAoai50eXBlID09PSBcInN0cmVhbV9ldmVudFwiKSB7XG4gICAgY29uc3QgZXZlbnQgPSBhc09iamVjdChqLmV2ZW50KTtcbiAgICBpZiAoZXZlbnQgJiYgZXZlbnQudHlwZSA9PT0gXCJjb250ZW50X2Jsb2NrX2RlbHRhXCIpIHtcbiAgICAgIGNvbnN0IGRlbHRhID0gYXNPYmplY3QoZXZlbnQuZGVsdGEpO1xuICAgICAgaWYgKGRlbHRhKSB7XG4gICAgICAgIGlmIChzdHJ1Y3R1cmVkT3V0cHV0KSB7XG4gICAgICAgICAgLy8gc3RydWN0dXJlZDogSlNPTiDsobDqsIHrp4wuIOyekOyXsOyWtCB0ZXh0X2RlbHRhIOuKlCDrsoTrprDri6Qoc3RyZWFtT2JqZWN0IO2MjOyEnCDrs7TtmLgpLlxuICAgICAgICAgIGlmIChkZWx0YS50eXBlID09PSBcImlucHV0X2pzb25fZGVsdGFcIiAmJiB0eXBlb2YgZGVsdGEucGFydGlhbF9qc29uID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBvbkRlbHRhKGRlbHRhLnBhcnRpYWxfanNvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHRleHQ6IOyekOyXsOyWtCBkZWx0YSDrp4wuXG4gICAgICAgICAgaWYgKGRlbHRhLnR5cGUgPT09IFwidGV4dF9kZWx0YVwiICYmIHR5cGVvZiBkZWx0YS50ZXh0ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBvbkRlbHRhKGRlbHRhLnRleHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChqLnR5cGUgPT09IFwiYXNzaXN0YW50XCIgJiYgc3RydWN0dXJlZE91dHB1dCAmJiBzdGF0ZSAmJiBzdGF0ZS5zdHJ1Y3R1cmVkT3V0cHV0VGV4dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgdGV4dCA9IHN0cnVjdHVyZWRPdXRwdXRUb29sVXNlVGV4dChqKTtcbiAgICBpZiAodGV4dCAhPT0gdW5kZWZpbmVkKSBzdGF0ZS5zdHJ1Y3R1cmVkT3V0cHV0VGV4dCA9IHRleHQ7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyDstZzsooUgcmVzdWx0LlxuICBpZiAoai50eXBlID09PSBcInJlc3VsdFwiKSB7XG4gICAgbGV0IHRleHQ6IHN0cmluZztcbiAgICBjb25zdCBwcmVzZXJ2ZWRTdHJ1Y3R1cmVkT3V0cHV0ID0gc3RydWN0dXJlZE91dHB1dCA/IHN0YXRlPy5zdHJ1Y3R1cmVkT3V0cHV0VGV4dCA6IHVuZGVmaW5lZDtcbiAgICBpZiAocHJlc2VydmVkU3RydWN0dXJlZE91dHB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0ZXh0ID0gcHJlc2VydmVkU3RydWN0dXJlZE91dHB1dDtcbiAgICB9IGVsc2UgaWYgKGouc3RydWN0dXJlZF9vdXRwdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGV4dCA9IEpTT04uc3RyaW5naWZ5KGouc3RydWN0dXJlZF9vdXRwdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0ZXh0ID0gc3RyaXBDb2RlRmVuY2UodHlwZW9mIGoucmVzdWx0ID09PSBcInN0cmluZ1wiID8gai5yZXN1bHQgOiBcIlwiKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2FnZSA9IHRvVXNhZ2VCcmVha2Rvd24oKGFzT2JqZWN0KGoudXNhZ2UpID8/IHt9KSBhcyBDbGF1ZGVVc2FnZSk7XG4gICAgY29uc3QgcXVvdGFFeGhhdXN0ZWQgPSB0ZXh0LnN0YXJ0c1dpdGgoXCJZb3UndmUgaGl0XCIpO1xuICAgIC8vIOyXkOufrCDtjJDsoJU6IGlzX2Vycm9yIHRydWUsIHRlcm1pbmFsIG1vZGVsX2Vycm9yLFxuICAgIC8vIOuYkOuKlCBzdWJ0eXBlIOydtCDsnojqs6AgXCJzdWNjZXNzXCIg6rCAIOyVhOuLiOuptChlcnJvcl9kdXJpbmdfZXhlY3V0aW9uIC8gZXJyb3JfbWF4X3R1cm5zIC9cbiAgICAvLyBlcnJvcl9tYXhfYnVkZ2V0X3VzZCAvIGVycm9yX21heF9zdHJ1Y3R1cmVkX291dHB1dF9yZXRyaWVzIOuTsSkg7JeQ65+s66GcIOuzuOuLpC5cbiAgICBjb25zdCBzdWJ0eXBlID0gdHlwZW9mIGouc3VidHlwZSA9PT0gXCJzdHJpbmdcIiA/IGouc3VidHlwZSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBzdHJ1Y3R1cmVkTWF4VHVybnNDb21wbGV0ZWQgPVxuICAgICAgcHJlc2VydmVkU3RydWN0dXJlZE91dHB1dCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoc3VidHlwZSA9PT0gXCJlcnJvcl9tYXhfdHVybnNcIiB8fCBqLnRlcm1pbmFsX3JlYXNvbiA9PT0gXCJtYXhfdHVybnNcIik7XG4gICAgY29uc3QgaXNFcnJvciA9XG4gICAgICAhc3RydWN0dXJlZE1heFR1cm5zQ29tcGxldGVkICYmXG4gICAgICAoai5pc19lcnJvciA9PT0gdHJ1ZSB8fFxuICAgICAgICBqLnRlcm1pbmFsX3JlYXNvbiA9PT0gXCJtb2RlbF9lcnJvclwiIHx8XG4gICAgICAgIChzdWJ0eXBlICE9PSB1bmRlZmluZWQgJiYgc3VidHlwZSAhPT0gXCJzdWNjZXNzXCIpKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0LFxuICAgICAgdXNhZ2UsXG4gICAgICBkdXJhdGlvbk1zOiB0eXBlb2Ygai5kdXJhdGlvbl9tcyA9PT0gXCJudW1iZXJcIiA/IGouZHVyYXRpb25fbXMgOiAwLFxuICAgICAgY29zdFVzZDogdHlwZW9mIGoudG90YWxfY29zdF91c2QgPT09IFwibnVtYmVyXCIgPyBqLnRvdGFsX2Nvc3RfdXNkIDogMCxcbiAgICAgIHF1b3RhRXhoYXVzdGVkLFxuICAgICAgaXNFcnJvcixcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBOENBLFNBQVMsZ0JBQWdCLE9BQWlDO0FBQ3hELFFBQU8sTUFDSixRQUFRLE1BQWlELEVBQUUsU0FBUyxPQUFPLENBQzNFLEtBQUssTUFBTSxFQUFFLEtBQUssQ0FDbEIsS0FBSyxLQUFLOztBQUlmLFNBQVMsVUFBVSxNQUFxRDtBQUN0RSxRQUFPLENBQUM7RUFBRSxNQUFNO0VBQVE7RUFBTSxDQUFDOztBQVdqQyxTQUFTLFNBQVMsR0FBK0M7QUFDL0QsUUFBTyxPQUFPLE1BQU0sWUFBWSxNQUFNLFFBQVEsQ0FBQyxNQUFNLFFBQVEsRUFBRSxHQUFJLElBQXFCOztBQUsxRixTQUFTLGlCQUFpQixNQUE0QjtDQUNwRCxNQUFNLFVBQVUsS0FBSztBQUNyQixLQUFJLENBQUMsTUFBTSxRQUFRLFFBQVEsQ0FBRSxRQUFPO0FBQ3BDLFFBQU8sUUFDSixLQUFLLE1BQU07RUFDVixNQUFNLE1BQU0sU0FBUyxFQUFFO0FBQ3ZCLFNBQU8sT0FBTyxPQUFPLElBQUksU0FBUyxXQUFXLElBQUksT0FBTztHQUN4RCxDQUNELE9BQU8sUUFBUSxDQUNmLEtBQUssS0FBSzs7Ozs7OztBQVFmLFNBQVMsbUJBQW1CLGFBQXVDO0NBQ2pFLE1BQU0sUUFBdUIsRUFBRTtBQUMvQixNQUFLLE1BQU0sT0FBTyxhQUFhO0VBQzdCLE1BQU0sT0FBTyxTQUFTLElBQUk7QUFDMUIsTUFBSSxDQUFDLEtBQU07QUFFWCxNQUFJLEtBQUssU0FBUyxhQUFhLEtBQUssU0FBUyxZQUMzQyxPQUFNLEtBQUssY0FBYyxpQkFBaUIsS0FBSyxHQUFHO1dBQ3pDLEtBQUssU0FBUyxhQUFhLEtBQUssU0FBUyxPQUNsRCxPQUFNLEtBQUssU0FBUyxpQkFBaUIsS0FBSyxHQUFHO1dBQ3BDLEtBQUssU0FBUyxpQkFBaUI7R0FDeEMsTUFBTSxPQUFPLE9BQU8sS0FBSyxTQUFTLFdBQVcsS0FBSyxP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
|
|
@@ -39,77 +39,92 @@ const ANTHROPIC_COSTS = {
|
|
|
39
39
|
sonnet: {
|
|
40
40
|
inputTokens: 3,
|
|
41
41
|
outputTokens: 15,
|
|
42
|
-
cachedInputTokens: .3
|
|
42
|
+
cachedInputTokens: .3,
|
|
43
|
+
cacheCreationInputTokens: 3.75
|
|
43
44
|
},
|
|
44
45
|
"claude-3-5-haiku": {
|
|
45
46
|
inputTokens: .8,
|
|
46
47
|
outputTokens: 4,
|
|
47
|
-
cachedInputTokens: .08
|
|
48
|
+
cachedInputTokens: .08,
|
|
49
|
+
cacheCreationInputTokens: 1
|
|
48
50
|
},
|
|
49
51
|
"claude-haiku-4-5": {
|
|
50
52
|
inputTokens: 1,
|
|
51
53
|
outputTokens: 5,
|
|
52
|
-
cachedInputTokens: .1
|
|
54
|
+
cachedInputTokens: .1,
|
|
55
|
+
cacheCreationInputTokens: 1.25
|
|
53
56
|
},
|
|
54
57
|
"claude-3-5-sonnet": {
|
|
55
58
|
inputTokens: 3,
|
|
56
59
|
outputTokens: 15,
|
|
57
|
-
cachedInputTokens: .3
|
|
60
|
+
cachedInputTokens: .3,
|
|
61
|
+
cacheCreationInputTokens: 3.75
|
|
58
62
|
},
|
|
59
63
|
"claude-3-7-sonnet": {
|
|
60
64
|
inputTokens: 3,
|
|
61
65
|
outputTokens: 15,
|
|
62
|
-
cachedInputTokens: .3
|
|
66
|
+
cachedInputTokens: .3,
|
|
67
|
+
cacheCreationInputTokens: 3.75
|
|
63
68
|
},
|
|
64
69
|
"claude-sonnet-4": {
|
|
65
70
|
inputTokens: 3,
|
|
66
71
|
outputTokens: 15,
|
|
67
|
-
cachedInputTokens: .3
|
|
72
|
+
cachedInputTokens: .3,
|
|
73
|
+
cacheCreationInputTokens: 3.75
|
|
68
74
|
},
|
|
69
75
|
"claude-sonnet-4-5": {
|
|
70
76
|
inputTokens: 3,
|
|
71
77
|
outputTokens: 15,
|
|
72
|
-
cachedInputTokens: .3
|
|
78
|
+
cachedInputTokens: .3,
|
|
79
|
+
cacheCreationInputTokens: 3.75
|
|
73
80
|
},
|
|
74
81
|
"claude-sonnet-4-6": {
|
|
75
82
|
inputTokens: 3,
|
|
76
83
|
outputTokens: 15,
|
|
77
|
-
cachedInputTokens: .3
|
|
84
|
+
cachedInputTokens: .3,
|
|
85
|
+
cacheCreationInputTokens: 3.75
|
|
78
86
|
},
|
|
79
87
|
"claude-sonnet-4-7": {
|
|
80
88
|
inputTokens: 3,
|
|
81
89
|
outputTokens: 15,
|
|
82
|
-
cachedInputTokens: .3
|
|
90
|
+
cachedInputTokens: .3,
|
|
91
|
+
cacheCreationInputTokens: 3.75
|
|
83
92
|
},
|
|
84
93
|
"claude-opus-4": {
|
|
85
94
|
inputTokens: 15,
|
|
86
95
|
outputTokens: 75,
|
|
87
|
-
cachedInputTokens: 1.5
|
|
96
|
+
cachedInputTokens: 1.5,
|
|
97
|
+
cacheCreationInputTokens: 18.75
|
|
88
98
|
},
|
|
89
99
|
"claude-opus-4-1": {
|
|
90
100
|
inputTokens: 15,
|
|
91
101
|
outputTokens: 75,
|
|
92
|
-
cachedInputTokens: 1.5
|
|
102
|
+
cachedInputTokens: 1.5,
|
|
103
|
+
cacheCreationInputTokens: 18.75
|
|
93
104
|
},
|
|
94
105
|
"claude-opus-4-5": {
|
|
95
106
|
inputTokens: 5,
|
|
96
107
|
outputTokens: 25,
|
|
97
|
-
cachedInputTokens: .5
|
|
108
|
+
cachedInputTokens: .5,
|
|
109
|
+
cacheCreationInputTokens: 6.25
|
|
98
110
|
},
|
|
99
111
|
"claude-opus-4-6": {
|
|
100
112
|
inputTokens: 5,
|
|
101
113
|
outputTokens: 25,
|
|
102
|
-
cachedInputTokens: .5
|
|
114
|
+
cachedInputTokens: .5,
|
|
115
|
+
cacheCreationInputTokens: 6.25
|
|
103
116
|
},
|
|
104
117
|
"claude-opus-4-7": {
|
|
105
118
|
inputTokens: 5,
|
|
106
119
|
outputTokens: 25,
|
|
107
|
-
cachedInputTokens: .5
|
|
120
|
+
cachedInputTokens: .5,
|
|
121
|
+
cacheCreationInputTokens: 6.25
|
|
108
122
|
},
|
|
109
123
|
"claude-opus-4-8": {
|
|
110
124
|
inputTokens: 5,
|
|
111
125
|
outputTokens: 25,
|
|
112
|
-
cachedInputTokens: .5
|
|
126
|
+
cachedInputTokens: .5,
|
|
127
|
+
cacheCreationInputTokens: 6.25
|
|
113
128
|
}
|
|
114
129
|
};
|
|
115
130
|
const DEFAULT_COSTS = {
|
|
@@ -123,15 +138,17 @@ function getModelCosts(model) {
|
|
|
123
138
|
function calculateCostUsd(model, usage) {
|
|
124
139
|
const costs = getModelCosts(model);
|
|
125
140
|
const cachedInput = usage.cachedInputTokens ?? 0;
|
|
126
|
-
const
|
|
141
|
+
const cacheCreationInput = usage.cacheCreationInputTokens ?? 0;
|
|
142
|
+
const nonCachedInput = Math.max(usage.inputTokens - cachedInput - cacheCreationInput, 0);
|
|
127
143
|
const lc = costs.longContext;
|
|
128
144
|
const isLongContext = lc !== void 0 && usage.inputTokens > lc.threshold;
|
|
129
145
|
const inputRate = costs.inputTokens * (isLongContext ? lc.inputMultiplier : 1);
|
|
130
146
|
const cachedRate = costs.cachedInputTokens * (isLongContext ? lc.cachedInputMultiplier : 1);
|
|
147
|
+
const cacheCreationRate = (costs.cacheCreationInputTokens ?? costs.inputTokens) * (isLongContext ? lc.inputMultiplier : 1);
|
|
131
148
|
const outputRate = costs.outputTokens * (isLongContext ? lc.outputMultiplier : 1);
|
|
132
|
-
return nonCachedInput / 1e6 * inputRate + usage.outputTokens / 1e6 * outputRate + cachedInput / 1e6 * cachedRate;
|
|
149
|
+
return nonCachedInput / 1e6 * inputRate + usage.outputTokens / 1e6 * outputRate + cachedInput / 1e6 * cachedRate + cacheCreationInput / 1e6 * cacheCreationRate;
|
|
133
150
|
}
|
|
134
151
|
//#endregion
|
|
135
152
|
export { calculateCostUsd, getModelCosts };
|
|
136
153
|
|
|
137
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29zdC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9tb2RlbC1jb3N0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog66qo642467OEIO2GoO2BsCDqsIDqsqkg7YWM7J2067iUICsgY29zdCDqs4TsgrAuXG4gKlxuICogY2xhdWRlIGNvZGUg7JmAIOuPmeydvCDtjKjthLQ6IO2BtOudvOydtOyWuO2KuOyXkOyEnCDqsIDqsqkg7YWM7J2067iU66GcIOyngeygkSDqs4TsgrAuXG4gKiDqsIDqsqkg64uo7JyEOiBVU0QgcGVyIDFNIHRva2Vucy5cbiAqXG4gKiBPcGVuQUkg66qo6424IOuqqeuhnTogY29kZXggYXBwLXNlcnZlciBtb2RlbC9saXN0IFJQQyDroZwg7Iuk7LihICgyMDI2LTA1LTE4KVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9wbGF0Zm9ybS5vcGVuYWkuY29tL2RvY3MvcHJpY2luZ1xuICogQHNlZSBodHRwczovL3BsYXRmb3JtLmNsYXVkZS5jb20vZG9jcy9lbi9hYm91dC1jbGF1ZGUvcHJpY2luZ1xuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxDb3N0cyB7XG4gIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gIG91dHB1dFRva2VuczogbnVtYmVyO1xuICBjYWNoZWRJbnB1dFRva2VuczogbnVtYmVyO1xuICAvKipcbiAgICogbG9uZy1jb250ZXh0IO2VoOymnS4g7KCE7LK0IOyeheugpSDthqDtgbAoaW5wdXRfdG9rZW5zLCBjYWNoZV9yZWFkIO2PrO2VqCnsnbQgdGhyZXNob2xkIOy0iOqzvCDsi5xcbiAgICog7LSI6rO867aE66eM7J20IOyVhOuLiOudvCDsmpTssq0g7KCE7LK0KGZ1bGwgc2Vzc2lvbinsl5Ag67Cw7JyoIOyggeyaqS5cbiAgICovXG4gIGxvbmdDb250ZXh0Pzoge1xuICAgIHRocmVzaG9sZDogbnVtYmVyO1xuICAgIGlucHV0TXVsdGlwbGllcjogbnVtYmVyO1xuICAgIGNhY2hlZElucHV0TXVsdGlwbGllcjogbnVtYmVyO1xuICAgIG91dHB1dE11bHRpcGxpZXI6IG51bWJlcjtcbiAgfTtcbn1cblxuLy8g4pSA4pSAIE9wZW5BSSDigJQgY29kZXggYXBwLXNlcnZlciDsl5DshJwg7IKs7JqpIOqwgOuKpe2VnCDrqqjrjbgg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vL1xuLy8g6rCA6rKpIOy2nOyymDogaHR0cHM6Ly9vcGVuYWkuY29tL2FwaS9wcmljaW5nICgyMDI2LTA2LTExIO2ZleyduClcbi8vIOyLoOuqqOuNuCDstpzsi5zrp4jri6Qg64uo6rCA6rCAIOuwlOuAjOuvgOuhnCg1LjLihpI1LjTihpI1LjUpIOuqqOuNuCDstpTqsIAg7IucIOuwmOuTnOyLnCDqs7Xsi50g7Y6Y7J207KeAIOyerO2ZleyduO2VtOyVvO2VqFxuXG4vLyBHUFQtNS407JeQ7IScIOyymOydjCDrj4TsnoXrkJwgbG9uZy1jb250ZXh0IO2VoOymnSAoNS4yLzUuMy1jb2RleOuKlCDtlbTri7kg7JeG7J2MLCA1LjQtbWluaeuKlCDrr7jtmZXsnbgpXG4vLyAyNzJLIOy0iOqzvCDsi5wgaW5wdXQgMnggLyBjYWNoZWQgMnggLyBvdXRwdXQgMS41eCDigJQg7LSI6rO867aE66eM7J20IOyVhOuLjCDshLjshZgg7KCE7LK07JeQIOyggeyaqeuQqFxuLy8gQHNlZSBodHRwczovL2RldmVsb3BlcnMub3BlbmFpLmNvbS9hcGkvZG9jcy9tb2RlbHMvZ3B0LTUuNSAoXCJwcm9tcHRzIHdpdGggPjI3MksgaW5wdXQgdG9rZW5zXCIpXG5jb25zdCBMT05HX0NPTlRFWFRfMjcySzogTm9uTnVsbGFibGU8TW9kZWxDb3N0c1tcImxvbmdDb250ZXh0XCJdPiA9IHtcbiAgdGhyZXNob2xkOiAyNzJfMDAwLFxuICBpbnB1dE11bHRpcGxpZXI6IDIsXG4gIGNhY2hlZElucHV0TXVsdGlwbGllcjogMixcbiAgb3V0cHV0TXVsdGlwbGllcjogMS41LFxufTtcblxuY29uc3QgT1BFTkFJX0NPU1RTOiBSZWNvcmQ8c3RyaW5nLCBNb2RlbENvc3RzPiA9IHtcbiAgLy8gaHR0cHM6Ly9vcGVuYWkuY29tL2luZGV4L2ludHJvZHVjaW5nLWdwdC01LTUvICgyMDI2LTA0IOy2nOyLnClcbiAgXCJncHQtNS41XCI6IHtcbiAgICBpbnB1dFRva2VuczogNSxcbiAgICBvdXRwdXRUb2tlbnM6IDMwLFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjUsXG4gICAgbG9uZ0NvbnRleHQ6IExPTkdfQ09OVEVYVF8yNzJLLFxuICB9LFxuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtNC8gKDIwMjYtMDMg7Lac7IucKVxuICBcImdwdC01LjRcIjoge1xuICAgIGlucHV0VG9rZW5zOiAyLjUsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4yNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIFwiZ3B0LTUuNC1taW5pXCI6IHsgaW5wdXRUb2tlbnM6IDAuNzUsIG91dHB1dFRva2VuczogNC41LCBjYWNoZWRJbnB1dFRva2VuczogMC4wNzUgfSxcbiAgLy8gZ3B0LTUuMuyZgCDrj5nsnbwg64uo6rCAIChjYWNoZWQgPSBpbnB1dOydmCAxMCUpXG4gIFwiZ3B0LTUuMy1jb2RleFwiOiB7IGlucHV0VG9rZW5zOiAxLjc1LCBvdXRwdXRUb2tlbnM6IDE0LCBjYWNoZWRJbnB1dFRva2VuczogMC4xNzUgfSxcbiAgLy8gaHR0cHM6Ly9vcGVuYWkuY29tL2luZGV4L2ludHJvZHVjaW5nLWdwdC01LTIvIChjYWNoZWQgaW5wdXQgOTAlIO2VoOyduCDrqoXsi5wpXG4gIFwiZ3B0LTUuMlwiOiB7IGlucHV0VG9rZW5zOiAxLjc1LCBvdXRwdXRUb2tlbnM6IDE0LCBjYWNoZWRJbnB1dFRva2VuczogMC4xNzUgfSxcbn07XG5cbi8vIOKUgOKUgCBBbnRocm9waWMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmNvbnN0IEFOVEhST1BJQ19DT1NUUzogUmVjb3JkPHN0cmluZywgTW9kZWxDb3N0cz4gPSB7XG4gIHNvbm5ldDogeyBpbnB1dFRva2VuczogMywgb3V0cHV0VG9rZW5zOiAxNSwgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMyB9LFxuICBcImNsYXVkZS0zLTUtaGFpa3VcIjogeyBpbnB1dFRva2VuczogMC44LCBvdXRwdXRUb2tlbnM6IDQsIGNhY2hlZElucHV0VG9rZW5zOiAwLjA4IH0sXG4gIFwiY2xhdWRlLWhhaWt1LTQtNVwiOiB7IGlucHV0VG9rZW5zOiAxLCBvdXRwdXRUb2tlbnM6IDUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjEgfSxcbiAgXCJjbGF1ZGUtMy01LXNvbm5ldFwiOiB7IGlucHV0VG9rZW5zOiAzLCBvdXRwdXRUb2tlbnM6IDE1LCBjYWNoZWRJbnB1dFRva2VuczogMC4zIH0sXG4gIFwiY2xhdWRlLTMtNy1zb25uZXRcIjogeyBpbnB1dFRva2VuczogMywgb3V0cHV0VG9rZW5zOiAxNSwgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMyB9LFxuICBcImNsYXVkZS1zb25uZXQtNFwiOiB7IGlucHV0VG9rZW5zOiAzLCBvdXRwdXRUb2tlbnM6IDE1LCBjYWNoZWRJbnB1dFRva2VuczogMC4zIH0sXG4gIFwiY2xhdWRlLXNvbm5ldC00LTVcIjogeyBpbnB1dFRva2VuczogMywgb3V0cHV0VG9rZW5zOiAxNSwgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMyB9LFxuICBcImNsYXVkZS1zb25uZXQtNC02XCI6IHsgaW5wdXRUb2tlbnM6IDMsIG91dHB1dFRva2VuczogMTUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjMgfSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtN1wiOiB7IGlucHV0VG9rZW5zOiAzLCBvdXRwdXRUb2tlbnM6IDE1LCBjYWNoZWRJbnB1dFRva2VuczogMC4zIH0sXG4gIFwiY2xhdWRlLW9wdXMtNFwiOiB7IGlucHV0VG9rZW5zOiAxNSwgb3V0cHV0VG9rZW5zOiA3NSwgY2FjaGVkSW5wdXRUb2tlbnM6IDEuNSB9LFxuICBcImNsYXVkZS1vcHVzLTQtMVwiOiB7IGlucHV0VG9rZW5zOiAxNSwgb3V0cHV0VG9rZW5zOiA3NSwgY2FjaGVkSW5wdXRUb2tlbnM6IDEuNSB9LFxuICBcImNsYXVkZS1vcHVzLTQtNVwiOiB7IGlucHV0VG9rZW5zOiA1LCBvdXRwdXRUb2tlbnM6IDI1LCBjYWNoZWRJbnB1dFRva2VuczogMC41IH0sXG4gIFwiY2xhdWRlLW9wdXMtNC02XCI6IHsgaW5wdXRUb2tlbnM6IDUsIG91dHB1dFRva2VuczogMjUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjUgfSxcbiAgXCJjbGF1ZGUtb3B1cy00LTdcIjogeyBpbnB1dFRva2VuczogNSwgb3V0cHV0VG9rZW5zOiAyNSwgY2FjaGVkSW5wdXRUb2tlbnM6IDAuNSB9LFxuICBcImNsYXVkZS1vcHVzLTQtOFwiOiB7IGlucHV0VG9rZW5zOiA1LCBvdXRwdXRUb2tlbnM6IDI1LCBjYWNoZWRJbnB1dFRva2VuczogMC41IH0sXG59O1xuXG5jb25zdCBERUZBVUxUX0NPU1RTOiBNb2RlbENvc3RzID0geyBpbnB1dFRva2VuczogMywgb3V0cHV0VG9rZW5zOiAxNSwgY2FjaGVkSW5wdXRUb2tlbnM6IDAuMyB9O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9kZWxDb3N0cyhtb2RlbDogc3RyaW5nKTogTW9kZWxDb3N0cyB7XG4gIHJldHVybiBPUEVOQUlfQ09TVFNbbW9kZWxdID8/IEFOVEhST1BJQ19DT1NUU1ttb2RlbF0gPz8gREVGQVVMVF9DT1NUUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUNvc3RVc2QoXG4gIG1vZGVsOiBzdHJpbmcsXG4gIHVzYWdlOiB7IGlucHV0VG9rZW5zOiBudW1iZXI7IG91dHB1dFRva2VuczogbnVtYmVyOyBjYWNoZWRJbnB1dFRva2Vucz86IG51bWJlciB9LFxuKTogbnVtYmVyIHtcbiAgY29uc3QgY29zdHMgPSBnZXRNb2RlbENvc3RzKG1vZGVsKTtcbiAgY29uc3QgY2FjaGVkSW5wdXQgPSB1c2FnZS5jYWNoZWRJbnB1dFRva2VucyA/PyAwO1xuICBjb25zdCBub25DYWNoZWRJbnB1dCA9IHVzYWdlLmlucHV0VG9rZW5zIC0gY2FjaGVkSW5wdXQ7XG5cbiAgLy8gbG9uZy1jb250ZXh0IO2VoOymnTog7KCE7LK0IOyeheugpShpbnB1dF90b2tlbnMsIGNhY2hlIO2PrO2VqCnsnbQgdGhyZXNob2xkIOy0iOqzvCDsi5wg7JqU7LKtIOyghOyytOyXkCDrsLDsnKgg7KCB7JqpXG4gIGNvbnN0IGxjID0gY29zdHMubG9uZ0NvbnRleHQ7XG4gIGNvbnN0IGlzTG9uZ0NvbnRleHQgPSBsYyAhPT0gdW5kZWZpbmVkICYmIHVzYWdlLmlucHV0VG9rZW5zID4gbGMudGhyZXNob2xkO1xuICBjb25zdCBpbnB1dFJhdGUgPSBjb3N0cy5pbnB1dFRva2VucyAqIChpc0xvbmdDb250ZXh0ID8gbGMuaW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IGNhY2hlZFJhdGUgPSBjb3N0cy5jYWNoZWRJbnB1dFRva2VucyAqIChpc0xvbmdDb250ZXh0ID8gbGMuY2FjaGVkSW5wdXRNdWx0aXBsaWVyIDogMSk7XG4gIGNvbnN0IG91dHB1dFJhdGUgPSBjb3N0cy5vdXRwdXRUb2tlbnMgKiAoaXNMb25nQ29udGV4dCA/IGxjLm91dHB1dE11bHRpcGxpZXIgOiAxKTtcblxuICByZXR1cm4gKFxuICAgIChub25DYWNoZWRJbnB1dCAvIDFfMDAwXzAwMCkgKiBpbnB1dFJhdGUgK1xuICAgICh1c2FnZS5vdXRwdXRUb2tlbnMgLyAxXzAwMF8wMDApICogb3V0cHV0UmF0ZSArXG4gICAgKGNhY2hlZElucHV0IC8gMV8wMDBfMDAwKSAqIGNhY2hlZFJhdGVcbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7QUFvQ0EsTUFBTSxvQkFBNEQ7Q0FDaEUsV0FBVztDQUNYLGlCQUFpQjtDQUNqQix1QkFBdUI7Q0FDdkIsa0JBQWtCO0NBQ25CO0FBRUQsTUFBTSxlQUEyQztDQUUvQyxXQUFXO0VBQ1QsYUFBYTtFQUNiLGNBQWM7RUFDZCxtQkFBbUI7RUFDbkIsYUFBYTtFQUNkO0NBRUQsV0FBVztFQUNULGFBQWE7RUFDYixjQUFjO0VBQ2QsbUJBQW1CO0VBQ25CLGFBQWE7RUFDZDtDQUNELGdCQUFnQjtFQUFFLGFBQWE7RUFBTSxjQUFjO0VBQUssbUJBQW1CO0VBQU87Q0FFbEYsaUJBQWlCO0VBQUUsYUFBYTtFQUFNLGNBQWM7RUFBSSxtQkFBbUI7RUFBTztDQUVsRixXQUFXO0VBQUUsYUFBYTtFQUFNLGNBQWM7RUFBSSxtQkFBbUI7RUFBTztDQUM3RTtBQUlELE1BQU0sa0JBQThDO0NBQ2xELFFBQVE7RUFBRSxhQUFhO0VBQUcsY0FBYztFQUFJLG1CQUFtQjtFQUFLO0NBQ3BFLG9CQUFvQjtFQUFFLGFBQWE7RUFBSyxjQUFjO0VBQUcsbUJBQW1CO0VBQU07Q0FDbEYsb0JBQW9CO0VBQUUsYUFBYTtFQUFHLGNBQWM7RUFBRyxtQkFBbUI7RUFBSztDQUMvRSxxQkFBcUI7RUFBRSxhQUFhO0VBQUcsY0FBYztFQUFJLG1CQUFtQjtFQUFLO0NBQ2pGLHFCQUFxQjtFQUFFLGFBQWE7RUFBRyxjQUFjO0VBQUksbUJBQW1CO0VBQUs7Q0FDakYsbUJBQW1CO0VBQUUsYUFBYTtFQUFHLGNBQWM7RUFBSSxtQkFBbUI7RUFBSztDQUMvRSxxQkFBcUI7RUFBRSxhQUFhO0VBQUcsY0FBYztFQUFJLG1CQUFtQjtFQUFLO0NBQ2pGLHFCQUFxQjtFQUFFLGFBQWE7RUFBRyxjQUFjO0VBQUksbUJBQW1CO0VBQUs7Q0FDakYscUJBQXFCO0VBQUUsYUFBYTtFQUFHLGNBQWM7RUFBSSxtQkFBbUI7RUFBSztDQUNqRixpQkFBaUI7RUFBRSxhQUFhO0VBQUksY0FBYztFQUFJLG1CQUFtQjtFQUFLO0NBQzlFLG1CQUFtQjtFQUFFLGFBQWE7RUFBSSxjQUFjO0VBQUksbUJBQW1CO0VBQUs7Q0FDaEYsbUJBQW1CO0VBQUUsYUFBYTtFQUFHLGNBQWM7RUFBSSxtQkFBbUI7RUFBSztDQUMvRSxtQkFBbUI7RUFBRSxhQUFhO0VBQUcsY0FBYztFQUFJLG1CQUFtQjtFQUFLO0NBQy9FLG1CQUFtQjtFQUFFLGFBQWE7RUFBRyxjQUFjO0VBQUksbUJBQW1CO0VBQUs7Q0FDL0UsbUJBQW1CO0VBQUUsYUFBYTtFQUFHLGNBQWM7RUFBSSxtQkFBbUI7RUFBSztDQUNoRjtBQUVELE1BQU0sZ0JBQTRCO0NBQUUsYUFBYTtDQUFHLGNBQWM7Q0FBSSxtQkFBbUI7Q0FBSztBQUU5RixTQUFnQixjQUFjLE9BQTJCO0FBQ3ZELFFBQU8sYUFBYSxVQUFVLGdCQUFnQixVQUFVOztBQUcxRCxTQUFnQixpQkFDZCxPQUNBLE9BQ1E7Q0FDUixNQUFNLFFBQVEsY0FBYyxNQUFNO0NBQ2xDLE1BQU0sY0FBYyxNQUFNLHFCQUFxQjtDQUMvQyxNQUFNLGlCQUFpQixNQUFNLGNBQWM7Q0FHM0MsTUFBTSxLQUFLLE1BQU07Q0FDakIsTUFBTSxnQkFBZ0IsT0FBTyxVQUFhLE1BQU0sY0FBYyxHQUFHO0NBQ2pFLE1BQU0sWUFBWSxNQUFNLGVBQWUsZ0JBQWdCLEdBQUcsa0JBQWtCO0NBQzVFLE1BQU0sYUFBYSxNQUFNLHFCQUFxQixnQkFBZ0IsR0FBRyx3QkFBd0I7Q0FDekYsTUFBTSxhQUFhLE1BQU0sZ0JBQWdCLGdCQUFnQixHQUFHLG1CQUFtQjtBQUUvRSxRQUNHLGlCQUFpQixNQUFhLFlBQzlCLE1BQU0sZUFBZSxNQUFhLGFBQ2xDLGNBQWMsTUFBYSJ9
|
|
154
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29zdC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL2NvbW1vbi9tb2RlbC1jb3N0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog66qo642467OEIO2GoO2BsCDqsIDqsqkg7YWM7J2067iUICsgY29zdCDqs4TsgrAuXG4gKlxuICogY2xhdWRlIGNvZGUg7JmAIOuPmeydvCDtjKjthLQ6IO2BtOudvOydtOyWuO2KuOyXkOyEnCDqsIDqsqkg7YWM7J2067iU66GcIOyngeygkSDqs4TsgrAuXG4gKiDqsIDqsqkg64uo7JyEOiBVU0QgcGVyIDFNIHRva2Vucy5cbiAqXG4gKiBPcGVuQUkg66qo6424IOuqqeuhnTogY29kZXggYXBwLXNlcnZlciBtb2RlbC9saXN0IFJQQyDroZwg7Iuk7LihICgyMDI2LTA1LTE4KVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9wbGF0Zm9ybS5vcGVuYWkuY29tL2RvY3MvcHJpY2luZ1xuICogQHNlZSBodHRwczovL3BsYXRmb3JtLmNsYXVkZS5jb20vZG9jcy9lbi9hYm91dC1jbGF1ZGUvcHJpY2luZ1xuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxDb3N0cyB7XG4gIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gIG91dHB1dFRva2VuczogbnVtYmVyO1xuICBjYWNoZWRJbnB1dFRva2VuczogbnVtYmVyO1xuICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBsb25nLWNvbnRleHQg7ZWg7KadLiDsoITssrQg7J6F66ClIO2GoO2BsChpbnB1dF90b2tlbnMsIGNhY2hlX3JlYWQg7Y+s7ZWoKeydtCB0aHJlc2hvbGQg7LSI6rO8IOyLnFxuICAgKiDstIjqs7zrtoTrp4zsnbQg7JWE64uI6528IOyalOyyrSDsoITssrQoZnVsbCBzZXNzaW9uKeyXkCDrsLDsnKgg7KCB7JqpLlxuICAgKi9cbiAgbG9uZ0NvbnRleHQ/OiB7XG4gICAgdGhyZXNob2xkOiBudW1iZXI7XG4gICAgaW5wdXRNdWx0aXBsaWVyOiBudW1iZXI7XG4gICAgY2FjaGVkSW5wdXRNdWx0aXBsaWVyOiBudW1iZXI7XG4gICAgb3V0cHV0TXVsdGlwbGllcjogbnVtYmVyO1xuICB9O1xufVxuXG4vLyDilIDilIAgT3BlbkFJIOKAlCBjb2RleCBhcHAtc2VydmVyIOyXkOyEnCDsgqzsmqkg6rCA64ql7ZWcIOuqqOuNuCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vXG4vLyDqsIDqsqkg7Lac7LKYOiBodHRwczovL29wZW5haS5jb20vYXBpL3ByaWNpbmcgKDIwMjYtMDYtMTEg7ZmV7J24KVxuLy8g7Iug66qo6424IOy2nOyLnOuniOuLpCDri6jqsIDqsIAg67CU64CM66+A66GcKDUuMuKGkjUuNOKGkjUuNSkg66qo6424IOy2lOqwgCDsi5wg67CY65Oc7IucIOqzteyLnSDtjpjsnbTsp4Ag7J6s7ZmV7J247ZW07JW87ZWoXG5cbi8vIEdQVC01LjTsl5DshJwg7LKY7J2MIOuPhOyeheuQnCBsb25nLWNvbnRleHQg7ZWg7KadICg1LjIvNS4zLWNvZGV464qUIO2VtOuLuSDsl4bsnYwsIDUuNC1taW5pL25hbm/ripQg6rO17IudIO2RnOyXkOyEnCBsb25nLWNvbnRleHQg64uo6rCAIOyXhuydjClcbi8vIDI3Mksg7LSI6rO8IOyLnCBpbnB1dCAyeCAvIGNhY2hlZCAyeCAvIG91dHB1dCAxLjV4IOKAlCDstIjqs7zrtoTrp4zsnbQg7JWE64uMIOyEuOyFmCDsoITssrTsl5Ag7KCB7Jqp65CoXG4vLyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuYWkuY29tL2FwaS9kb2NzL21vZGVscy9ncHQtNS41IChcInByb21wdHMgd2l0aCA+MjcySyBpbnB1dCB0b2tlbnNcIilcbmNvbnN0IExPTkdfQ09OVEVYVF8yNzJLOiBOb25OdWxsYWJsZTxNb2RlbENvc3RzW1wibG9uZ0NvbnRleHRcIl0+ID0ge1xuICB0aHJlc2hvbGQ6IDI3Ml8wMDAsXG4gIGlucHV0TXVsdGlwbGllcjogMixcbiAgY2FjaGVkSW5wdXRNdWx0aXBsaWVyOiAyLFxuICBvdXRwdXRNdWx0aXBsaWVyOiAxLjUsXG59O1xuXG5jb25zdCBPUEVOQUlfQ09TVFM6IFJlY29yZDxzdHJpbmcsIE1vZGVsQ29zdHM+ID0ge1xuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtNS8gKDIwMjYtMDQg7Lac7IucKVxuICBcImdwdC01LjVcIjoge1xuICAgIGlucHV0VG9rZW5zOiA1LFxuICAgIG91dHB1dFRva2VuczogMzAsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuNSxcbiAgICBsb25nQ29udGV4dDogTE9OR19DT05URVhUXzI3MkssXG4gIH0sXG4gIC8vIGh0dHBzOi8vb3BlbmFpLmNvbS9pbmRleC9pbnRyb2R1Y2luZy1ncHQtNS00LyAoMjAyNi0wMyDstpzsi5wpXG4gIFwiZ3B0LTUuNFwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDIuNSxcbiAgICBvdXRwdXRUb2tlbnM6IDE1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjI1LFxuICAgIGxvbmdDb250ZXh0OiBMT05HX0NPTlRFWFRfMjcySyxcbiAgfSxcbiAgXCJncHQtNS40LW1pbmlcIjogeyBpbnB1dFRva2VuczogMC43NSwgb3V0cHV0VG9rZW5zOiA0LjUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjA3NSB9LFxuICAvLyBncHQtNS4y7JmAIOuPmeydvCDri6jqsIAgKGNhY2hlZCA9IGlucHV07J2YIDEwJSlcbiAgXCJncHQtNS4zLWNvZGV4XCI6IHsgaW5wdXRUb2tlbnM6IDEuNzUsIG91dHB1dFRva2VuczogMTQsIGNhY2hlZElucHV0VG9rZW5zOiAwLjE3NSB9LFxuICAvLyBodHRwczovL29wZW5haS5jb20vaW5kZXgvaW50cm9kdWNpbmctZ3B0LTUtMi8gKGNhY2hlZCBpbnB1dCA5MCUg7ZWg7J24IOuqheyLnClcbiAgXCJncHQtNS4yXCI6IHsgaW5wdXRUb2tlbnM6IDEuNzUsIG91dHB1dFRva2VuczogMTQsIGNhY2hlZElucHV0VG9rZW5zOiAwLjE3NSB9LFxufTtcblxuLy8g4pSA4pSAIEFudGhyb3BpYyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuY29uc3QgQU5USFJPUElDX0NPU1RTOiBSZWNvcmQ8c3RyaW5nLCBNb2RlbENvc3RzPiA9IHtcbiAgLy8gQ2xhdWRlIENvZGUg64qUIOuzhOuPhCB0dGw6XCIxaFwiIOyYteyFmCDsl4bsnbQg7Iuk7ZaJ65CY66+A66GcIGZhbGxiYWNrIOqwgOqyqe2RnOuKlCA167aEIGNhY2hlIHdyaXRlKDEuMjV4KeulvCDquLDspIDsnLzroZwg65GU64ukLlxuICAvLyAx7Iuc6rCEIGNhY2hlIHdyaXRlIOuKlCBpbnB1dCAyeCDsnbTsp4Drp4wg7ZiE7J6sIHFncmlkIOyLpO2WiSDqsr3roZzsnZgg6riw67O46rCS7J20IOyVhOuLiOuLpC5cbiAgc29ubmV0OiB7XG4gICAgaW5wdXRUb2tlbnM6IDMsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4zLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMy43NSxcbiAgfSxcbiAgXCJjbGF1ZGUtMy01LWhhaWt1XCI6IHtcbiAgICBpbnB1dFRva2VuczogMC44LFxuICAgIG91dHB1dFRva2VuczogNCxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4wOCxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDEsXG4gIH0sXG4gIFwiY2xhdWRlLWhhaWt1LTQtNVwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDEsXG4gICAgb3V0cHV0VG9rZW5zOiA1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjEsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiAxLjI1LFxuICB9LFxuICBcImNsYXVkZS0zLTUtc29ubmV0XCI6IHtcbiAgICBpbnB1dFRva2VuczogMyxcbiAgICBvdXRwdXRUb2tlbnM6IDE1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjMsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiAzLjc1LFxuICB9LFxuICBcImNsYXVkZS0zLTctc29ubmV0XCI6IHtcbiAgICBpbnB1dFRva2VuczogMyxcbiAgICBvdXRwdXRUb2tlbnM6IDE1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjMsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiAzLjc1LFxuICB9LFxuICBcImNsYXVkZS1zb25uZXQtNFwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDMsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4zLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMy43NSxcbiAgfSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtNVwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDMsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4zLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMy43NSxcbiAgfSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtNlwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDMsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4zLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMy43NSxcbiAgfSxcbiAgXCJjbGF1ZGUtc29ubmV0LTQtN1wiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDMsXG4gICAgb3V0cHV0VG9rZW5zOiAxNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC4zLFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMy43NSxcbiAgfSxcbiAgXCJjbGF1ZGUtb3B1cy00XCI6IHtcbiAgICBpbnB1dFRva2VuczogMTUsXG4gICAgb3V0cHV0VG9rZW5zOiA3NSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMS41LFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMTguNzUsXG4gIH0sXG4gIFwiY2xhdWRlLW9wdXMtNC0xXCI6IHtcbiAgICBpbnB1dFRva2VuczogMTUsXG4gICAgb3V0cHV0VG9rZW5zOiA3NSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMS41LFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogMTguNzUsXG4gIH0sXG4gIFwiY2xhdWRlLW9wdXMtNC01XCI6IHtcbiAgICBpbnB1dFRva2VuczogNSxcbiAgICBvdXRwdXRUb2tlbnM6IDI1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjUsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiA2LjI1LFxuICB9LFxuICBcImNsYXVkZS1vcHVzLTQtNlwiOiB7XG4gICAgaW5wdXRUb2tlbnM6IDUsXG4gICAgb3V0cHV0VG9rZW5zOiAyNSxcbiAgICBjYWNoZWRJbnB1dFRva2VuczogMC41LFxuICAgIGNhY2hlQ3JlYXRpb25JbnB1dFRva2VuczogNi4yNSxcbiAgfSxcbiAgXCJjbGF1ZGUtb3B1cy00LTdcIjoge1xuICAgIGlucHV0VG9rZW5zOiA1LFxuICAgIG91dHB1dFRva2VuczogMjUsXG4gICAgY2FjaGVkSW5wdXRUb2tlbnM6IDAuNSxcbiAgICBjYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnM6IDYuMjUsXG4gIH0sXG4gIFwiY2xhdWRlLW9wdXMtNC04XCI6IHtcbiAgICBpbnB1dFRva2VuczogNSxcbiAgICBvdXRwdXRUb2tlbnM6IDI1LFxuICAgIGNhY2hlZElucHV0VG9rZW5zOiAwLjUsXG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zOiA2LjI1LFxuICB9LFxufTtcblxuY29uc3QgREVGQVVMVF9DT1NUUzogTW9kZWxDb3N0cyA9IHsgaW5wdXRUb2tlbnM6IDMsIG91dHB1dFRva2VuczogMTUsIGNhY2hlZElucHV0VG9rZW5zOiAwLjMgfTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZGVsQ29zdHMobW9kZWw6IHN0cmluZyk6IE1vZGVsQ29zdHMge1xuICByZXR1cm4gT1BFTkFJX0NPU1RTW21vZGVsXSA/PyBBTlRIUk9QSUNfQ09TVFNbbW9kZWxdID8/IERFRkFVTFRfQ09TVFM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVDb3N0VXNkKFxuICBtb2RlbDogc3RyaW5nLFxuICB1c2FnZToge1xuICAgIGlucHV0VG9rZW5zOiBudW1iZXI7XG4gICAgb3V0cHV0VG9rZW5zOiBudW1iZXI7XG4gICAgY2FjaGVkSW5wdXRUb2tlbnM/OiBudW1iZXI7XG4gICAgY2FjaGVDcmVhdGlvbklucHV0VG9rZW5zPzogbnVtYmVyO1xuICB9LFxuKTogbnVtYmVyIHtcbiAgY29uc3QgY29zdHMgPSBnZXRNb2RlbENvc3RzKG1vZGVsKTtcbiAgY29uc3QgY2FjaGVkSW5wdXQgPSB1c2FnZS5jYWNoZWRJbnB1dFRva2VucyA/PyAwO1xuICBjb25zdCBjYWNoZUNyZWF0aW9uSW5wdXQgPSB1c2FnZS5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gMDtcbiAgY29uc3Qgbm9uQ2FjaGVkSW5wdXQgPSBNYXRoLm1heCh1c2FnZS5pbnB1dFRva2VucyAtIGNhY2hlZElucHV0IC0gY2FjaGVDcmVhdGlvbklucHV0LCAwKTtcblxuICAvLyBsb25nLWNvbnRleHQg7ZWg7KadOiDsoITssrQg7J6F66ClKGlucHV0X3Rva2VucywgY2FjaGUg7Y+s7ZWoKeydtCB0aHJlc2hvbGQg7LSI6rO8IOyLnCDsmpTssq0g7KCE7LK07JeQIOuwsOycqCDsoIHsmqlcbiAgY29uc3QgbGMgPSBjb3N0cy5sb25nQ29udGV4dDtcbiAgY29uc3QgaXNMb25nQ29udGV4dCA9IGxjICE9PSB1bmRlZmluZWQgJiYgdXNhZ2UuaW5wdXRUb2tlbnMgPiBsYy50aHJlc2hvbGQ7XG4gIGNvbnN0IGlucHV0UmF0ZSA9IGNvc3RzLmlucHV0VG9rZW5zICogKGlzTG9uZ0NvbnRleHQgPyBsYy5pbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3QgY2FjaGVkUmF0ZSA9IGNvc3RzLmNhY2hlZElucHV0VG9rZW5zICogKGlzTG9uZ0NvbnRleHQgPyBsYy5jYWNoZWRJbnB1dE11bHRpcGxpZXIgOiAxKTtcbiAgY29uc3QgY2FjaGVDcmVhdGlvblJhdGUgPVxuICAgIChjb3N0cy5jYWNoZUNyZWF0aW9uSW5wdXRUb2tlbnMgPz8gY29zdHMuaW5wdXRUb2tlbnMpICpcbiAgICAoaXNMb25nQ29udGV4dCA/IGxjLmlucHV0TXVsdGlwbGllciA6IDEpO1xuICBjb25zdCBvdXRwdXRSYXRlID0gY29zdHMub3V0cHV0VG9rZW5zICogKGlzTG9uZ0NvbnRleHQgPyBsYy5vdXRwdXRNdWx0aXBsaWVyIDogMSk7XG5cbiAgcmV0dXJuIChcbiAgICAobm9uQ2FjaGVkSW5wdXQgLyAxXzAwMF8wMDApICogaW5wdXRSYXRlICtcbiAgICAodXNhZ2Uub3V0cHV0VG9rZW5zIC8gMV8wMDBfMDAwKSAqIG91dHB1dFJhdGUgK1xuICAgIChjYWNoZWRJbnB1dCAvIDFfMDAwXzAwMCkgKiBjYWNoZWRSYXRlICtcbiAgICAoY2FjaGVDcmVhdGlvbklucHV0IC8gMV8wMDBfMDAwKSAqIGNhY2hlQ3JlYXRpb25SYXRlXG4gICk7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBcUNBLE1BQU0sb0JBQTREO0NBQ2hFLFdBQVc7Q0FDWCxpQkFBaUI7Q0FDakIsdUJBQXVCO0NBQ3ZCLGtCQUFrQjtDQUNuQjtBQUVELE1BQU0sZUFBMkM7Q0FFL0MsV0FBVztFQUNULGFBQWE7RUFDYixjQUFjO0VBQ2QsbUJBQW1CO0VBQ25CLGFBQWE7RUFDZDtDQUVELFdBQVc7RUFDVCxhQUFhO0VBQ2IsY0FBYztFQUNkLG1CQUFtQjtFQUNuQixhQUFhO0VBQ2Q7Q0FDRCxnQkFBZ0I7RUFBRSxh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
|
|
@@ -16,6 +16,7 @@ const inflightRefresh = /* @__PURE__ */ new Map();
|
|
|
16
16
|
const lastRefreshTime = /* @__PURE__ */ new Map();
|
|
17
17
|
const REFRESH_MIN_INTERVAL_MS = 5e3;
|
|
18
18
|
async function handleChatgptAuthTokensRefresh(tokenId) {
|
|
19
|
+
logger.info(`refresh requested for token ${tokenId} (pid=${process.pid})`);
|
|
19
20
|
const existing = inflightRefresh.get(tokenId);
|
|
20
21
|
if (existing) {
|
|
21
22
|
logger.info(`refresh dedup for token ${tokenId}`);
|
|
@@ -62,11 +63,17 @@ async function doRefresh(tokenId) {
|
|
|
62
63
|
});
|
|
63
64
|
if (!resp.ok) {
|
|
64
65
|
const body = await resp.text().catch(() => "");
|
|
66
|
+
let errorCode;
|
|
67
|
+
try {
|
|
68
|
+
errorCode = JSON.parse(body).error;
|
|
69
|
+
} catch {}
|
|
70
|
+
logger.error(`OpenAI refresh FAILED token=${token.name}(id=${tokenId}) status=${resp.status} code=${errorCode ?? "?"} body=${body}`);
|
|
65
71
|
throw new Error(`OpenAI refresh failed: ${resp.status} ${body}`);
|
|
66
72
|
}
|
|
67
73
|
const data = await resp.json();
|
|
68
74
|
const newRefreshToken = data.refresh_token ?? creds.refreshToken;
|
|
69
|
-
|
|
75
|
+
const rotated = data.refresh_token !== null && data.refresh_token !== void 0 && data.refresh_token !== creds.refreshToken;
|
|
76
|
+
if (rotated) logger.info(`refresh_token rotated for token ${token.name}`);
|
|
70
77
|
const updatedCreds = {
|
|
71
78
|
...creds,
|
|
72
79
|
accessToken: data.access_token,
|
|
@@ -74,13 +81,18 @@ async function doRefresh(tokenId) {
|
|
|
74
81
|
accessTokenExpiresAt: data.expires_in ? Date.now() + data.expires_in * 1e3 : creds.accessTokenExpiresAt,
|
|
75
82
|
...data.id_token ? { idToken: data.id_token } : {}
|
|
76
83
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
try {
|
|
85
|
+
await TokenModel.save([{
|
|
86
|
+
id: tokenId,
|
|
87
|
+
provider: "openai",
|
|
88
|
+
credentials: updatedCreds,
|
|
89
|
+
name: token.name
|
|
90
|
+
}]);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
logger.error(`OpenAI refresh: DB save FAILED after rotation(rotated=${rotated}) token=${token.name}(id=${tokenId}) — 옛 refresh_token 폐기됨, DB 미반영 → 토큰 사망 위험. err=${String(e)}`);
|
|
93
|
+
throw e;
|
|
94
|
+
}
|
|
95
|
+
logger.info(`token ${token.name} refreshed successfully (rotated=${rotated})`);
|
|
84
96
|
return {
|
|
85
97
|
accessToken: data.access_token,
|
|
86
98
|
chatgptAccountId: creds.accountId,
|
|
@@ -90,4 +102,4 @@ async function doRefresh(tokenId) {
|
|
|
90
102
|
//#endregion
|
|
91
103
|
export { handleChatgptAuthTokensRefresh };
|
|
92
104
|
|
|
93
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXJlZnJlc2guanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXJlZnJlc2gudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUkgY2hhdGdwdEF1dGhUb2tlbnMgcmVmcmVzaCBoYW5kbGVyLlxuICpcbiAqIC0gY29kZXggYXBwLXNlcnZlciDqsIAgNDAxIOuwm+ycvOuptCBgYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoYCBzZXJ2ZXItcmVxdWVzdCDrpbwg67O064OEXG4gKiAtIHFncmlkIOqwgCBEQiDsnZggcmVmcmVzaF90b2tlbiDsnLzroZwg7IOIIGFjY2Vzc190b2tlbiDsnYQg67Cc6riJ67Cb7JWEIOydkeuLtVxuICogLSBwZXItdG9rZW4gaW5mbGlnaHQgcHJvbWlzZSDroZwgY29uY3VycmVudCByZWZyZXNoIGRlZHVwXG4gKiAtIHJvdGF0aW9uIOqwkOyngDog7IOIIHJlZnJlc2hfdG9rZW4g7J6I7Jy866m0IERCIOymieyLnCDsl4XrjbDsnbTtirhcbiAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcblxuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJvcGVuYWktcmVmcmVzaFwiXSk7XG5cbmltcG9ydCB7IE9QRU5BSV9DTElFTlRfSUQsIE9QRU5BSV9UT0tFTl9VUkwgfSBmcm9tIFwiLi9vcGVuYWktY29uc3RhbnRzXCI7XG5cbi8vIHBlci10b2tlbiBpbmZsaWdodCBwcm9taXNlIGRlZHVwICsgbWluaW11bSBpbnRlcnZhbFxuY29uc3QgaW5mbGlnaHRSZWZyZXNoID0gbmV3IE1hcDxudW1iZXIsIFByb21pc2U8UmVmcmVzaFJlc3VsdD4+KCk7XG5jb25zdCBsYXN0UmVmcmVzaFRpbWUgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuY29uc3QgUkVGUkVTSF9NSU5fSU5URVJWQUxfTVMgPSA1XzAwMDtcblxuaW50ZXJmYWNlIFJlZnJlc2hSZXN1bHQge1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICBjaGF0Z3B0QWNjb3VudElkOiBzdHJpbmc7XG4gIGNoYXRncHRQbGFuVHlwZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkOiBudW1iZXIpOiBQcm9taXNlPFJlZnJlc2hSZXN1bHQ+IHtcbiAgY29uc3QgZXhpc3RpbmcgPSBpbmZsaWdodFJlZnJlc2guZ2V0KHRva2VuSWQpO1xuICBpZiAoZXhpc3RpbmcpIHtcbiAgICBsb2dnZXIuaW5mbyhgcmVmcmVzaCBkZWR1cCBmb3IgdG9rZW4gJHt0b2tlbklkfWApO1xuICAgIHJldHVybiBleGlzdGluZztcbiAgfVxuXG4gIGNvbnN0IGxhc3RBdCA9IGxhc3RSZWZyZXNoVGltZS5nZXQodG9rZW5JZCkgPz8gMDtcbiAgaWYgKERhdGUubm93KCkgLSBsYXN0QXQgPCBSRUZSRVNIX01JTl9JTlRFUlZBTF9NUykge1xuICAgIGxvZ2dlci5pbmZvKGByZWZyZXNoIHRvbyBzb29uIGZvciB0b2tlbiAke3Rva2VuSWR9LCByZWFkaW5nIGN1cnJlbnQgY3JlZHMgZnJvbSBEQmApO1xuICAgIHJldHVybiByZWFkQ3VycmVudENyZWRzKHRva2VuSWQpO1xuICB9XG5cbiAgbGFzdFJlZnJlc2hUaW1lLnNldCh0b2tlbklkLCBEYXRlLm5vdygpKTtcbiAgY29uc3QgcHJvbWlzZSA9IGRvUmVmcmVzaCh0b2tlbklkKTtcbiAgaW5mbGlnaHRSZWZyZXNoLnNldCh0b2tlbklkLCBwcm9taXNlKTtcblxuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBwcm9taXNlO1xuICB9IGZpbmFsbHkge1xuICAgIGluZmxpZ2h0UmVmcmVzaC5kZWxldGUodG9rZW5JZCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZEN1cnJlbnRDcmVkcyh0b2tlbklkOiBudW1iZXIpOiBQcm9taXNlPFJlZnJlc2hSZXN1bHQ+IHtcbiAgY29uc3QgdG9rZW4gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRPbmUoXCJBXCIsIHsgaWQ6IHRva2VuSWQgfSk7XG4gIGlmICghdG9rZW4gfHwgdG9rZW4ucHJvdmlkZXIgIT09IFwib3BlbmFpXCIpIHRocm93IG5ldyBFcnJvcihgdG9rZW4gJHt0b2tlbklkfSBub3QgZm91bmRgKTtcbiAgY29uc3QgY3JlZHMgPSB0b2tlbi5jcmVkZW50aWFscyBhcyBPcGVuQUlDcmVkZW50aWFscztcbiAgcmV0dXJuIHtcbiAgICBhY2Nlc3NUb2tlbjogY3JlZHMuYWNjZXNzVG9rZW4sXG4gICAgY2hhdGdwdEFjY291bnRJZDogY3JlZHMuYWNjb3VudElkLFxuICAgIGNoYXRncHRQbGFuVHlwZTogY3JlZHMucGxhblR5cGUsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRvUmVmcmVzaCh0b2tlbklkOiBudW1iZXIpOiBQcm9taXNlPFJlZnJlc2hSZXN1bHQ+IHtcbiAgY29uc3QgdG9rZW4gPSBhd2FpdCBUb2tlbk1vZGVsLmZpbmRPbmUoXCJBXCIsIHsgaWQ6IHRva2VuSWQgfSk7XG4gIGlmICghdG9rZW4gfHwgdG9rZW4ucHJvdmlkZXIgIT09IFwib3BlbmFpXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gbm90IGZvdW5kIG9yIG5vdCBvcGVuYWlgKTtcbiAgfVxuXG4gIGNvbnN0IGNyZWRzID0gdG9rZW4uY3JlZGVudGlhbHMgYXMgT3BlbkFJQ3JlZGVudGlhbHM7XG4gIGlmICghY3JlZHMucmVmcmVzaFRva2VuKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB0b2tlbiAke3Rva2VuSWR9IGhhcyBubyByZWZyZXNoVG9rZW5gKTtcbiAgfVxuXG4gIGxvZ2dlci5pbmZvKGByZWZyZXNoaW5nIHRva2VuICR7dG9rZW4ubmFtZX0gKGlkPSR7dG9rZW5JZH0pYCk7XG5cbiAgY29uc3QgcmVzcCA9IGF3YWl0IGZldGNoKE9QRU5BSV9UT0tFTl9VUkwsIHtcbiAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgIGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiB9LFxuICAgIGJvZHk6IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgZ3JhbnRfdHlwZTogXCJyZWZyZXNoX3Rva2VuXCIsXG4gICAgICBjbGllbnRfaWQ6IE9QRU5BSV9DTElFTlRfSUQsXG4gICAgICByZWZyZXNoX3Rva2VuOiBjcmVkcy5yZWZyZXNoVG9rZW4sXG4gICAgfSksXG4gIH0pO1xuXG4gIGlmICghcmVzcC5vaykge1xuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZXNwLnRleHQoKS5jYXRjaCgoKSA9PiBcIlwiKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYE9wZW5BSSByZWZyZXNoIGZhaWxlZDogJHtyZXNwLnN0YXR1c30gJHtib2R5fWApO1xuICB9XG5cbiAgY29uc3QgZGF0YSA9IChhd2FpdCByZXNwLmpzb24oKSkgYXMge1xuICAgIGFjY2Vzc190b2tlbjogc3RyaW5nO1xuICAgIHJlZnJlc2hfdG9rZW4/OiBzdHJpbmc7XG4gICAgZXhwaXJlc19pbj86IG51bWJlcjtcbiAgICBpZF90b2tlbj86IHN0cmluZztcbiAgfTtcblxuICBjb25zdCBuZXdSZWZyZXNoVG9rZW4gPSBkYXRhLnJlZnJlc2hfdG9rZW4gPz8gY3JlZHMucmVmcmVzaFRva2VuO1xuICBjb25zdCByb3RhdGVkID1cbiAgICBkYXRhLnJlZnJlc2hfdG9rZW4gIT09IG51bGwgJiZcbiAgICBkYXRhLnJlZnJlc2hfdG9rZW4gIT09IHVuZGVmaW5lZCAmJlxuICAgIGRhdGEucmVmcmVzaF90b2tlbiAhPT0gY3JlZHMucmVmcmVzaFRva2VuO1xuICBpZiAocm90YXRlZCkge1xuICAgIGxvZ2dlci5pbmZvKGByZWZyZXNoX3Rva2VuIHJvdGF0ZWQgZm9yIHRva2VuICR7dG9rZW4ubmFtZX1gKTtcbiAgfVxuXG4gIGNvbnN0IHVwZGF0ZWRDcmVkczogT3BlbkFJQ3JlZGVudGlhbHMgPSB7XG4gICAgLi4uY3JlZHMsXG4gICAgYWNjZXNzVG9rZW46IGRhdGEuYWNjZXNzX3Rva2VuLFxuICAgIHJlZnJlc2hUb2tlbjogbmV3UmVmcmVzaFRva2VuLFxuICAgIGFjY2Vzc1Rva2VuRXhwaXJlc0F0OiBkYXRhLmV4cGlyZXNfaW5cbiAgICAgID8gRGF0ZS5ub3coKSArIGRhdGEuZXhwaXJlc19pbiAqIDEwMDBcbiAgICAgIDogY3JlZHMuYWNjZXNzVG9rZW5FeHBpcmVzQXQsXG4gICAgLi4uKGRhdGEuaWRfdG9rZW4gPyB7IGlkVG9rZW46IGRhdGEuaWRfdG9rZW4gfSA6IHt9KSxcbiAgfTtcblxuICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgIHtcbiAgICAgIGlkOiB0b2tlbklkLFxuICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICBjcmVkZW50aWFsczogdXBkYXRlZENyZWRzLFxuICAgICAgbmFtZTogdG9rZW4ubmFtZSxcbiAgICB9LFxuICBdKTtcblxuICBsb2dnZXIuaW5mbyhgdG9rZW4gJHt0b2tlbi5uYW1lfSByZWZyZXNoZWQgc3VjY2Vzc2Z1bGx5YCk7XG5cbiAgcmV0dXJuIHtcbiAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgY2hhdGdwdEFjY291bnRJZDogY3JlZHMuYWNjb3VudElkLFxuICAgIGNoYXRncHRQbGFuVHlwZTogY3JlZHMucGxhblR5cGUsXG4gIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFhQSxNQUFNLFNBQVMsVUFB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
|
|
105
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXJlZnJlc2guanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXJlZnJlc2gudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUkgY2hhdGdwdEF1dGhUb2tlbnMgcmVmcmVzaCBoYW5kbGVyLlxuICpcbiAqIC0gY29kZXggYXBwLXNlcnZlciDqsIAgNDAxIOuwm+ycvOuptCBgYWNjb3VudC9jaGF0Z3B0QXV0aFRva2Vucy9yZWZyZXNoYCBzZXJ2ZXItcmVxdWVzdCDrpbwg67O064OEXG4gKiAtIHFncmlkIOqwgCBEQiDsnZggcmVmcmVzaF90b2tlbiDsnLzroZwg7IOIIGFjY2Vzc190b2tlbiDsnYQg67Cc6riJ67Cb7JWEIOydkeuLtVxuICogLSBwZXItdG9rZW4gaW5mbGlnaHQgcHJvbWlzZSDroZwgY29uY3VycmVudCByZWZyZXNoIGRlZHVwXG4gKiAtIHJvdGF0aW9uIOqwkOyngDog7IOIIHJlZnJlc2hfdG9rZW4g7J6I7Jy866m0IERCIOymieyLnCDsl4XrjbDsnbTtirhcbiAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcblxuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJvcGVuYWktcmVmcmVzaFwiXSk7XG5cbmltcG9ydCB7IE9QRU5BSV9DTElFTlRfSUQsIE9QRU5BSV9UT0tFTl9VUkwgfSBmcm9tIFwiLi9vcGVuYWktY29uc3RhbnRzXCI7XG5cbi8vIHBlci10b2tlbiBpbmZsaWdodCBwcm9taXNlIGRlZHVwICsgbWluaW11bSBpbnRlcnZhbFxuY29uc3QgaW5mbGlnaHRSZWZyZXNoID0gbmV3IE1hcDxudW1iZXIsIFByb21pc2U8UmVmcmVzaFJlc3VsdD4+KCk7XG5jb25zdCBsYXN0UmVmcmVzaFRpbWUgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuY29uc3QgUkVGUkVTSF9NSU5fSU5URVJWQUxfTVMgPSA1XzAwMDtcblxuaW50ZXJmYWNlIFJlZnJlc2hSZXN1bHQge1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nO1xuICBjaGF0Z3B0QWNjb3VudElkOiBzdHJpbmc7XG4gIGNoYXRncHRQbGFuVHlwZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUNoYXRncHRBdXRoVG9rZW5zUmVmcmVzaCh0b2tlbklkOiBudW1iZXIpOiBQcm9taXNlPFJlZnJlc2hSZXN1bHQ+IHtcbiAgbG9nZ2VyLmluZm8oYHJlZnJlc2ggcmVxdWVzdGVkIGZvciB0b2tlbiAke3Rva2VuSWR9IChwaWQ9JHtwcm9jZXNzLnBpZH0pYCk7XG4gIGNvbnN0IGV4aXN0aW5nID0gaW5mbGlnaHRSZWZyZXNoLmdldCh0b2tlbklkKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgbG9nZ2VyLmluZm8oYHJlZnJlc2ggZGVkdXAgZm9yIHRva2VuICR7dG9rZW5JZH1gKTtcbiAgICByZXR1cm4gZXhpc3Rpbmc7XG4gIH1cblxuICBjb25zdCBsYXN0QXQgPSBsYXN0UmVmcmVzaFRpbWUuZ2V0KHRva2VuSWQpID8/IDA7XG4gIGlmIChEYXRlLm5vdygpIC0gbGFzdEF0IDwgUkVGUkVTSF9NSU5fSU5URVJWQUxfTVMpIHtcbiAgICBsb2dnZXIuaW5mbyhgcmVmcmVzaCB0b28gc29vbiBmb3IgdG9rZW4gJHt0b2tlbklkfSwgcmVhZGluZyBjdXJyZW50IGNyZWRzIGZyb20gREJgKTtcbiAgICByZXR1cm4gcmVhZEN1cnJlbnRDcmVkcyh0b2tlbklkKTtcbiAgfVxuXG4gIGxhc3RSZWZyZXNoVGltZS5zZXQodG9rZW5JZCwgRGF0ZS5ub3coKSk7XG4gIGNvbnN0IHByb21pc2UgPSBkb1JlZnJlc2godG9rZW5JZCk7XG4gIGluZmxpZ2h0UmVmcmVzaC5zZXQodG9rZW5JZCwgcHJvbWlzZSk7XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcHJvbWlzZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpbmZsaWdodFJlZnJlc2guZGVsZXRlKHRva2VuSWQpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRDdXJyZW50Q3JlZHModG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxSZWZyZXNoUmVzdWx0PiB7XG4gIGNvbnN0IHRva2VuID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kT25lKFwiQVwiLCB7IGlkOiB0b2tlbklkIH0pO1xuICBpZiAoIXRva2VuIHx8IHRva2VuLnByb3ZpZGVyICE9PSBcIm9wZW5haVwiKSB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gbm90IGZvdW5kYCk7XG4gIGNvbnN0IGNyZWRzID0gdG9rZW4uY3JlZGVudGlhbHMgYXMgT3BlbkFJQ3JlZGVudGlhbHM7XG4gIHJldHVybiB7XG4gICAgYWNjZXNzVG9rZW46IGNyZWRzLmFjY2Vzc1Rva2VuLFxuICAgIGNoYXRncHRBY2NvdW50SWQ6IGNyZWRzLmFjY291bnRJZCxcbiAgICBjaGF0Z3B0UGxhblR5cGU6IGNyZWRzLnBsYW5UeXBlLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBkb1JlZnJlc2godG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxSZWZyZXNoUmVzdWx0PiB7XG4gIGNvbnN0IHRva2VuID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kT25lKFwiQVwiLCB7IGlkOiB0b2tlbklkIH0pO1xuICBpZiAoIXRva2VuIHx8IHRva2VuLnByb3ZpZGVyICE9PSBcIm9wZW5haVwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB0b2tlbiAke3Rva2VuSWR9IG5vdCBmb3VuZCBvciBub3Qgb3BlbmFpYCk7XG4gIH1cblxuICBjb25zdCBjcmVkcyA9IHRva2VuLmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzO1xuICBpZiAoIWNyZWRzLnJlZnJlc2hUb2tlbikge1xuICAgIHRocm93IG5ldyBFcnJvcihgdG9rZW4gJHt0b2tlbklkfSBoYXMgbm8gcmVmcmVzaFRva2VuYCk7XG4gIH1cblxuICBsb2dnZXIuaW5mbyhgcmVmcmVzaGluZyB0b2tlbiAke3Rva2VuLm5hbWV9IChpZD0ke3Rva2VuSWR9KWApO1xuXG4gIGNvbnN0IHJlc3AgPSBhd2FpdCBmZXRjaChPUEVOQUlfVE9LRU5fVVJMLCB7XG4gICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgfSxcbiAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGdyYW50X3R5cGU6IFwicmVmcmVzaF90b2tlblwiLFxuICAgICAgY2xpZW50X2lkOiBPUEVOQUlfQ0xJRU5UX0lELFxuICAgICAgcmVmcmVzaF90b2tlbjogY3JlZHMucmVmcmVzaFRva2VuLFxuICAgIH0pLFxuICB9KTtcblxuICBpZiAoIXJlc3Aub2spIHtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzcC50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgLy8gNDAxIOuzuOusuOydmCBlcnJvciDsvZTrk5zqsIAg7Yag7YGwIOyCrOunneydmCDqsrDsoJXsoIEg7IKs7J247J2064ukLlxuICAgIC8vICAgcmVmcmVzaF90b2tlbl9leHBpcmVkICAgICDihpIgcmVmcmVzaF90b2tlbiDsnpDssrQg66eM66OMXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX3JldXNlZCAgICAgIOKGkiDsnbTrr7gg7IKs7Jqp65CcKO2ajOyghCDtj5DquLDrkJwpIHJlZnJlc2hfdG9rZW4g7J6s7IKs7JqpIOKGkiDtjKjrsIDrpqwg66y07Zqo7ZmUXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX2ludmFsaWRhdGVkIOKGkiDshJzrsoTsuKEgcmV2b2tlXG4gICAgLy8g7JyEIDPqsJzripQg66qo65GQIOyYgeq1rCDsi6TtjKguIOyerOuTseuhnSDsmbgg67O16rWsIOu2iOqwgC5cbiAgICBsZXQgZXJyb3JDb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGVycm9yQ29kZSA9IChKU09OLnBhcnNlKGJvZHkpIGFzIHsgZXJyb3I/OiBzdHJpbmcgfSkuZXJyb3I7XG4gICAgfSBjYXRjaCB7fVxuICAgIGxvZ2dlci5lcnJvcihcbiAgICAgIGBPcGVuQUkgcmVmcmVzaCBGQUlMRUQgdG9rZW49JHt0b2tlbi5uYW1lfShpZD0ke3Rva2VuSWR9KSBzdGF0dXM9JHtyZXNwLnN0YXR1c30gYCArXG4gICAgICAgIGBjb2RlPSR7ZXJyb3JDb2RlID8/IFwiP1wifSBib2R5PSR7Ym9keX1gLFxuICAgICk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBPcGVuQUkgcmVmcmVzaCBmYWlsZWQ6ICR7cmVzcC5zdGF0dXN9ICR7Ym9keX1gKTtcbiAgfVxuXG4gIGNvbnN0IGRhdGEgPSAoYXdhaXQgcmVzcC5qc29uKCkpIGFzIHtcbiAgICBhY2Nlc3NfdG9rZW46IHN0cmluZztcbiAgICByZWZyZXNoX3Rva2VuPzogc3RyaW5nO1xuICAgIGV4cGlyZXNfaW4/OiBudW1iZXI7XG4gICAgaWRfdG9rZW4/OiBzdHJpbmc7XG4gIH07XG5cbiAgY29uc3QgbmV3UmVmcmVzaFRva2VuID0gZGF0YS5yZWZyZXNoX3Rva2VuID8/IGNyZWRzLnJlZnJlc2hUb2tlbjtcbiAgY29uc3Qgcm90YXRlZCA9XG4gICAgZGF0YS5yZWZyZXNoX3Rva2VuICE9PSBudWxsICYmXG4gICAgZGF0YS5yZWZyZXNoX3Rva2VuICE9PSB1bmRlZmluZWQgJiZcbiAgICBkYXRhLnJlZnJlc2hfdG9rZW4gIT09IGNyZWRzLnJlZnJlc2hUb2tlbjtcbiAgaWYgKHJvdGF0ZWQpIHtcbiAgICBsb2dnZXIuaW5mbyhgcmVmcmVzaF90b2tlbiByb3RhdGVkIGZvciB0b2tlbiAke3Rva2VuLm5hbWV9YCk7XG4gIH1cblxuICBjb25zdCB1cGRhdGVkQ3JlZHM6IE9wZW5BSUNyZWRlbnRpYWxzID0ge1xuICAgIC4uLmNyZWRzLFxuICAgIGFjY2Vzc1Rva2VuOiBkYXRhLmFjY2Vzc190b2tlbixcbiAgICByZWZyZXNoVG9rZW46IG5ld1JlZnJlc2hUb2tlbixcbiAgICBhY2Nlc3NUb2tlbkV4cGlyZXNBdDogZGF0YS5leHBpcmVzX2luXG4gICAgICA/IERhdGUubm93KCkgKyBkYXRhLmV4cGlyZXNfaW4gKiAxMDAwXG4gICAgICA6IGNyZWRzLmFjY2Vzc1Rva2VuRXhwaXJlc0F0LFxuICAgIC4uLihkYXRhLmlkX3Rva2VuID8geyBpZFRva2VuOiBkYXRhLmlkX3Rva2VuIH0gOiB7fSksXG4gIH07XG5cbiAgLy8g7ZqM7KCEKHJvdGF0ZWQp7J20IOydvOyWtOuCrOuKlOuNsCDsnbQgc2F2ZSDqsIAg7Iuk7Yyo7ZWY66m0LCBPcGVuQUkg7Kq9IOyYmyByZWZyZXNoX3Rva2VuIOydgCDsnbTrr7hcbiAgLy8g7Y+Q6riw65CcIOyDge2DnOyXkOyEnCBEQiDsl5DripQg7JibIO2GoO2BsOydtCDrgqjripTri6Qg4oaSIOuLpOydjCByZWZyZXNoIOqwgCByZWZyZXNoX3Rva2VuX3JldXNlZCDroZxcbiAgLy8g7JiB6rWsIOyCrOunnS4g7J20IOq1rOqwhCDsi6TtjKjripQg7Yag7YGwIOyCrOunneydmCDsp4HsoJEg7JuQ7J247J2066+A66GcIOuwmOuTnOyLnCDtgazqsowg64Ko6ri064ukLlxuICB0cnkge1xuICAgIGF3YWl0IFRva2VuTW9kZWwuc2F2ZShbXG4gICAgICB7XG4gICAgICAgIGlkOiB0b2tlbklkLFxuICAgICAgICBwcm92aWRlcjogXCJvcGVuYWlcIixcbiAgICAgICAgY3JlZGVudGlhbHM6IHVwZGF0ZWRDcmVkcyxcbiAgICAgICAgbmFtZTogdG9rZW4ubmFtZSxcbiAgICAgIH0sXG4gICAgXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2dnZXIuZXJyb3IoXG4gICAgICBgT3BlbkFJIHJlZnJlc2g6IERCIHNhdmUgRkFJTEVEIGFmdGVyIHJvdGF0aW9uKHJvdGF0ZWQ9JHtyb3RhdGVkfSkgYCArXG4gICAgICAgIGB0b2tlbj0ke3Rva2VuLm5hbWV9KGlkPSR7dG9rZW5JZH0pIOKAlCDsmJsgcmVmcmVzaF90b2tlbiDtj5DquLDrkKgsIERCIOuvuOuwmOyYgSDihpIg7Yag7YGwIOyCrOunnSDsnITtl5guIGVycj0ke1N0cmluZyhlKX1gLFxuICAgICk7XG4gICAgdGhyb3cgZTtcbiAgfVxuXG4gIGxvZ2dlci5pbmZvKGB0b2tlbiAke3Rva2VuLm5hbWV9IHJlZnJlc2hlZCBzdWNjZXNzZnVsbHkgKHJvdGF0ZWQ9JHtyb3RhdGVkfSlgKTtcblxuICByZXR1cm4ge1xuICAgIGFjY2Vzc1Rva2VuOiBkYXRhLmFjY2Vzc190b2tlbixcbiAgICBjaGF0Z3B0QWNjb3VudElkOiBjcmVkcy5hY2NvdW50SWQsXG4gICAgY2hhdGdwdFBsYW5UeXBlOiBjcmVkcy5wbGFuVHlwZSxcbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQWFBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxpQkFBaUIsQ0FBQztBQUtyRCxNQUFNLGtDQUFrQixJQUFJLEtBQXFDO0FBQ2pFLE1BQU0sa0NBQWtCLElBQUksS0FBcUI7QUFDakQsTUFBTSwwQkFBMEI7QUFRaEMsZUFBc0IsK0JBQStCLFNBQXlDO0FBQzVGLFFBQU8sS0FBSywrQkFBK0IsUUFBUSxRQUFRLFFBQVEsSUFBSSxHQUFHO0NBQzFFLE1BQU0sV0FBVyxnQkFBZ0IsSUFBSSxRQUFRO0FBQzdDLEtBQUksVUFBVTtBQUNaLFNBQU8sS0FBSywyQkFBMkIsVUFBVTtBQUNqRCxTQUFPOztDQUdULE1BQU0sU0FBUyxnQkFBZ0IsSUFBSSxRQUFRLElBQUk7QUFDL0MsS0FBSSxLQUFLLEtBQUssR0FBRyxTQUFTLHlCQUF5QjtBQUNqRCxTQUFPLEtBQUssOEJBQThCLFFBQVEsaUNB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
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { decideConvRouting, systemHash } from "./conv-routing";
|
|
4
|
+
import { type QueryInput } from "./qgrid.types";
|
|
5
|
+
|
|
6
|
+
function input(overrides: Partial<QueryInput> = {}): QueryInput {
|
|
7
|
+
return {
|
|
8
|
+
prompt: "hello",
|
|
9
|
+
...overrides,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe("decideConvRouting", () => {
|
|
14
|
+
it("일반 cold 첫 turn 은 기존 prompt 를 실행 input 으로 유지한다", () => {
|
|
15
|
+
const decision = decideConvRouting(input({ prompt: "first turn" }));
|
|
16
|
+
|
|
17
|
+
expect(decision.reuse).toBeUndefined();
|
|
18
|
+
expect(decision.reuseInput).toBeUndefined();
|
|
19
|
+
expect(decision.coldInput).toEqual([{ type: "text", text: "first turn", text_elements: [] }]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("tool result follow-up cold fallback 도 continuation 을 실행 input 으로 담는다", () => {
|
|
23
|
+
const decision = decideConvRouting(
|
|
24
|
+
input({
|
|
25
|
+
prompt: "",
|
|
26
|
+
history: JSON.stringify([
|
|
27
|
+
{
|
|
28
|
+
type: "function_call",
|
|
29
|
+
name: "getWeather",
|
|
30
|
+
arguments: '{"city":"Seoul"}',
|
|
31
|
+
call_id: "call_1",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: "function_call_output",
|
|
35
|
+
call_id: "call_1",
|
|
36
|
+
output: "22C and clear",
|
|
37
|
+
},
|
|
38
|
+
]),
|
|
39
|
+
toolResults: [
|
|
40
|
+
{
|
|
41
|
+
toolCallId: "call_1",
|
|
42
|
+
toolName: "getWeather",
|
|
43
|
+
output: "22C and clear",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(decision.reuse).toBeUndefined();
|
|
50
|
+
expect(decision.coldHistory).toHaveLength(2);
|
|
51
|
+
expect(decision.coldInput).toEqual([
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: "Tool result for call call_1 (getWeather): 22C and clear\n\nNow continue answering the user's request using these results.",
|
|
55
|
+
text_elements: [],
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("reuse 가능한 tool result follow-up 은 reuseInput 과 coldInput 이 같은 continuation 을 쓴다", () => {
|
|
61
|
+
const decision = decideConvRouting(
|
|
62
|
+
input({
|
|
63
|
+
prompt: "",
|
|
64
|
+
system: "same",
|
|
65
|
+
runContext: {
|
|
66
|
+
threadCoord: {
|
|
67
|
+
workerId: 1,
|
|
68
|
+
threadId: "S1",
|
|
69
|
+
epoch: 0,
|
|
70
|
+
systemHash: systemHash("same"),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
toolResults: [{ toolCallId: "call_1", output: "ok" }],
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(decision.reuse).toEqual({ workerId: 1, threadId: "S1", epoch: 0 });
|
|
78
|
+
expect(decision.reuseInput).toEqual(decision.coldInput);
|
|
79
|
+
expect(decision.coldInput[0]).toMatchObject({
|
|
80
|
+
type: "text",
|
|
81
|
+
text: expect.stringContaining("Tool result for call call_1"),
|
|
82
|
+
});
|
|
83
|
+
expect(decision.coldInput[0]).not.toMatchObject({ type: "text", text: "" });
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -68,8 +68,9 @@ export function decideConvRouting(input: QueryInput): ConvDecision {
|
|
|
68
68
|
: undefined,
|
|
69
69
|
// 재사용 turn 은 delta(마지막 user/tool 결과)만 — thread 가 이미 이전 turn 들을 누적.
|
|
70
70
|
reuseInput: eligible ? buildDeltaInput(input) : undefined,
|
|
71
|
-
// 첫 turn / 폴백: 전체 prompt + history inject.
|
|
72
|
-
|
|
71
|
+
// 첫 turn / 폴백: 전체 prompt + history inject. tool 결과 follow-up 이 cold 로 떨어져도
|
|
72
|
+
// 실행 user 줄에는 "이 결과로 계속 답하라"는 continuation 이 들어가야 한다.
|
|
73
|
+
coldInput: buildDeltaInput(input),
|
|
73
74
|
coldHistory: history,
|
|
74
75
|
systemHash: sysHash,
|
|
75
76
|
};
|