@automagik/omni 2.260423.6 → 2.260423.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +257 -171
- package/dist/server/index.js +1090 -1004
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -35354,6 +35354,81 @@ var init_agno_client = __esm(() => {
|
|
|
35354
35354
|
init_types6();
|
|
35355
35355
|
});
|
|
35356
35356
|
|
|
35357
|
+
// ../core/src/providers/claude-code-executable.ts
|
|
35358
|
+
import { existsSync as nodeExistsSync } from "fs";
|
|
35359
|
+
import { createRequire } from "module";
|
|
35360
|
+
function archLinkerNames(arch) {
|
|
35361
|
+
if (arch === "x64")
|
|
35362
|
+
return { musl: "x86_64", glibc: "x86-64" };
|
|
35363
|
+
if (arch === "arm64")
|
|
35364
|
+
return { musl: "aarch64", glibc: "aarch64" };
|
|
35365
|
+
return null;
|
|
35366
|
+
}
|
|
35367
|
+
function muslLinkerPath(muslName) {
|
|
35368
|
+
return `/lib/ld-musl-${muslName}.so.1`;
|
|
35369
|
+
}
|
|
35370
|
+
function glibcLinkerCandidates(glibcName, muslName, nodeArch) {
|
|
35371
|
+
const suffix = nodeArch === "arm64" ? "1" : "2";
|
|
35372
|
+
const fileName = `ld-linux-${glibcName}.so.${suffix}`;
|
|
35373
|
+
return [`/lib64/${fileName}`, `/lib/${muslName}-linux-gnu/${fileName}`, `/lib/${fileName}`];
|
|
35374
|
+
}
|
|
35375
|
+
function detectLinuxLibc(options = {}) {
|
|
35376
|
+
const platform = options.platform ?? process.platform;
|
|
35377
|
+
if (platform !== "linux")
|
|
35378
|
+
return "unknown";
|
|
35379
|
+
const arch = options.arch ?? process.arch;
|
|
35380
|
+
const names = archLinkerNames(arch);
|
|
35381
|
+
if (!names)
|
|
35382
|
+
return "unknown";
|
|
35383
|
+
const exists = options.existsSync ?? nodeExistsSync;
|
|
35384
|
+
if (exists(muslLinkerPath(names.musl)))
|
|
35385
|
+
return "musl";
|
|
35386
|
+
if (glibcLinkerCandidates(names.glibc, names.musl, arch).some(exists))
|
|
35387
|
+
return "glibc";
|
|
35388
|
+
return "unknown";
|
|
35389
|
+
}
|
|
35390
|
+
function resolveClaudeCodeExecutable(options = {}) {
|
|
35391
|
+
const platform = options.platform ?? process.platform;
|
|
35392
|
+
if (platform !== "linux")
|
|
35393
|
+
return;
|
|
35394
|
+
const libc = options.libc ?? detectLinuxLibc({ platform, arch: options.arch });
|
|
35395
|
+
if (libc === "unknown")
|
|
35396
|
+
return;
|
|
35397
|
+
const arch = options.arch ?? process.arch;
|
|
35398
|
+
if (arch !== "x64" && arch !== "arm64")
|
|
35399
|
+
return;
|
|
35400
|
+
const suffix = libc === "musl" ? `-${arch}-musl` : `-${arch}`;
|
|
35401
|
+
const specifier = `@anthropic-ai/claude-agent-sdk-linux${suffix}/claude`;
|
|
35402
|
+
const resolve2 = options.resolve ?? createRequire(import.meta.url).resolve;
|
|
35403
|
+
try {
|
|
35404
|
+
const resolved = resolve2(specifier);
|
|
35405
|
+
log6.debug("Resolved Claude Code executable for host libc", { libc, arch, resolved });
|
|
35406
|
+
return resolved;
|
|
35407
|
+
} catch (error2) {
|
|
35408
|
+
log6.debug("Claude Code subpackage not installed; falling back to SDK default", {
|
|
35409
|
+
libc,
|
|
35410
|
+
arch,
|
|
35411
|
+
specifier,
|
|
35412
|
+
error: String(error2)
|
|
35413
|
+
});
|
|
35414
|
+
return;
|
|
35415
|
+
}
|
|
35416
|
+
}
|
|
35417
|
+
function describeClaudeCodeStartupError(error2, options = {}) {
|
|
35418
|
+
const raw2 = String(error2);
|
|
35419
|
+
const platform = options.platform ?? process.platform;
|
|
35420
|
+
const isStartupCrash = /process exited with code 1/i.test(raw2);
|
|
35421
|
+
if (!isStartupCrash || platform !== "linux")
|
|
35422
|
+
return raw2;
|
|
35423
|
+
const configuredHint = options.explicitExecutablePath ? `Configured pathToClaudeCodeExecutable=${options.explicitExecutablePath} did not launch \u2014 verify the binary is executable on this host.` : "Set `pathToClaudeCodeExecutable` on the provider to the correct SDK binary for this host, " + "or remove the mismatched optional subpackage " + "(e.g. `bun remove @anthropic-ai/claude-agent-sdk-linux-x64-musl` on glibc).";
|
|
35424
|
+
return `${raw2} \u2014 Claude Code binary failed to start. This is typically a glibc/musl ABI mismatch: the SDK resolved an optional subpackage whose native binary cannot execute on this host's dynamic linker. ${configuredHint}`;
|
|
35425
|
+
}
|
|
35426
|
+
var log6;
|
|
35427
|
+
var init_claude_code_executable = __esm(() => {
|
|
35428
|
+
init_logger();
|
|
35429
|
+
log6 = createLogger("provider:claude-code:libc");
|
|
35430
|
+
});
|
|
35431
|
+
|
|
35357
35432
|
// ../../node_modules/.bun/@anthropic-ai+claude-agent-sdk@0.2.63+27912429049419a2/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
|
|
35358
35433
|
var exports_sdk = {};
|
|
35359
35434
|
__export(exports_sdk, {
|
|
@@ -49449,7 +49524,7 @@ function processRunMessage(message2, acc, startTime) {
|
|
|
49449
49524
|
const errors2 = message2.errors ?? [];
|
|
49450
49525
|
const content = errors2.join(`
|
|
49451
49526
|
`) || `Agent error: ${message2.subtype}`;
|
|
49452
|
-
|
|
49527
|
+
log7.error("Claude Code agent error", { subtype: message2.subtype, errors: errors2, sessionId: acc.sessionId });
|
|
49453
49528
|
return {
|
|
49454
49529
|
content,
|
|
49455
49530
|
runId: crypto.randomUUID(),
|
|
@@ -49504,6 +49579,10 @@ function buildQueryOptions(config2, request, opts) {
|
|
|
49504
49579
|
options.model = config2.model;
|
|
49505
49580
|
if (config2.systemPrompt)
|
|
49506
49581
|
options.systemPrompt = config2.systemPrompt;
|
|
49582
|
+
const executablePath = config2.pathToClaudeCodeExecutable ?? resolveClaudeCodeExecutable();
|
|
49583
|
+
if (executablePath) {
|
|
49584
|
+
options.pathToClaudeCodeExecutable = executablePath;
|
|
49585
|
+
}
|
|
49507
49586
|
if (config2.mcpServers) {
|
|
49508
49587
|
options.mcpServers = resolveMcpServers(config2.mcpServers, request.mcpUrlParams);
|
|
49509
49588
|
}
|
|
@@ -49540,7 +49619,7 @@ async function* generateStream(config2, request, flags, abortSignal, state) {
|
|
|
49540
49619
|
activeTextBlockIndices: new Map,
|
|
49541
49620
|
insideXmlThinking: false
|
|
49542
49621
|
};
|
|
49543
|
-
|
|
49622
|
+
log7.info("streamRun: starting", {
|
|
49544
49623
|
projectPath: config2.projectPath,
|
|
49545
49624
|
sessionId: request.sessionId,
|
|
49546
49625
|
model: config2.model,
|
|
@@ -49563,7 +49642,7 @@ async function* generateStream(config2, request, flags, abortSignal, state) {
|
|
|
49563
49642
|
if ("kind" in delta) {
|
|
49564
49643
|
state.sessionId = delta.sessionId;
|
|
49565
49644
|
state.metrics = delta.metrics;
|
|
49566
|
-
|
|
49645
|
+
log7.info(`streamRun: ${delta.kind}`, { sessionId: state.sessionId, durationMs: delta.metrics.durationMs });
|
|
49567
49646
|
yield delta.delta;
|
|
49568
49647
|
return;
|
|
49569
49648
|
}
|
|
@@ -49584,8 +49663,11 @@ async function* generateStream(config2, request, flags, abortSignal, state) {
|
|
|
49584
49663
|
yield { phase: "error", error: "Aborted" };
|
|
49585
49664
|
return;
|
|
49586
49665
|
}
|
|
49587
|
-
|
|
49588
|
-
|
|
49666
|
+
const annotated = describeClaudeCodeStartupError(error2, {
|
|
49667
|
+
explicitExecutablePath: config2.pathToClaudeCodeExecutable
|
|
49668
|
+
});
|
|
49669
|
+
log7.error("streamRun: threw", { error: annotated, sessionId: state.sessionId });
|
|
49670
|
+
yield { phase: "error", error: `Agent error: ${annotated}` };
|
|
49589
49671
|
}
|
|
49590
49672
|
}
|
|
49591
49673
|
|
|
@@ -49601,7 +49683,7 @@ class ClaudeCodeClient {
|
|
|
49601
49683
|
const { query } = await Promise.resolve().then(() => (init_sdk(), exports_sdk));
|
|
49602
49684
|
const startTime = Date.now();
|
|
49603
49685
|
const acc = { content: "", sessionId: "", costUsd: 0, inputTokens: 0, outputTokens: 0 };
|
|
49604
|
-
|
|
49686
|
+
log7.info("Running Claude Code agent", {
|
|
49605
49687
|
projectPath: this.config.projectPath,
|
|
49606
49688
|
sessionId: request.sessionId,
|
|
49607
49689
|
model: this.config.model
|
|
@@ -49616,9 +49698,12 @@ class ClaudeCodeClient {
|
|
|
49616
49698
|
return earlyReturn;
|
|
49617
49699
|
}
|
|
49618
49700
|
} catch (error2) {
|
|
49619
|
-
|
|
49701
|
+
const annotated = describeClaudeCodeStartupError(error2, {
|
|
49702
|
+
explicitExecutablePath: this.config.pathToClaudeCodeExecutable
|
|
49703
|
+
});
|
|
49704
|
+
log7.error("Claude Code agent threw", { error: annotated, sessionId: acc.sessionId });
|
|
49620
49705
|
return {
|
|
49621
|
-
content: `Agent error: ${
|
|
49706
|
+
content: `Agent error: ${annotated}`,
|
|
49622
49707
|
runId: crypto.randomUUID(),
|
|
49623
49708
|
sessionId: acc.sessionId,
|
|
49624
49709
|
status: "failed",
|
|
@@ -49626,7 +49711,7 @@ class ClaudeCodeClient {
|
|
|
49626
49711
|
};
|
|
49627
49712
|
}
|
|
49628
49713
|
const durationMs = Date.now() - startTime;
|
|
49629
|
-
|
|
49714
|
+
log7.info("Claude Code agent completed", {
|
|
49630
49715
|
sessionId: acc.sessionId,
|
|
49631
49716
|
durationMs,
|
|
49632
49717
|
costUsd: acc.costUsd,
|
|
@@ -49659,7 +49744,7 @@ class ClaudeCodeClient {
|
|
|
49659
49744
|
async* stream(request) {
|
|
49660
49745
|
const { query } = await Promise.resolve().then(() => (init_sdk(), exports_sdk));
|
|
49661
49746
|
let sessionId = "";
|
|
49662
|
-
|
|
49747
|
+
log7.info("Streaming Claude Code agent", {
|
|
49663
49748
|
projectPath: this.config.projectPath,
|
|
49664
49749
|
sessionId: request.sessionId
|
|
49665
49750
|
});
|
|
@@ -49676,7 +49761,7 @@ class ClaudeCodeClient {
|
|
|
49676
49761
|
}
|
|
49677
49762
|
}
|
|
49678
49763
|
} catch (error2) {
|
|
49679
|
-
|
|
49764
|
+
log7.error("Claude Code stream error", { error: String(error2), sessionId });
|
|
49680
49765
|
yield {
|
|
49681
49766
|
event: "RunCompleted",
|
|
49682
49767
|
isComplete: true,
|
|
@@ -49722,7 +49807,7 @@ function processStreamRunMessage(message2, acc, flags, startTime, currentSession
|
|
|
49722
49807
|
if (msg.type === "system" && msg.subtype === "compact_boundary") {
|
|
49723
49808
|
const trigger = msg.trigger ?? "auto";
|
|
49724
49809
|
const preTokens = msg.pre_tokens ?? 0;
|
|
49725
|
-
|
|
49810
|
+
log7.info("streamRun: compact_boundary", { trigger, preTokens, sessionId: currentSessionId });
|
|
49726
49811
|
acc.content += `
|
|
49727
49812
|
\uD83D\uDCE6 _Context compacted (${trigger}, ${preTokens} tokens before)_
|
|
49728
49813
|
`;
|
|
@@ -49737,10 +49822,11 @@ function processStreamRunMessage(message2, acc, flags, startTime, currentSession
|
|
|
49737
49822
|
function createClaudeCodeClient(config2) {
|
|
49738
49823
|
return new ClaudeCodeClient(config2);
|
|
49739
49824
|
}
|
|
49740
|
-
var
|
|
49825
|
+
var log7, THINKING_TAG_RE;
|
|
49741
49826
|
var init_claude_code_client = __esm(() => {
|
|
49742
49827
|
init_logger();
|
|
49743
|
-
|
|
49828
|
+
init_claude_code_executable();
|
|
49829
|
+
log7 = createLogger("provider:claude-code");
|
|
49744
49830
|
THINKING_TAG_RE = /<thinking>[\s\S]*?<\/thinking>\s*/g;
|
|
49745
49831
|
});
|
|
49746
49832
|
|
|
@@ -49770,7 +49856,7 @@ class AgnoAgentProvider {
|
|
|
49770
49856
|
message2 = `[Reaction: ${context.content.emoji} on message ${context.content.referencedMessageId ?? context.source.messageId}]`;
|
|
49771
49857
|
}
|
|
49772
49858
|
if (!message2) {
|
|
49773
|
-
|
|
49859
|
+
log8.debug("No content to send to agent", { traceId: context.traceId });
|
|
49774
49860
|
return {
|
|
49775
49861
|
parts: [],
|
|
49776
49862
|
metadata: {
|
|
@@ -49792,7 +49878,7 @@ class AgnoAgentProvider {
|
|
|
49792
49878
|
userId: context.sender.platformUserId,
|
|
49793
49879
|
timeoutMs: this.config.timeoutMs ?? 60000
|
|
49794
49880
|
};
|
|
49795
|
-
|
|
49881
|
+
log8.info("Triggering Agno agent", {
|
|
49796
49882
|
agentId: this.config.agentId,
|
|
49797
49883
|
agentType: this.config.agentType,
|
|
49798
49884
|
triggerType: context.type,
|
|
@@ -49803,7 +49889,7 @@ class AgnoAgentProvider {
|
|
|
49803
49889
|
|
|
49804
49890
|
`).map((p3) => p3.trim()).filter(Boolean) : [response.content.trim()].filter(Boolean);
|
|
49805
49891
|
const durationMs = Date.now() - startTime;
|
|
49806
|
-
|
|
49892
|
+
log8.info("Agno agent responded", {
|
|
49807
49893
|
agentId: this.config.agentId,
|
|
49808
49894
|
runId: response.runId,
|
|
49809
49895
|
parts: parts.length,
|
|
@@ -49827,10 +49913,10 @@ class AgnoAgentProvider {
|
|
|
49827
49913
|
return this.client.checkHealth();
|
|
49828
49914
|
}
|
|
49829
49915
|
}
|
|
49830
|
-
var
|
|
49916
|
+
var log8;
|
|
49831
49917
|
var init_agno_provider = __esm(() => {
|
|
49832
49918
|
init_logger();
|
|
49833
|
-
|
|
49919
|
+
log8 = createLogger("provider:agno");
|
|
49834
49920
|
});
|
|
49835
49921
|
|
|
49836
49922
|
// ../core/src/providers/claude-code-provider.ts
|
|
@@ -49916,15 +50002,15 @@ ${fileList}`;
|
|
|
49916
50002
|
async resolveSession(instanceId, internalSessionKey) {
|
|
49917
50003
|
if (!internalSessionKey || !instanceId)
|
|
49918
50004
|
return;
|
|
49919
|
-
|
|
50005
|
+
log9.debug("Session lookup", { internalKey: internalSessionKey, instanceId });
|
|
49920
50006
|
const existing = await this.sessionStorage.getSession(instanceId, internalSessionKey);
|
|
49921
50007
|
if (!existing) {
|
|
49922
|
-
|
|
50008
|
+
log9.debug("No session found in DB", { internalKey: internalSessionKey });
|
|
49923
50009
|
return;
|
|
49924
50010
|
}
|
|
49925
50011
|
const age = Date.now() - existing.lastUsedAt.getTime();
|
|
49926
50012
|
if (this.sessionTtlMs < Number.POSITIVE_INFINITY && age >= this.sessionTtlMs) {
|
|
49927
|
-
|
|
50013
|
+
log9.debug("Session expired", {
|
|
49928
50014
|
internalKey: internalSessionKey,
|
|
49929
50015
|
age: `${Math.round(age / 1000)}s`,
|
|
49930
50016
|
ttl: `${Math.round(this.sessionTtlMs / 1000)}s`
|
|
@@ -49932,7 +50018,7 @@ ${fileList}`;
|
|
|
49932
50018
|
await this.sessionStorage.deleteSession(instanceId, internalSessionKey);
|
|
49933
50019
|
return;
|
|
49934
50020
|
}
|
|
49935
|
-
|
|
50021
|
+
log9.debug("Resuming session from DB", {
|
|
49936
50022
|
internalKey: internalSessionKey,
|
|
49937
50023
|
claudeSessionId: existing.sessionId,
|
|
49938
50024
|
age: `${Math.round(age / 1000)}s`
|
|
@@ -49945,7 +50031,7 @@ ${fileList}`;
|
|
|
49945
50031
|
return null;
|
|
49946
50032
|
const internalSessionKey = context.sessionId;
|
|
49947
50033
|
const resolvedSessionId = await this.resolveSession(context.source.instanceId, internalSessionKey);
|
|
49948
|
-
|
|
50034
|
+
log9.debug("Session resolution", {
|
|
49949
50035
|
internalKey: internalSessionKey,
|
|
49950
50036
|
resolvedUuid: resolvedSessionId ?? "(new session)"
|
|
49951
50037
|
});
|
|
@@ -49953,7 +50039,7 @@ ${fileList}`;
|
|
|
49953
50039
|
}
|
|
49954
50040
|
async persistSession(instanceId, internalSessionKey, claudeSessionId) {
|
|
49955
50041
|
if (!internalSessionKey || !claudeSessionId || !instanceId) {
|
|
49956
|
-
|
|
50042
|
+
log9.warn("Session not stored", {
|
|
49957
50043
|
hasInternalKey: !!internalSessionKey,
|
|
49958
50044
|
hasResponseSessionId: !!claudeSessionId,
|
|
49959
50045
|
hasInstanceId: !!instanceId,
|
|
@@ -49964,7 +50050,7 @@ ${fileList}`;
|
|
|
49964
50050
|
}
|
|
49965
50051
|
const expiresAt = this.sessionTtlMs < Number.POSITIVE_INFINITY ? new Date(Date.now() + this.sessionTtlMs) : null;
|
|
49966
50052
|
await this.sessionStorage.upsertSession(instanceId, internalSessionKey, claudeSessionId, expiresAt);
|
|
49967
|
-
|
|
50053
|
+
log9.debug("Session stored in DB", {
|
|
49968
50054
|
internalKey: internalSessionKey,
|
|
49969
50055
|
claudeSessionId,
|
|
49970
50056
|
expiresAt: expiresAt?.toISOString() ?? "never"
|
|
@@ -49974,7 +50060,7 @@ ${fileList}`;
|
|
|
49974
50060
|
const startTime = Date.now();
|
|
49975
50061
|
const prepared = await this.prepareRequest(context);
|
|
49976
50062
|
if (!prepared) {
|
|
49977
|
-
|
|
50063
|
+
log9.debug("No content to send to Claude Code", { traceId: context.traceId });
|
|
49978
50064
|
return {
|
|
49979
50065
|
parts: [],
|
|
49980
50066
|
metadata: { runId: "", providerId: this.id, durationMs: Date.now() - startTime }
|
|
@@ -49991,7 +50077,7 @@ ${fileList}`;
|
|
|
49991
50077
|
env: buildOmniEnv(context),
|
|
49992
50078
|
...context.source.chatId ? { mcpUrlParams: { chat_id: context.source.chatId } } : {}
|
|
49993
50079
|
};
|
|
49994
|
-
|
|
50080
|
+
log9.info("Triggering Claude Code agent", {
|
|
49995
50081
|
triggerType: context.type,
|
|
49996
50082
|
traceId: context.traceId
|
|
49997
50083
|
});
|
|
@@ -50001,7 +50087,7 @@ ${fileList}`;
|
|
|
50001
50087
|
|
|
50002
50088
|
`).map((p3) => p3.trim()).filter(Boolean) : [response.content.trim()].filter(Boolean);
|
|
50003
50089
|
const durationMs = Date.now() - startTime;
|
|
50004
|
-
|
|
50090
|
+
log9.info("Claude Code agent responded", {
|
|
50005
50091
|
runId: response.runId,
|
|
50006
50092
|
parts: parts.length,
|
|
50007
50093
|
durationMs,
|
|
@@ -50020,7 +50106,7 @@ ${fileList}`;
|
|
|
50020
50106
|
async* triggerStream(context) {
|
|
50021
50107
|
const prepared = await this.prepareRequest(context);
|
|
50022
50108
|
if (!prepared) {
|
|
50023
|
-
|
|
50109
|
+
log9.debug("No content to send to Claude Code (stream)", { traceId: context.traceId });
|
|
50024
50110
|
return;
|
|
50025
50111
|
}
|
|
50026
50112
|
const { message: message2, resolvedSessionId, internalSessionKey } = prepared;
|
|
@@ -50034,7 +50120,7 @@ ${fileList}`;
|
|
|
50034
50120
|
env: buildOmniEnv(context),
|
|
50035
50121
|
...context.source.chatId ? { mcpUrlParams: { chat_id: context.source.chatId } } : {}
|
|
50036
50122
|
};
|
|
50037
|
-
|
|
50123
|
+
log9.info("Triggering Claude Code agent (stream)", {
|
|
50038
50124
|
triggerType: context.type,
|
|
50039
50125
|
traceId: context.traceId
|
|
50040
50126
|
});
|
|
@@ -50051,7 +50137,7 @@ ${fileList}`;
|
|
|
50051
50137
|
}
|
|
50052
50138
|
const streamMetrics = result.getMetrics();
|
|
50053
50139
|
if (streamMetrics) {
|
|
50054
|
-
|
|
50140
|
+
log9.info("Claude Code agent stream completed", {
|
|
50055
50141
|
traceId: context.traceId,
|
|
50056
50142
|
sessionId: claudeSessionId,
|
|
50057
50143
|
durationMs: streamMetrics.durationMs,
|
|
@@ -50067,25 +50153,25 @@ ${fileList}`;
|
|
|
50067
50153
|
}
|
|
50068
50154
|
async resetSession(sessionKey, _chatId, instanceId) {
|
|
50069
50155
|
if (!instanceId) {
|
|
50070
|
-
|
|
50156
|
+
log9.warn("Claude session reset skipped: missing instanceId", {
|
|
50071
50157
|
providerId: this.id,
|
|
50072
50158
|
sessionKey
|
|
50073
50159
|
});
|
|
50074
50160
|
throw new Error("instanceId is required to reset Claude Code session");
|
|
50075
50161
|
}
|
|
50076
50162
|
await this.sessionStorage.deleteSession(instanceId, sessionKey);
|
|
50077
|
-
|
|
50163
|
+
log9.info("Claude session reset", {
|
|
50078
50164
|
providerId: this.id,
|
|
50079
50165
|
instanceId,
|
|
50080
50166
|
sessionKey
|
|
50081
50167
|
});
|
|
50082
50168
|
}
|
|
50083
50169
|
}
|
|
50084
|
-
var
|
|
50170
|
+
var log9, MAX_CONTEXT_MESSAGES = 20, MAX_CONTEXT_CHARS = 4000;
|
|
50085
50171
|
var init_claude_code_provider = __esm(() => {
|
|
50086
50172
|
init_logger();
|
|
50087
50173
|
init_claude_code_client();
|
|
50088
|
-
|
|
50174
|
+
log9 = createLogger("provider:claude-code");
|
|
50089
50175
|
});
|
|
50090
50176
|
|
|
50091
50177
|
// ../core/src/providers/webhook-provider.ts
|
|
@@ -50129,7 +50215,7 @@ class WebhookAgentProvider {
|
|
|
50129
50215
|
traceId: context.traceId,
|
|
50130
50216
|
replyEndpoint: "POST /api/v2/messages/send"
|
|
50131
50217
|
};
|
|
50132
|
-
|
|
50218
|
+
log10.info("Sending webhook trigger", {
|
|
50133
50219
|
webhookUrl: this.config.webhookUrl,
|
|
50134
50220
|
mode: this.mode,
|
|
50135
50221
|
triggerType: context.type,
|
|
@@ -50137,7 +50223,7 @@ class WebhookAgentProvider {
|
|
|
50137
50223
|
});
|
|
50138
50224
|
if (this.mode === "fire-and-forget") {
|
|
50139
50225
|
this.postWebhook(payload).catch((error2) => {
|
|
50140
|
-
|
|
50226
|
+
log10.error("Fire-and-forget webhook failed", {
|
|
50141
50227
|
error: String(error2),
|
|
50142
50228
|
traceId: context.traceId
|
|
50143
50229
|
});
|
|
@@ -50227,7 +50313,7 @@ class WebhookAgentProvider {
|
|
|
50227
50313
|
} catch (error2) {
|
|
50228
50314
|
lastError = error2;
|
|
50229
50315
|
if (error2 instanceof ProviderError && error2.code === "SERVER_ERROR" && attempt < maxRetries) {
|
|
50230
|
-
|
|
50316
|
+
log10.warn("Webhook 5xx error, retrying", {
|
|
50231
50317
|
attempt: attempt + 1,
|
|
50232
50318
|
maxRetries,
|
|
50233
50319
|
error: String(error2)
|
|
@@ -50241,11 +50327,11 @@ class WebhookAgentProvider {
|
|
|
50241
50327
|
throw lastError;
|
|
50242
50328
|
}
|
|
50243
50329
|
}
|
|
50244
|
-
var
|
|
50330
|
+
var log10, DEFAULT_TIMEOUT_MS2 = 30000, DEFAULT_RETRIES = 1;
|
|
50245
50331
|
var init_webhook_provider = __esm(() => {
|
|
50246
50332
|
init_logger();
|
|
50247
50333
|
init_types6();
|
|
50248
|
-
|
|
50334
|
+
log10 = createLogger("provider:webhook");
|
|
50249
50335
|
});
|
|
50250
50336
|
|
|
50251
50337
|
// ../core/src/providers/openclaw/device.ts
|
|
@@ -50291,7 +50377,7 @@ class OpenClawClient {
|
|
|
50291
50377
|
const urlObj = new URL(config2.url);
|
|
50292
50378
|
const host = urlObj.hostname;
|
|
50293
50379
|
if (host !== "localhost" && host !== "127.0.0.1" && host !== "::1") {
|
|
50294
|
-
|
|
50380
|
+
log11.warn("Connecting over unencrypted WebSocket to non-localhost", {
|
|
50295
50381
|
providerId: config2.providerId,
|
|
50296
50382
|
host
|
|
50297
50383
|
});
|
|
@@ -50330,7 +50416,7 @@ class OpenClawClient {
|
|
|
50330
50416
|
this.flushAccumulations(new Error("Client stopped"));
|
|
50331
50417
|
this.flushAgentAccumulations(new Error("Client stopped"));
|
|
50332
50418
|
this.setState("disconnected");
|
|
50333
|
-
|
|
50419
|
+
log11.info("Client stopped", {
|
|
50334
50420
|
providerId: this.config.providerId,
|
|
50335
50421
|
pendingRequests: this.pending.size
|
|
50336
50422
|
});
|
|
@@ -50417,7 +50503,7 @@ class OpenClawClient {
|
|
|
50417
50503
|
try {
|
|
50418
50504
|
this.ws = new WebSocket(this.config.url);
|
|
50419
50505
|
} catch (err2) {
|
|
50420
|
-
|
|
50506
|
+
log11.error("WebSocket construction failed", {
|
|
50421
50507
|
providerId: this.config.providerId,
|
|
50422
50508
|
error: String(err2)
|
|
50423
50509
|
});
|
|
@@ -50474,7 +50560,7 @@ class OpenClawClient {
|
|
|
50474
50560
|
try {
|
|
50475
50561
|
listener(event);
|
|
50476
50562
|
} catch (err2) {
|
|
50477
|
-
|
|
50563
|
+
log11.error("Event listener error", {
|
|
50478
50564
|
providerId: this.config.providerId,
|
|
50479
50565
|
event: event.event,
|
|
50480
50566
|
error: String(err2)
|
|
@@ -50491,7 +50577,7 @@ class OpenClawClient {
|
|
|
50491
50577
|
try {
|
|
50492
50578
|
callback(chatEvent);
|
|
50493
50579
|
} catch (err2) {
|
|
50494
|
-
|
|
50580
|
+
log11.error("Accumulation callback error", {
|
|
50495
50581
|
providerId: this.config.providerId,
|
|
50496
50582
|
runId: chatEvent.runId,
|
|
50497
50583
|
error: String(err2)
|
|
@@ -50508,7 +50594,7 @@ class OpenClawClient {
|
|
|
50508
50594
|
try {
|
|
50509
50595
|
callback(payload);
|
|
50510
50596
|
} catch (err2) {
|
|
50511
|
-
|
|
50597
|
+
log11.error("Agent accumulation callback error", {
|
|
50512
50598
|
providerId: this.config.providerId,
|
|
50513
50599
|
runId,
|
|
50514
50600
|
error: String(err2)
|
|
@@ -50564,7 +50650,7 @@ class OpenClawClient {
|
|
|
50564
50650
|
nonce
|
|
50565
50651
|
};
|
|
50566
50652
|
authToken = dev.token;
|
|
50567
|
-
|
|
50653
|
+
log11.debug("Using device keypair for operator scopes", {
|
|
50568
50654
|
providerId: this.config.providerId,
|
|
50569
50655
|
deviceId: dev.id,
|
|
50570
50656
|
scopes
|
|
@@ -50587,7 +50673,7 @@ class OpenClawClient {
|
|
|
50587
50673
|
userAgent: "omni-v2/1.0.0",
|
|
50588
50674
|
device: deviceField
|
|
50589
50675
|
};
|
|
50590
|
-
|
|
50676
|
+
log11.debug("Sending connect handshake", {
|
|
50591
50677
|
providerId: this.config.providerId,
|
|
50592
50678
|
auth: params.auth ? { token: "[REDACTED]" } : undefined,
|
|
50593
50679
|
scopes: params.scopes,
|
|
@@ -50600,13 +50686,13 @@ class OpenClawClient {
|
|
|
50600
50686
|
this.reconnectAttempt = 0;
|
|
50601
50687
|
this.setState("connected");
|
|
50602
50688
|
this.startHealthPing();
|
|
50603
|
-
|
|
50689
|
+
log11.info("Connected to OpenClaw gateway", {
|
|
50604
50690
|
providerId: this.config.providerId,
|
|
50605
50691
|
protocol: payload.protocol,
|
|
50606
50692
|
defaultAgentId: payload.snapshot?.sessionDefaults?.defaultAgentId
|
|
50607
50693
|
});
|
|
50608
50694
|
} catch (err2) {
|
|
50609
|
-
|
|
50695
|
+
log11.error("Connect handshake failed", {
|
|
50610
50696
|
providerId: this.config.providerId,
|
|
50611
50697
|
error: String(err2)
|
|
50612
50698
|
});
|
|
@@ -50634,13 +50720,13 @@ class OpenClawClient {
|
|
|
50634
50720
|
backoffMs: Math.round(this.backoffMs)
|
|
50635
50721
|
};
|
|
50636
50722
|
if (this.reconnectAttempt < 3) {
|
|
50637
|
-
|
|
50723
|
+
log11.warn("Connection lost, reconnecting", ctx);
|
|
50638
50724
|
} else if (this.reconnectAttempt % 10 === 0) {
|
|
50639
|
-
|
|
50725
|
+
log11.warn("Still reconnecting (periodic)", ctx);
|
|
50640
50726
|
} else if (this.reconnectAttempt < 10) {
|
|
50641
|
-
|
|
50727
|
+
log11.info("Reconnecting", ctx);
|
|
50642
50728
|
} else {
|
|
50643
|
-
|
|
50729
|
+
log11.debug("Reconnecting", ctx);
|
|
50644
50730
|
}
|
|
50645
50731
|
}
|
|
50646
50732
|
startHealthPing() {
|
|
@@ -50648,7 +50734,7 @@ class OpenClawClient {
|
|
|
50648
50734
|
this.healthPingTimer = setInterval(() => {
|
|
50649
50735
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
50650
50736
|
this.request("health").then(() => {}).catch(() => {
|
|
50651
|
-
|
|
50737
|
+
log11.warn("Health ping failed, connection may be stale", {
|
|
50652
50738
|
providerId: this.config.providerId
|
|
50653
50739
|
});
|
|
50654
50740
|
});
|
|
@@ -50701,11 +50787,11 @@ class OpenClawClient {
|
|
|
50701
50787
|
}
|
|
50702
50788
|
}
|
|
50703
50789
|
}
|
|
50704
|
-
var
|
|
50790
|
+
var log11;
|
|
50705
50791
|
var init_client2 = __esm(() => {
|
|
50706
50792
|
init_logger();
|
|
50707
50793
|
init_device();
|
|
50708
|
-
|
|
50794
|
+
log11 = createLogger("openclaw:client");
|
|
50709
50795
|
});
|
|
50710
50796
|
|
|
50711
50797
|
// ../core/src/providers/openclaw/provider.ts
|
|
@@ -50822,7 +50908,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50822
50908
|
const sessionKey = this.buildSessionKey(agentId, context.sessionId || context.source.chatId);
|
|
50823
50909
|
const agentTimeoutMs = this.config.agentTimeoutMs ?? 120000;
|
|
50824
50910
|
const sendAckTimeoutMs = this.config.sendAckTimeoutMs ?? 1e4;
|
|
50825
|
-
|
|
50911
|
+
log12.info("Triggering OpenClaw agent", {
|
|
50826
50912
|
traceId: context.traceId,
|
|
50827
50913
|
agentId,
|
|
50828
50914
|
sessionKey,
|
|
@@ -50832,7 +50918,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50832
50918
|
});
|
|
50833
50919
|
if (this.isCircuitOpen()) {
|
|
50834
50920
|
const msg = "The assistant is temporarily unavailable. Please try again in a moment.";
|
|
50835
|
-
|
|
50921
|
+
log12.warn("Circuit breaker open, rejecting trigger", {
|
|
50836
50922
|
traceId: context.traceId,
|
|
50837
50923
|
providerId: this.id,
|
|
50838
50924
|
agentId,
|
|
@@ -50849,14 +50935,14 @@ ${fileRefs}` : fileRefs;
|
|
|
50849
50935
|
}
|
|
50850
50936
|
const built = this.buildMessage(context);
|
|
50851
50937
|
if (!built) {
|
|
50852
|
-
|
|
50938
|
+
log12.debug("No content to send to agent", { traceId: context.traceId });
|
|
50853
50939
|
return {
|
|
50854
50940
|
parts: [],
|
|
50855
50941
|
metadata: { runId: "", providerId: this.id, durationMs: Date.now() - startTime }
|
|
50856
50942
|
};
|
|
50857
50943
|
}
|
|
50858
50944
|
if ("error" in built) {
|
|
50859
|
-
|
|
50945
|
+
log12.error("Message exceeds 100KB limit", { traceId: context.traceId, providerId: this.id });
|
|
50860
50946
|
return {
|
|
50861
50947
|
parts: [built.error],
|
|
50862
50948
|
metadata: { runId: "", providerId: this.id, durationMs: Date.now() - startTime }
|
|
@@ -50872,7 +50958,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50872
50958
|
idempotencyKey: randomUUID()
|
|
50873
50959
|
}, sendAckTimeoutMs);
|
|
50874
50960
|
const runId = sendResult.runId;
|
|
50875
|
-
|
|
50961
|
+
log12.debug("chat.send acknowledged", {
|
|
50876
50962
|
traceId: context.traceId,
|
|
50877
50963
|
runId,
|
|
50878
50964
|
wsRequestId: sendResult.runId,
|
|
@@ -50884,7 +50970,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50884
50970
|
const accumulated = await this.accumulateResponse(runId, agentTimeoutMs, context.traceId, sendTimestamp);
|
|
50885
50971
|
this.consecutiveFailures = 0;
|
|
50886
50972
|
const durationMs = Date.now() - startTime;
|
|
50887
|
-
|
|
50973
|
+
log12.info("OpenClaw agent responded", {
|
|
50888
50974
|
traceId: context.traceId,
|
|
50889
50975
|
runId,
|
|
50890
50976
|
sessionKey,
|
|
@@ -50906,7 +50992,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50906
50992
|
} catch (err2) {
|
|
50907
50993
|
this.consecutiveFailures++;
|
|
50908
50994
|
const durationMs = Date.now() - startTime;
|
|
50909
|
-
|
|
50995
|
+
log12.error("OpenClaw trigger failed", {
|
|
50910
50996
|
traceId: context.traceId,
|
|
50911
50997
|
agentId,
|
|
50912
50998
|
sessionKey,
|
|
@@ -50917,7 +51003,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50917
51003
|
});
|
|
50918
51004
|
if (this.consecutiveFailures >= OpenClawAgentProvider.CIRCUIT_THRESHOLD) {
|
|
50919
51005
|
this.circuitOpenUntil = Date.now() + OpenClawAgentProvider.CIRCUIT_COOLDOWN_MS;
|
|
50920
|
-
|
|
51006
|
+
log12.warn("Circuit breaker OPENED", {
|
|
50921
51007
|
providerId: this.id,
|
|
50922
51008
|
agentId,
|
|
50923
51009
|
consecutiveFailures: this.consecutiveFailures,
|
|
@@ -50959,7 +51045,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50959
51045
|
idempotencyKey: randomUUID()
|
|
50960
51046
|
}, sendAckTimeoutMs);
|
|
50961
51047
|
ctx.runId = sendResult.runId;
|
|
50962
|
-
|
|
51048
|
+
log12.debug("triggerStream: started", {
|
|
50963
51049
|
traceId: context.traceId,
|
|
50964
51050
|
runId: ctx.runId,
|
|
50965
51051
|
sessionKey,
|
|
@@ -50968,7 +51054,7 @@ ${fileRefs}` : fileRefs;
|
|
|
50968
51054
|
ctx.timeoutHandle = setTimeout(() => {
|
|
50969
51055
|
if (ctx.done)
|
|
50970
51056
|
return;
|
|
50971
|
-
|
|
51057
|
+
log12.warn("triggerStream: timeout", {
|
|
50972
51058
|
traceId: context.traceId,
|
|
50973
51059
|
runId: ctx.runId,
|
|
50974
51060
|
timeoutMs: agentTimeoutMs,
|
|
@@ -51001,7 +51087,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51001
51087
|
} catch (err2) {
|
|
51002
51088
|
const error2 = String(err2);
|
|
51003
51089
|
this.registerStreamFailure(error2);
|
|
51004
|
-
|
|
51090
|
+
log12.error("triggerStream: error", {
|
|
51005
51091
|
traceId: context.traceId,
|
|
51006
51092
|
runId: ctx.runId,
|
|
51007
51093
|
sessionKey,
|
|
@@ -51021,7 +51107,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51021
51107
|
this.consecutiveFailures++;
|
|
51022
51108
|
if (this.consecutiveFailures >= OpenClawAgentProvider.CIRCUIT_THRESHOLD) {
|
|
51023
51109
|
this.circuitOpenUntil = Date.now() + OpenClawAgentProvider.CIRCUIT_COOLDOWN_MS;
|
|
51024
|
-
|
|
51110
|
+
log12.warn("Circuit breaker OPENED", {
|
|
51025
51111
|
providerId: this.id,
|
|
51026
51112
|
consecutiveFailures: this.consecutiveFailures,
|
|
51027
51113
|
cooldownMs: OpenClawAgentProvider.CIRCUIT_COOLDOWN_MS,
|
|
@@ -51042,7 +51128,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51042
51128
|
this.handleAssistantEvent(data2, ctx, trigger);
|
|
51043
51129
|
break;
|
|
51044
51130
|
case "tool":
|
|
51045
|
-
|
|
51131
|
+
log12.debug("triggerStream: tool_event", {
|
|
51046
51132
|
traceId: trigger.traceId,
|
|
51047
51133
|
runId: ctx.runId,
|
|
51048
51134
|
seq: event.seq,
|
|
@@ -51063,7 +51149,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51063
51149
|
ctx.thinkingStartMs = Date.now();
|
|
51064
51150
|
if (!ctx.sawThinkingStarted) {
|
|
51065
51151
|
ctx.sawThinkingStarted = true;
|
|
51066
|
-
|
|
51152
|
+
log12.debug("triggerStream: thinking_started", {
|
|
51067
51153
|
traceId: trigger.traceId,
|
|
51068
51154
|
runId: ctx.runId,
|
|
51069
51155
|
providerId: this.id
|
|
@@ -51078,7 +51164,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51078
51164
|
ctx.contentText = text;
|
|
51079
51165
|
if (!ctx.sawContentStarted) {
|
|
51080
51166
|
ctx.sawContentStarted = true;
|
|
51081
|
-
|
|
51167
|
+
log12.debug("triggerStream: content_started", { traceId: trigger.traceId, runId: ctx.runId, providerId: this.id });
|
|
51082
51168
|
}
|
|
51083
51169
|
if (ctx.thinkingStartMs && ctx.thinkingDurationMs === undefined) {
|
|
51084
51170
|
ctx.thinkingDurationMs = Date.now() - ctx.thinkingStartMs;
|
|
@@ -51097,7 +51183,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51097
51183
|
ctx.thinkingDurationMs = Date.now() - ctx.thinkingStartMs;
|
|
51098
51184
|
}
|
|
51099
51185
|
this.consecutiveFailures = 0;
|
|
51100
|
-
|
|
51186
|
+
log12.info("triggerStream: completed", {
|
|
51101
51187
|
traceId: trigger.traceId,
|
|
51102
51188
|
runId: ctx.runId,
|
|
51103
51189
|
providerId: this.id,
|
|
@@ -51114,7 +51200,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51114
51200
|
}
|
|
51115
51201
|
if (phase === "error") {
|
|
51116
51202
|
const error2 = typeof data2.error === "string" && data2.error ? data2.error : "Agent error";
|
|
51117
|
-
|
|
51203
|
+
log12.error("triggerStream: lifecycle_error", {
|
|
51118
51204
|
traceId: trigger.traceId,
|
|
51119
51205
|
runId: ctx.runId,
|
|
51120
51206
|
providerId: this.id,
|
|
@@ -51127,7 +51213,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51127
51213
|
}
|
|
51128
51214
|
handleErrorEvent(data2, ctx, trigger) {
|
|
51129
51215
|
const error2 = typeof data2.error === "string" && data2.error || typeof data2.message === "string" && data2.message || "Unknown error";
|
|
51130
|
-
|
|
51216
|
+
log12.error("triggerStream: error_stream", {
|
|
51131
51217
|
traceId: trigger.traceId,
|
|
51132
51218
|
runId: ctx.runId,
|
|
51133
51219
|
providerId: this.id,
|
|
@@ -51153,7 +51239,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51153
51239
|
resolve2();
|
|
51154
51240
|
});
|
|
51155
51241
|
await Promise.race([cleanup, timeout]);
|
|
51156
|
-
|
|
51242
|
+
log12.info("Provider disposed", {
|
|
51157
51243
|
providerId: this.id
|
|
51158
51244
|
});
|
|
51159
51245
|
}
|
|
@@ -51162,9 +51248,9 @@ ${fileRefs}` : fileRefs;
|
|
|
51162
51248
|
try {
|
|
51163
51249
|
await this.client.waitForReady(5000);
|
|
51164
51250
|
await this.client.deleteSession(effectiveKey);
|
|
51165
|
-
|
|
51251
|
+
log12.info("Session reset", { providerId: this.id, sessionKey: effectiveKey, originalKey: sessionKey, chatId });
|
|
51166
51252
|
} catch (err2) {
|
|
51167
|
-
|
|
51253
|
+
log12.error("Session reset failed", {
|
|
51168
51254
|
providerId: this.id,
|
|
51169
51255
|
sessionKey: effectiveKey,
|
|
51170
51256
|
error: String(err2)
|
|
@@ -51180,7 +51266,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51180
51266
|
if (this.circuitOpenUntil === 0)
|
|
51181
51267
|
return false;
|
|
51182
51268
|
if (Date.now() >= this.circuitOpenUntil) {
|
|
51183
|
-
|
|
51269
|
+
log12.info("Circuit breaker CLOSED", { providerId: this.id });
|
|
51184
51270
|
this.circuitOpenUntil = 0;
|
|
51185
51271
|
this.consecutiveFailures = 0;
|
|
51186
51272
|
return false;
|
|
@@ -51198,7 +51284,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51198
51284
|
if (!state.firstDeltaAt) {
|
|
51199
51285
|
state.firstDeltaAt = now;
|
|
51200
51286
|
const ttfdMs = now - state.sendTimestamp;
|
|
51201
|
-
|
|
51287
|
+
log12.debug("Time-to-first-delta", { traceId: state.traceId, runId: state.runId, ttfdMs, providerId: this.id });
|
|
51202
51288
|
}
|
|
51203
51289
|
const text = this.extractText(event);
|
|
51204
51290
|
if (text) {
|
|
@@ -51234,7 +51320,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51234
51320
|
return;
|
|
51235
51321
|
finish(() => {
|
|
51236
51322
|
const kind = state.deltasReceived === 0 ? "Dead-response" : "Accumulation timeout (stalled mid-stream)";
|
|
51237
|
-
|
|
51323
|
+
log12.warn(kind, { traceId, runId, providerId: this.id, deltasReceived: state.deltasReceived, timeoutMs });
|
|
51238
51324
|
reject(new Error(`Accumulation timeout after ${timeoutMs}ms (deltas: ${state.deltasReceived})`));
|
|
51239
51325
|
});
|
|
51240
51326
|
}, timeoutMs);
|
|
@@ -51248,7 +51334,7 @@ ${fileRefs}` : fileRefs;
|
|
|
51248
51334
|
finish(() => resolve2(state.accumulated));
|
|
51249
51335
|
} else if (outcome === "cap_exceeded") {
|
|
51250
51336
|
finish(() => {
|
|
51251
|
-
|
|
51337
|
+
log12.error("Accumulation cap (1MB) exceeded", { traceId, runId, providerId: this.id });
|
|
51252
51338
|
reject(new Error("Response too large (1MB cap)"));
|
|
51253
51339
|
});
|
|
51254
51340
|
} else {
|
|
@@ -51274,11 +51360,11 @@ function createOpenClawProvider(id, name, clientConfig, providerConfig) {
|
|
|
51274
51360
|
client.start();
|
|
51275
51361
|
return new OpenClawAgentProvider(id, name, client, providerConfig);
|
|
51276
51362
|
}
|
|
51277
|
-
var
|
|
51363
|
+
var log12, CONTROL_CHAR_RE, MAX_MESSAGE_BYTES, MAX_ACCUMULATION_BYTES, MAX_DELTA_CONTENT_BYTES, AGENT_ID_REGEX;
|
|
51278
51364
|
var init_provider = __esm(() => {
|
|
51279
51365
|
init_logger();
|
|
51280
51366
|
init_client2();
|
|
51281
|
-
|
|
51367
|
+
log12 = createLogger("openclaw:provider");
|
|
51282
51368
|
CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/g;
|
|
51283
51369
|
MAX_MESSAGE_BYTES = 100 * 1024;
|
|
51284
51370
|
MAX_ACCUMULATION_BYTES = 1 * 1024 * 1024;
|
|
@@ -51468,7 +51554,7 @@ class AgUiClient {
|
|
|
51468
51554
|
const event = JSON.parse(data2);
|
|
51469
51555
|
return this.parseAgUiEvent(event, currentRunId);
|
|
51470
51556
|
} catch (e2) {
|
|
51471
|
-
|
|
51557
|
+
log13.warn("Failed to parse AG-UI SSE event", { data: data2, error: String(e2) });
|
|
51472
51558
|
return null;
|
|
51473
51559
|
}
|
|
51474
51560
|
}
|
|
@@ -51510,11 +51596,11 @@ class AgUiClient {
|
|
|
51510
51596
|
function createAgUiClient(config2) {
|
|
51511
51597
|
return new AgUiClient(config2);
|
|
51512
51598
|
}
|
|
51513
|
-
var
|
|
51599
|
+
var log13, DEFAULT_TIMEOUT_MS3 = 120000, AG_UI_TEXT_CONTENT = "TEXT_MESSAGE_CONTENT", AG_UI_RUN_FINISHED = "RUN_FINISHED", AG_UI_RUN_ERROR = "RUN_ERROR", AG_UI_RUN_STARTED = "RUN_STARTED";
|
|
51514
51600
|
var init_ag_ui_client = __esm(() => {
|
|
51515
51601
|
init_logger();
|
|
51516
51602
|
init_types6();
|
|
51517
|
-
|
|
51603
|
+
log13 = createLogger("providers:ag-ui-client");
|
|
51518
51604
|
});
|
|
51519
51605
|
|
|
51520
51606
|
// ../core/src/providers/ag-ui-provider.ts
|
|
@@ -51538,7 +51624,7 @@ class AgUiAgentProvider {
|
|
|
51538
51624
|
const startTime = Date.now();
|
|
51539
51625
|
const message2 = this.buildMessage(context);
|
|
51540
51626
|
if (!message2) {
|
|
51541
|
-
|
|
51627
|
+
log14.debug("No content to send to AG-UI agent", { traceId: context.traceId });
|
|
51542
51628
|
return { parts: [], metadata: { runId: "", providerId: this.id, durationMs: 0 } };
|
|
51543
51629
|
}
|
|
51544
51630
|
const request = {
|
|
@@ -51548,13 +51634,13 @@ class AgUiAgentProvider {
|
|
|
51548
51634
|
userId: context.sender.platformUserId,
|
|
51549
51635
|
timeoutMs: this.config.timeoutMs ?? 60000
|
|
51550
51636
|
};
|
|
51551
|
-
|
|
51637
|
+
log14.info("Triggering AG-UI agent", { agentId: this.config.agentId, traceId: context.traceId });
|
|
51552
51638
|
const response = await this.client.run(request);
|
|
51553
51639
|
const durationMs = Date.now() - startTime;
|
|
51554
51640
|
const parts = this.config.enableAutoSplit !== false ? response.content.split(`
|
|
51555
51641
|
|
|
51556
51642
|
`).map((p3) => p3.trim()).filter(Boolean) : [response.content.trim()].filter(Boolean);
|
|
51557
|
-
|
|
51643
|
+
log14.info("AG-UI agent responded", {
|
|
51558
51644
|
runId: response.runId,
|
|
51559
51645
|
parts: parts.length,
|
|
51560
51646
|
durationMs,
|
|
@@ -51568,7 +51654,7 @@ class AgUiAgentProvider {
|
|
|
51568
51654
|
async* triggerStream(context) {
|
|
51569
51655
|
const message2 = this.buildMessage(context);
|
|
51570
51656
|
if (!message2) {
|
|
51571
|
-
|
|
51657
|
+
log14.debug("No content to send to AG-UI agent (stream)", { traceId: context.traceId });
|
|
51572
51658
|
return;
|
|
51573
51659
|
}
|
|
51574
51660
|
const request = {
|
|
@@ -51578,7 +51664,7 @@ class AgUiAgentProvider {
|
|
|
51578
51664
|
userId: context.sender.platformUserId,
|
|
51579
51665
|
timeoutMs: this.config.timeoutMs ?? 60000
|
|
51580
51666
|
};
|
|
51581
|
-
|
|
51667
|
+
log14.info("Streaming AG-UI agent", { agentId: this.config.agentId, traceId: context.traceId });
|
|
51582
51668
|
for await (const chunk of this.client.stream(request)) {
|
|
51583
51669
|
if (chunk.event === "delta" && chunk.content) {
|
|
51584
51670
|
yield { phase: "content", content: chunk.content };
|
|
@@ -51618,11 +51704,11 @@ function createAgUiProvider(id, name, config2) {
|
|
|
51618
51704
|
prefixSenderName: config2.prefixSenderName
|
|
51619
51705
|
});
|
|
51620
51706
|
}
|
|
51621
|
-
var
|
|
51707
|
+
var log14;
|
|
51622
51708
|
var init_ag_ui_provider = __esm(() => {
|
|
51623
51709
|
init_logger();
|
|
51624
51710
|
init_ag_ui_client();
|
|
51625
|
-
|
|
51711
|
+
log14 = createLogger("provider:ag-ui");
|
|
51626
51712
|
});
|
|
51627
51713
|
|
|
51628
51714
|
// ../core/src/providers/a2a-client.ts
|
|
@@ -51781,7 +51867,7 @@ class A2AClient {
|
|
|
51781
51867
|
const event = JSON.parse(data2);
|
|
51782
51868
|
return this.parseSSEEvent(event);
|
|
51783
51869
|
} catch (e2) {
|
|
51784
|
-
|
|
51870
|
+
log15.warn("Failed to parse A2A SSE event", { data: data2, error: String(e2) });
|
|
51785
51871
|
return null;
|
|
51786
51872
|
}
|
|
51787
51873
|
}
|
|
@@ -51884,11 +51970,11 @@ function sleep2(ms) {
|
|
|
51884
51970
|
function createA2AClient(config2) {
|
|
51885
51971
|
return new A2AClient(config2);
|
|
51886
51972
|
}
|
|
51887
|
-
var
|
|
51973
|
+
var log15, DEFAULT_TIMEOUT_MS4 = 60000, MAX_POLL_ATTEMPTS = 60, POLL_INTERVAL_MS = 1000;
|
|
51888
51974
|
var init_a2a_client = __esm(() => {
|
|
51889
51975
|
init_logger();
|
|
51890
51976
|
init_types6();
|
|
51891
|
-
|
|
51977
|
+
log15 = createLogger("providers:a2a-client");
|
|
51892
51978
|
});
|
|
51893
51979
|
|
|
51894
51980
|
// ../core/src/providers/a2a-provider.ts
|
|
@@ -51912,7 +51998,7 @@ class A2AAgentProvider {
|
|
|
51912
51998
|
const startTime = Date.now();
|
|
51913
51999
|
const message2 = this.buildMessage(context);
|
|
51914
52000
|
if (!message2) {
|
|
51915
|
-
|
|
52001
|
+
log16.debug("No content to send to A2A agent", { traceId: context.traceId });
|
|
51916
52002
|
return { parts: [], metadata: { runId: "", providerId: this.id, durationMs: 0 } };
|
|
51917
52003
|
}
|
|
51918
52004
|
const request = {
|
|
@@ -51922,7 +52008,7 @@ class A2AAgentProvider {
|
|
|
51922
52008
|
userId: context.sender.platformUserId,
|
|
51923
52009
|
timeoutMs: this.config.timeoutMs ?? 60000
|
|
51924
52010
|
};
|
|
51925
|
-
|
|
52011
|
+
log16.info("Triggering A2A agent", { agentId: this.config.agentId, traceId: context.traceId });
|
|
51926
52012
|
const response = await this.client.run(request);
|
|
51927
52013
|
if (response.status === "failed") {
|
|
51928
52014
|
throw new Error(`A2A agent failed: ${response.content || "unknown"}`);
|
|
@@ -51931,7 +52017,7 @@ class A2AAgentProvider {
|
|
|
51931
52017
|
const parts = this.config.enableAutoSplit !== false ? response.content.split(`
|
|
51932
52018
|
|
|
51933
52019
|
`).map((p3) => p3.trim()).filter(Boolean) : [response.content.trim()].filter(Boolean);
|
|
51934
|
-
|
|
52020
|
+
log16.info("A2A agent responded", {
|
|
51935
52021
|
runId: response.runId,
|
|
51936
52022
|
parts: parts.length,
|
|
51937
52023
|
durationMs,
|
|
@@ -51945,7 +52031,7 @@ class A2AAgentProvider {
|
|
|
51945
52031
|
async* triggerStream(context) {
|
|
51946
52032
|
const message2 = this.buildMessage(context);
|
|
51947
52033
|
if (!message2) {
|
|
51948
|
-
|
|
52034
|
+
log16.debug("No content to send to A2A agent (stream)", { traceId: context.traceId });
|
|
51949
52035
|
return;
|
|
51950
52036
|
}
|
|
51951
52037
|
const request = {
|
|
@@ -51955,7 +52041,7 @@ class A2AAgentProvider {
|
|
|
51955
52041
|
userId: context.sender.platformUserId,
|
|
51956
52042
|
timeoutMs: this.config.timeoutMs ?? 60000
|
|
51957
52043
|
};
|
|
51958
|
-
|
|
52044
|
+
log16.info("Streaming A2A agent", { agentId: this.config.agentId, traceId: context.traceId });
|
|
51959
52045
|
for await (const chunk of this.client.stream(request)) {
|
|
51960
52046
|
if (chunk.event === "artifact" && chunk.content) {
|
|
51961
52047
|
yield { phase: "content", content: chunk.content };
|
|
@@ -51997,11 +52083,11 @@ function createA2AProvider(id, name, config2) {
|
|
|
51997
52083
|
prefixSenderName: config2.prefixSenderName
|
|
51998
52084
|
});
|
|
51999
52085
|
}
|
|
52000
|
-
var
|
|
52086
|
+
var log16;
|
|
52001
52087
|
var init_a2a_provider = __esm(() => {
|
|
52002
52088
|
init_logger();
|
|
52003
52089
|
init_a2a_client();
|
|
52004
|
-
|
|
52090
|
+
log16 = createLogger("provider:a2a");
|
|
52005
52091
|
});
|
|
52006
52092
|
|
|
52007
52093
|
// ../core/src/providers/nats-genie-provider.ts
|
|
@@ -52031,7 +52117,7 @@ class NatsGenieProvider {
|
|
|
52031
52117
|
const startTime = Date.now();
|
|
52032
52118
|
const message2 = this.buildMessage(context);
|
|
52033
52119
|
if (!message2) {
|
|
52034
|
-
|
|
52120
|
+
log17.debug("No content to send", { traceId: context.traceId });
|
|
52035
52121
|
return {
|
|
52036
52122
|
parts: [],
|
|
52037
52123
|
metadata: { runId: "", providerId: this.id, durationMs: Date.now() - startTime }
|
|
@@ -52053,14 +52139,14 @@ class NatsGenieProvider {
|
|
|
52053
52139
|
try {
|
|
52054
52140
|
await this.ensureConnected();
|
|
52055
52141
|
this.nc?.publish(topic, this.sc.encode(JSON.stringify(payload)));
|
|
52056
|
-
|
|
52142
|
+
log17.info("Published to NATS", {
|
|
52057
52143
|
topic,
|
|
52058
52144
|
agent: this.config.agentName,
|
|
52059
52145
|
chatId: context.source.chatId,
|
|
52060
52146
|
traceId: context.traceId
|
|
52061
52147
|
});
|
|
52062
52148
|
} catch (error2) {
|
|
52063
|
-
|
|
52149
|
+
log17.error("Failed to publish to NATS, writing to dead-letter queue", {
|
|
52064
52150
|
topic,
|
|
52065
52151
|
error: error2 instanceof Error ? error2.message : String(error2),
|
|
52066
52152
|
traceId: context.traceId
|
|
@@ -52088,7 +52174,7 @@ class NatsGenieProvider {
|
|
|
52088
52174
|
const topic = `omni.reply.${this.config.instanceId}.>`;
|
|
52089
52175
|
const sub = this.nc.subscribe(topic);
|
|
52090
52176
|
this.replySubscription = sub;
|
|
52091
|
-
|
|
52177
|
+
log17.info("Subscribed to agent replies", { topic });
|
|
52092
52178
|
const subjectPrefix = `omni.reply.${this.config.instanceId}.`;
|
|
52093
52179
|
(async () => {
|
|
52094
52180
|
for await (const msg of sub) {
|
|
@@ -52103,7 +52189,7 @@ class NatsGenieProvider {
|
|
|
52103
52189
|
});
|
|
52104
52190
|
}
|
|
52105
52191
|
} catch (error2) {
|
|
52106
|
-
|
|
52192
|
+
log17.error("Error processing reply", {
|
|
52107
52193
|
subject: msg.subject,
|
|
52108
52194
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
52109
52195
|
});
|
|
@@ -52127,7 +52213,7 @@ class NatsGenieProvider {
|
|
|
52127
52213
|
async resetSession(sessionKey, chatId, instanceId) {
|
|
52128
52214
|
const resolvedInstanceId = instanceId ?? this.config.instanceId;
|
|
52129
52215
|
if (!chatId) {
|
|
52130
|
-
|
|
52216
|
+
log17.warn("NATS session reset skipped: missing chatId", {
|
|
52131
52217
|
providerId: this.id,
|
|
52132
52218
|
sessionKey
|
|
52133
52219
|
});
|
|
@@ -52145,14 +52231,14 @@ class NatsGenieProvider {
|
|
|
52145
52231
|
try {
|
|
52146
52232
|
await this.ensureConnected();
|
|
52147
52233
|
this.nc?.publish(topic, this.sc.encode(JSON.stringify(payload)));
|
|
52148
|
-
|
|
52234
|
+
log17.info("Published session reset to NATS", {
|
|
52149
52235
|
topic,
|
|
52150
52236
|
providerId: this.id,
|
|
52151
52237
|
sessionKey,
|
|
52152
52238
|
chatId
|
|
52153
52239
|
});
|
|
52154
52240
|
} catch (error2) {
|
|
52155
|
-
|
|
52241
|
+
log17.error("Failed to publish NATS session reset", {
|
|
52156
52242
|
topic,
|
|
52157
52243
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
52158
52244
|
});
|
|
@@ -52181,7 +52267,7 @@ class NatsGenieProvider {
|
|
|
52181
52267
|
maxReconnectAttempts: -1,
|
|
52182
52268
|
reconnectTimeWait: 2000
|
|
52183
52269
|
});
|
|
52184
|
-
|
|
52270
|
+
log17.info("Connected to NATS", { url: this.config.natsUrl });
|
|
52185
52271
|
}
|
|
52186
52272
|
buildMessage(context) {
|
|
52187
52273
|
let message2 = "";
|
|
@@ -52205,19 +52291,19 @@ class NatsGenieProvider {
|
|
|
52205
52291
|
error: error2 instanceof Error ? error2.message : String(error2),
|
|
52206
52292
|
timestamp: new Date().toISOString()
|
|
52207
52293
|
}, null, 2));
|
|
52208
|
-
|
|
52294
|
+
log17.warn("Dead letter written", { filename });
|
|
52209
52295
|
} catch (dlError) {
|
|
52210
|
-
|
|
52296
|
+
log17.error("Failed to write dead letter", {
|
|
52211
52297
|
error: dlError instanceof Error ? dlError.message : String(dlError)
|
|
52212
52298
|
});
|
|
52213
52299
|
}
|
|
52214
52300
|
}
|
|
52215
52301
|
}
|
|
52216
|
-
var import_nats4,
|
|
52302
|
+
var import_nats4, log17;
|
|
52217
52303
|
var init_nats_genie_provider = __esm(() => {
|
|
52218
52304
|
init_logger();
|
|
52219
52305
|
import_nats4 = __toESM(require_mod4(), 1);
|
|
52220
|
-
|
|
52306
|
+
log17 = createLogger("provider:nats-genie");
|
|
52221
52307
|
});
|
|
52222
52308
|
|
|
52223
52309
|
// ../core/src/providers/factory.ts
|
|
@@ -52708,11 +52794,11 @@ async function executeSingleHook(hook, handlerContext, timeoutMs, event, instanc
|
|
|
52708
52794
|
const outcome = await withTimeout(handlerPromise, timeoutMs, controller);
|
|
52709
52795
|
if (outcome.timedOut) {
|
|
52710
52796
|
const durationMs2 = performance.now() - hookStart;
|
|
52711
|
-
|
|
52797
|
+
log18.warn("Hook timed out", { hookId: hook.id, hookName: hook.name, event, instanceId, timeoutMs, durationMs: durationMs2 });
|
|
52712
52798
|
return { result: { hookId: hook.id, hookName: hook.name, status: "timeout", durationMs: durationMs2 } };
|
|
52713
52799
|
}
|
|
52714
52800
|
const durationMs = performance.now() - hookStart;
|
|
52715
|
-
|
|
52801
|
+
log18.debug("Hook executed", {
|
|
52716
52802
|
hookId: hook.id,
|
|
52717
52803
|
hookName: hook.name,
|
|
52718
52804
|
event,
|
|
@@ -52726,7 +52812,7 @@ async function executeSingleHook(hook, handlerContext, timeoutMs, event, instanc
|
|
|
52726
52812
|
} catch (error2) {
|
|
52727
52813
|
const durationMs = performance.now() - hookStart;
|
|
52728
52814
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
52729
|
-
|
|
52815
|
+
log18.warn("Hook execution failed", {
|
|
52730
52816
|
hookId: hook.id,
|
|
52731
52817
|
hookName: hook.name,
|
|
52732
52818
|
event,
|
|
@@ -52744,7 +52830,7 @@ function commitContextUpdate(event, instanceId, hook, baseResult, contextBefore,
|
|
|
52744
52830
|
const parsed = schema.safeParse(returnedContext);
|
|
52745
52831
|
if (!parsed.success) {
|
|
52746
52832
|
const errorMessage = `Hook returned invalid context: ${parsed.error.message}`;
|
|
52747
|
-
|
|
52833
|
+
log18.warn("Hook returned invalid context shape, rejecting update", {
|
|
52748
52834
|
hookId: hook.id,
|
|
52749
52835
|
hookName: hook.name,
|
|
52750
52836
|
event,
|
|
@@ -52763,7 +52849,7 @@ function commitContextUpdate(event, instanceId, hook, baseResult, contextBefore,
|
|
|
52763
52849
|
};
|
|
52764
52850
|
}
|
|
52765
52851
|
const changedFields = Object.keys(parsed.data).filter((key) => contextBefore[key] !== parsed.data[key]);
|
|
52766
|
-
|
|
52852
|
+
log18.info("Hook executed", {
|
|
52767
52853
|
hookId: hook.id,
|
|
52768
52854
|
hookName: hook.name,
|
|
52769
52855
|
event,
|
|
@@ -52786,7 +52872,7 @@ async function runPipelineLoop(hooks, initialContext, event, instanceId, timeout
|
|
|
52786
52872
|
});
|
|
52787
52873
|
for (const hook of hooks) {
|
|
52788
52874
|
if (pipelineTimedOut) {
|
|
52789
|
-
|
|
52875
|
+
log18.warn("Hook pipeline global timeout reached, returning partial results", {
|
|
52790
52876
|
event,
|
|
52791
52877
|
instanceId,
|
|
52792
52878
|
pipelineTimeoutMs,
|
|
@@ -52804,7 +52890,7 @@ async function runPipelineLoop(hooks, initialContext, event, instanceId, timeout
|
|
|
52804
52890
|
const hookExecution = executeSingleHook(hook, handlerContext, timeoutMs, event, instanceId);
|
|
52805
52891
|
const outcome = await Promise.race([hookExecution, pipelineDeadline.then(() => null)]);
|
|
52806
52892
|
if (outcome === null) {
|
|
52807
|
-
|
|
52893
|
+
log18.warn("Hook pipeline global timeout reached during hook execution, returning partial results", {
|
|
52808
52894
|
event,
|
|
52809
52895
|
instanceId,
|
|
52810
52896
|
pipelineTimeoutMs,
|
|
@@ -52839,7 +52925,7 @@ async function executeHooks(instanceId, event, context, options, registry2) {
|
|
|
52839
52925
|
try {
|
|
52840
52926
|
initialContext = structuredClone(context);
|
|
52841
52927
|
} catch (cloneError) {
|
|
52842
|
-
|
|
52928
|
+
log18.warn("structuredClone failed on hook context, skipping hooks for this event", {
|
|
52843
52929
|
event,
|
|
52844
52930
|
instanceId,
|
|
52845
52931
|
error: cloneError instanceof Error ? cloneError.message : String(cloneError)
|
|
@@ -52848,7 +52934,7 @@ async function executeHooks(instanceId, event, context, options, registry2) {
|
|
|
52848
52934
|
}
|
|
52849
52935
|
const { results, finalContext } = await runPipelineLoop(hooks, initialContext, event, instanceId, timeoutMs, pipelineTimeoutMs);
|
|
52850
52936
|
const totalDurationMs = performance.now() - pipelineStart;
|
|
52851
|
-
|
|
52937
|
+
log18.info("Hook pipeline complete", {
|
|
52852
52938
|
event,
|
|
52853
52939
|
instanceId,
|
|
52854
52940
|
hookCount: hooks.length,
|
|
@@ -52857,12 +52943,12 @@ async function executeHooks(instanceId, event, context, options, registry2) {
|
|
|
52857
52943
|
});
|
|
52858
52944
|
return { context: finalContext, results, totalDurationMs };
|
|
52859
52945
|
}
|
|
52860
|
-
var
|
|
52946
|
+
var log18;
|
|
52861
52947
|
var init_executor = __esm(() => {
|
|
52862
52948
|
init_logger();
|
|
52863
52949
|
init_registry2();
|
|
52864
52950
|
init_types8();
|
|
52865
|
-
|
|
52951
|
+
log18 = createLogger("hooks:executor");
|
|
52866
52952
|
});
|
|
52867
52953
|
|
|
52868
52954
|
// ../core/src/hooks/index.ts
|
|
@@ -62062,11 +62148,11 @@ var init_client3 = __esm(() => {
|
|
|
62062
62148
|
});
|
|
62063
62149
|
|
|
62064
62150
|
// ../db/src/migrate.ts
|
|
62065
|
-
var
|
|
62151
|
+
var log19;
|
|
62066
62152
|
var init_migrate = __esm(() => {
|
|
62067
62153
|
init_src();
|
|
62068
62154
|
init_client3();
|
|
62069
|
-
|
|
62155
|
+
log19 = createLogger("db:migrate");
|
|
62070
62156
|
if (false) {}
|
|
62071
62157
|
});
|
|
62072
62158
|
|
|
@@ -62262,7 +62348,7 @@ class ApiKeyService {
|
|
|
62262
62348
|
}
|
|
62263
62349
|
async validate(key, ip) {
|
|
62264
62350
|
if (!key.startsWith(API_KEY_PREFIX)) {
|
|
62265
|
-
|
|
62351
|
+
log20.debug("Invalid key format");
|
|
62266
62352
|
return null;
|
|
62267
62353
|
}
|
|
62268
62354
|
const keyHash = await this.hashKey(key);
|
|
@@ -62293,7 +62379,7 @@ class ApiKeyService {
|
|
|
62293
62379
|
}
|
|
62294
62380
|
const [apiKey] = await this.db.select().from(apiKeys).where(and(eq2(apiKeys.keyHash, keyHash), eq2(apiKeys.status, "active"), or(isNull(apiKeys.expiresAt), gt(apiKeys.expiresAt, new Date)))).limit(1);
|
|
62295
62381
|
if (!apiKey) {
|
|
62296
|
-
|
|
62382
|
+
log20.debug("Key not found or invalid");
|
|
62297
62383
|
return null;
|
|
62298
62384
|
}
|
|
62299
62385
|
const cachedData = {
|
|
@@ -62333,12 +62419,12 @@ class ApiKeyService {
|
|
|
62333
62419
|
if (ip) {
|
|
62334
62420
|
updates.lastUsedIp = ip;
|
|
62335
62421
|
}
|
|
62336
|
-
this.db.update(apiKeys).set(updates).where(eq2(apiKeys.id, keyId)).then(() => {}).catch((err2) =>
|
|
62422
|
+
this.db.update(apiKeys).set(updates).where(eq2(apiKeys.id, keyId)).then(() => {}).catch((err2) => log20.error("Failed to update key usage", { error: String(err2) }));
|
|
62337
62423
|
}
|
|
62338
62424
|
async invalidateCacheForKey(id) {
|
|
62339
62425
|
const key = await this.getById(id);
|
|
62340
62426
|
if (key) {
|
|
62341
|
-
|
|
62427
|
+
log20.debug("Cache invalidation requested for key", { id });
|
|
62342
62428
|
}
|
|
62343
62429
|
}
|
|
62344
62430
|
async create(options) {
|
|
@@ -62365,7 +62451,7 @@ class ApiKeyService {
|
|
|
62365
62451
|
if (!created) {
|
|
62366
62452
|
throw new Error("Failed to create API key");
|
|
62367
62453
|
}
|
|
62368
|
-
|
|
62454
|
+
log20.info("API key created", { id: created.id, name: created.name });
|
|
62369
62455
|
return {
|
|
62370
62456
|
key: created,
|
|
62371
62457
|
plainTextKey
|
|
@@ -62400,7 +62486,7 @@ class ApiKeyService {
|
|
|
62400
62486
|
const [updated] = await this.db.update(apiKeys).set(updates).where(eq2(apiKeys.id, id)).returning();
|
|
62401
62487
|
if (updated) {
|
|
62402
62488
|
await apiKeyCache.delete(CacheKeys.apiKey(updated.keyHash));
|
|
62403
|
-
|
|
62489
|
+
log20.info("API key updated", { id, fields: Object.keys(options) });
|
|
62404
62490
|
}
|
|
62405
62491
|
return updated ?? null;
|
|
62406
62492
|
}
|
|
@@ -62425,7 +62511,7 @@ class ApiKeyService {
|
|
|
62425
62511
|
}).where(eq2(apiKeys.id, id)).returning();
|
|
62426
62512
|
if (revoked) {
|
|
62427
62513
|
await apiKeyCache.delete(CacheKeys.apiKey(revoked.keyHash));
|
|
62428
|
-
|
|
62514
|
+
log20.info("API key revoked", { id, reason });
|
|
62429
62515
|
}
|
|
62430
62516
|
return revoked ?? null;
|
|
62431
62517
|
}
|
|
@@ -62465,12 +62551,12 @@ class ApiKeyService {
|
|
|
62465
62551
|
keyHash = await this.hashKey(envKey);
|
|
62466
62552
|
keyPrefix = this.getKeyPrefix(envKey);
|
|
62467
62553
|
isFromEnv = true;
|
|
62468
|
-
|
|
62554
|
+
log20.info("Using primary API key from OMNI_API_KEY environment variable");
|
|
62469
62555
|
} else {
|
|
62470
62556
|
plainTextKey = this.generateKey();
|
|
62471
62557
|
keyHash = await this.hashKey(plainTextKey);
|
|
62472
62558
|
keyPrefix = this.getKeyPrefix(plainTextKey);
|
|
62473
|
-
|
|
62559
|
+
log20.info("Generated new primary API key");
|
|
62474
62560
|
}
|
|
62475
62561
|
const data2 = {
|
|
62476
62562
|
name: PRIMARY_KEY_NAME,
|
|
@@ -62511,13 +62597,13 @@ class ApiKeyService {
|
|
|
62511
62597
|
return `${API_KEY_PREFIX}${keyPrefix}${"*".repeat(24)}`;
|
|
62512
62598
|
}
|
|
62513
62599
|
}
|
|
62514
|
-
var
|
|
62600
|
+
var log20, API_KEY_PREFIX = "omni_sk_", PRIMARY_KEY_NAME = "__primary__";
|
|
62515
62601
|
var init_api_keys = __esm(() => {
|
|
62516
62602
|
init_src();
|
|
62517
62603
|
init_src3();
|
|
62518
62604
|
init_drizzle_orm();
|
|
62519
62605
|
init_cache2();
|
|
62520
|
-
|
|
62606
|
+
log20 = createLogger("api-keys");
|
|
62521
62607
|
});
|
|
62522
62608
|
|
|
62523
62609
|
// ../api/src/constants/profiles.ts
|
|
@@ -67023,7 +67109,7 @@ var require_node3 = __commonJS((exports, module) => {
|
|
|
67023
67109
|
var tty3 = __require("tty");
|
|
67024
67110
|
var util3 = __require("util");
|
|
67025
67111
|
exports.init = init;
|
|
67026
|
-
exports.log =
|
|
67112
|
+
exports.log = log21;
|
|
67027
67113
|
exports.formatArgs = formatArgs;
|
|
67028
67114
|
exports.save = save;
|
|
67029
67115
|
exports.load = load2;
|
|
@@ -67155,7 +67241,7 @@ var require_node3 = __commonJS((exports, module) => {
|
|
|
67155
67241
|
}
|
|
67156
67242
|
return new Date().toISOString() + " ";
|
|
67157
67243
|
}
|
|
67158
|
-
function
|
|
67244
|
+
function log21(...args) {
|
|
67159
67245
|
return process.stderr.write(util3.formatWithOptions(exports.inspectOpts, ...args) + `
|
|
67160
67246
|
`);
|
|
67161
67247
|
}
|
|
@@ -69655,7 +69741,7 @@ var require_debug_logger = __commonJS((exports) => {
|
|
|
69655
69741
|
function isEnabled() {
|
|
69656
69742
|
return _getLoggerSettings().enabled;
|
|
69657
69743
|
}
|
|
69658
|
-
function
|
|
69744
|
+
function log21(...args) {
|
|
69659
69745
|
_maybeLog("log", ...args);
|
|
69660
69746
|
}
|
|
69661
69747
|
function warn2(...args) {
|
|
@@ -69684,7 +69770,7 @@ var require_debug_logger = __commonJS((exports) => {
|
|
|
69684
69770
|
enable,
|
|
69685
69771
|
disable,
|
|
69686
69772
|
isEnabled,
|
|
69687
|
-
log:
|
|
69773
|
+
log: log21,
|
|
69688
69774
|
warn: warn2,
|
|
69689
69775
|
error: error2
|
|
69690
69776
|
};
|
|
@@ -74683,13 +74769,13 @@ var require_internal = __commonJS((exports) => {
|
|
|
74683
74769
|
setLogAttribute(processedLogAttributes, "sentry.trace.parent_span_id", span?.spanContext().spanId);
|
|
74684
74770
|
const processedLog = { ...beforeLog, attributes: processedLogAttributes };
|
|
74685
74771
|
client.emit("beforeCaptureLog", processedLog);
|
|
74686
|
-
const
|
|
74687
|
-
if (!
|
|
74772
|
+
const log21 = beforeSendLog ? debugLogger.consoleSandbox(() => beforeSendLog(processedLog)) : processedLog;
|
|
74773
|
+
if (!log21) {
|
|
74688
74774
|
client.recordDroppedEvent("before_send", "log_item", 1);
|
|
74689
74775
|
debugBuild.DEBUG_BUILD && debugLogger.debug.warn("beforeSendLog returned null, log will not be captured.");
|
|
74690
74776
|
return;
|
|
74691
74777
|
}
|
|
74692
|
-
const { level, message: message2, attributes: logAttributes = {}, severityNumber } =
|
|
74778
|
+
const { level, message: message2, attributes: logAttributes = {}, severityNumber } = log21;
|
|
74693
74779
|
const serializedLog = {
|
|
74694
74780
|
timestamp: time3.timestampInSeconds(),
|
|
74695
74781
|
level,
|
|
@@ -74702,7 +74788,7 @@ var require_internal = __commonJS((exports) => {
|
|
|
74702
74788
|
}
|
|
74703
74789
|
};
|
|
74704
74790
|
captureSerializedLog(client, serializedLog);
|
|
74705
|
-
client.emit("afterCaptureLog",
|
|
74791
|
+
client.emit("afterCaptureLog", log21);
|
|
74706
74792
|
}
|
|
74707
74793
|
function _INTERNAL_flushLogsBuffer(client, maybeLogBuffer) {
|
|
74708
74794
|
const logBuffer = maybeLogBuffer ?? _INTERNAL_getLogBuffer(client) ?? [];
|
|
@@ -75740,12 +75826,12 @@ Reason: ${reason}`);
|
|
|
75740
75826
|
weight += 8;
|
|
75741
75827
|
return weight + estimateAttributesSizeInBytes(metric.attributes);
|
|
75742
75828
|
}
|
|
75743
|
-
function estimateLogSizeInBytes(
|
|
75829
|
+
function estimateLogSizeInBytes(log21) {
|
|
75744
75830
|
let weight = 0;
|
|
75745
|
-
if (
|
|
75746
|
-
weight +=
|
|
75831
|
+
if (log21.message) {
|
|
75832
|
+
weight += log21.message.length * 2;
|
|
75747
75833
|
}
|
|
75748
|
-
return weight + estimateAttributesSizeInBytes(
|
|
75834
|
+
return weight + estimateAttributesSizeInBytes(log21.attributes);
|
|
75749
75835
|
}
|
|
75750
75836
|
function estimateAttributesSizeInBytes(attributes) {
|
|
75751
75837
|
if (!attributes) {
|
|
@@ -76146,7 +76232,7 @@ var require_offline = __commonJS((exports) => {
|
|
|
76146
76232
|
var START_DELAY = 5000;
|
|
76147
76233
|
var MAX_DELAY = 3600000;
|
|
76148
76234
|
function makeOfflineTransport(createTransport) {
|
|
76149
|
-
function
|
|
76235
|
+
function log21(...args) {
|
|
76150
76236
|
debugBuild.DEBUG_BUILD && debugLogger.debug.log("[Offline]:", ...args);
|
|
76151
76237
|
}
|
|
76152
76238
|
return (options3) => {
|
|
@@ -76174,10 +76260,10 @@ var require_offline = __commonJS((exports) => {
|
|
|
76174
76260
|
flushTimer = undefined;
|
|
76175
76261
|
const found = await store.shift();
|
|
76176
76262
|
if (found) {
|
|
76177
|
-
|
|
76263
|
+
log21("Attempting to send previously queued event");
|
|
76178
76264
|
found[0].sent_at = new Date().toISOString();
|
|
76179
76265
|
send(found, true).catch((e2) => {
|
|
76180
|
-
|
|
76266
|
+
log21("Failed to retry sending", e2);
|
|
76181
76267
|
});
|
|
76182
76268
|
}
|
|
76183
76269
|
}, delay));
|
|
@@ -76221,7 +76307,7 @@ var require_offline = __commonJS((exports) => {
|
|
|
76221
76307
|
await store.push(envelope$1);
|
|
76222
76308
|
}
|
|
76223
76309
|
flushWithBackOff();
|
|
76224
|
-
|
|
76310
|
+
log21("Error sending. Event queued.", e2);
|
|
76225
76311
|
return {};
|
|
76226
76312
|
} else {
|
|
76227
76313
|
throw e2;
|
|
@@ -77562,8 +77648,8 @@ var require_console = __commonJS((exports) => {
|
|
|
77562
77648
|
return function(...args) {
|
|
77563
77649
|
const handlerData = { args, level };
|
|
77564
77650
|
handlers.triggerHandlers("console", handlerData);
|
|
77565
|
-
const
|
|
77566
|
-
|
|
77651
|
+
const log21 = debugLogger.originalConsoleMethods[level];
|
|
77652
|
+
log21?.apply(worldwide.GLOBAL_OBJ.console, args);
|
|
77567
77653
|
};
|
|
77568
77654
|
});
|
|
77569
77655
|
});
|
|
@@ -91772,7 +91858,7 @@ var require_local_variables_async = __commonJS((exports) => {
|
|
|
91772
91858
|
var debug = require_debug();
|
|
91773
91859
|
var common3 = require_common2();
|
|
91774
91860
|
var base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjQzLjAgKDNmYjgxMDIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIHR9ZnJvbSJub2RlOndvcmtlcl90aHJlYWRzIjtjb25zdCBuPWdsb2JhbFRoaXMsaT17fTtjb25zdCBvPSJfX1NFTlRSWV9FUlJPUl9MT0NBTF9WQVJJQUJMRVNfXyI7Y29uc3QgYT10O2Z1bmN0aW9uIHMoLi4uZSl7YS5kZWJ1ZyYmZnVuY3Rpb24oZSl7aWYoISgiY29uc29sZSJpbiBuKSlyZXR1cm4gZSgpO2NvbnN0IHQ9bi5jb25zb2xlLG89e30sYT1PYmplY3Qua2V5cyhpKTthLmZvckVhY2goZT0+e2NvbnN0IG49aVtlXTtvW2VdPXRbZV0sdFtlXT1ufSk7dHJ5e3JldHVybiBlKCl9ZmluYWxseXthLmZvckVhY2goZT0+e3RbZV09b1tlXX0pfX0oKCk9PmNvbnNvbGUubG9nKCJbTG9jYWxWYXJpYWJsZXMgV29ya2VyXSIsLi4uZSkpfWFzeW5jIGZ1bmN0aW9uIGMoZSx0LG4saSl7Y29uc3Qgbz1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pO2lbbl09by5yZXN1bHQuZmlsdGVyKGU9PiJsZW5ndGgiIT09ZS5uYW1lJiYhaXNOYU4ocGFyc2VJbnQoZS5uYW1lLDEwKSkpLnNvcnQoKGUsdCk9PnBhcnNlSW50KGUubmFtZSwxMCktcGFyc2VJbnQodC5uYW1lLDEwKSkubWFwKGU9PmUudmFsdWU/LnZhbHVlKX1hc3luYyBmdW5jdGlvbiByKGUsdCxuLGkpe2NvbnN0IG89YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDp0LG93blByb3BlcnRpZXM6ITB9KTtpW25dPW8ucmVzdWx0Lm1hcChlPT5bZS5uYW1lLGUudmFsdWU/LnZhbHVlXSkucmVkdWNlKChlLFt0LG5dKT0+KGVbdF09bixlKSx7fSl9ZnVuY3Rpb24gdShlLHQpe2UudmFsdWUmJigidmFsdWUiaW4gZS52YWx1ZT92b2lkIDA9PT1lLnZhbHVlLnZhbHVlfHxudWxsPT09ZS52YWx1ZS52YWx1ZT90W2UubmFtZV09YDwke2UudmFsdWUudmFsdWV9PmA6dFtlLm5hbWVdPWUudmFsdWUudmFsdWU6ImRlc2NyaXB0aW9uImluIGUudmFsdWUmJiJmdW5jdGlvbiIhPT1lLnZhbHVlLnR5cGU/dFtlLm5hbWVdPWA8JHtlLnZhbHVlLmRlc2NyaXB0aW9ufT5gOiJ1bmRlZmluZWQiPT09ZS52YWx1ZS50eXBlJiYodFtlLm5hbWVdPSI8dW5kZWZpbmVkPiIpKX1hc3luYyBmdW5jdGlvbiBsKGUsdCl7Y29uc3Qgbj1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuZ2V0UHJvcGVydGllcyIse29iamVjdElkOnQsb3duUHJvcGVydGllczohMH0pLGk9e307Zm9yKGNvbnN0IHQgb2Ygbi5yZXN1bHQpaWYodC52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT10LnZhbHVlLmNsYXNzTmFtZSl7Y29uc3Qgbj10LnZhbHVlLm9iamVjdElkO2F3YWl0IGMoZSxuLHQubmFtZSxpKX1lbHNlIGlmKHQudmFsdWU/Lm9iamVjdElkJiYiT2JqZWN0Ij09PXQudmFsdWUuY2xhc3NOYW1lKXtjb25zdCBuPXQudmFsdWUub2JqZWN0SWQ7YXdhaXQgcihlLG4sdC5uYW1lLGkpfWVsc2UgdC52YWx1ZSYmdSh0LGkpO3JldHVybiBpfWxldCBmOyhhc3luYyBmdW5jdGlvbigpe2NvbnN0IHQ9bmV3IGU7dC5jb25uZWN0VG9NYWluVGhyZWFkKCkscygiQ29ubmVjdGVkIHRvIG1haW4gdGhyZWFkIik7bGV0IG49ITE7dC5vbigiRGVidWdnZXIucmVzdW1lZCIsKCk9PntuPSExfSksdC5vbigiRGVidWdnZXIucGF1c2VkIixlPT57bj0hMCxhc3luYyBmdW5jdGlvbihlLHtyZWFzb246dCxkYXRhOntvYmplY3RJZDpufSxjYWxsRnJhbWVzOml9KXtpZigiZXhjZXB0aW9uIiE9PXQmJiJwcm9taXNlUmVqZWN0aW9uIiE9PXQpcmV0dXJuO2lmKGY/LigpLG51bGw9PW4pcmV0dXJuO2NvbnN0IGE9W107Zm9yKGxldCB0PTA7dDxpLmxlbmd0aDt0Kyspe2NvbnN0e3Njb3BlQ2hhaW46bixmdW5jdGlvbk5hbWU6byx0aGlzOnN9PWlbdF0sYz1uLmZpbmQoZT0+ImxvY2FsIj09PWUudHlwZSkscj0iZ2xvYmFsIiE9PXMuY2xhc3NOYW1lJiZzLmNsYXNzTmFtZT9gJHtzLmNsYXNzTmFtZX0uJHtvfWA6bztpZih2b2lkIDA9PT1jPy5vYmplY3Qub2JqZWN0SWQpYVt0XT17ZnVuY3Rpb246cn07ZWxzZXtjb25zdCBuPWF3YWl0IGwoZSxjLm9iamVjdC5vYmplY3RJZCk7YVt0XT17ZnVuY3Rpb246cix2YXJzOm59fX1hd2FpdCBlLnBvc3QoIlJ1bnRpbWUuY2FsbEZ1bmN0aW9uT24iLHtmdW5jdGlvbkRlY2xhcmF0aW9uOmBmdW5jdGlvbigpIHsgdGhpcy4ke299ID0gdGhpcy4ke299IHx8ICR7SlNPTi5zdHJpbmdpZnkoYSl9OyB9YCxzaWxlbnQ6ITAsb2JqZWN0SWQ6bn0pLGF3YWl0IGUucG9zdCgiUnVudGltZS5yZWxlYXNlT2JqZWN0Iix7b2JqZWN0SWQ6bn0pfSh0LGUucGFyYW1zKS50aGVuKGFzeW5jKCk9PntuJiZhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpfSxhc3luYyBlPT57biYmYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKX0pfSksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5lbmFibGUiKTtjb25zdCBpPSExIT09YS5jYXB0dXJlQWxsRXhjZXB0aW9ucztpZihhd2FpdCB0LnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6aT8iYWxsIjoidW5jYXVnaHQifSksaSl7Y29uc3QgZT1hLm1heEV4Y2VwdGlvbnNQZXJTZWNvbmR8fDUwO2Y9ZnVuY3Rpb24oZSx0LG4pe2xldCBpPTAsbz01LGE9MDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCk9PnswPT09YT9pPmUmJihvKj0yLG4obyksbz44NjQwMCYmKG89ODY0MDApLGE9byk6KGEtPTEsMD09PWEmJnQoKSksaT0wfSwxZTMpLnVucmVmKCksKCk9PntpKz0xfX0oZSxhc3luYygpPT57cygiUmF0ZS1saW1pdCBsaWZ0ZWQuIiksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJhbGwifSl9LGFzeW5jIGU9PntzKGBSYXRlLWxpbWl0IGV4Y2VlZGVkLiBEaXNhYmxpbmcgY2FwdHVyaW5nIG9mIGNhdWdodCBleGNlcHRpb25zIGZvciAke2V9IHNlY29uZHMuYCksYXdhaXQgdC5wb3N0KCJEZWJ1Z2dlci5zZXRQYXVzZU9uRXhjZXB0aW9ucyIse3N0YXRlOiJ1bmNhdWdodCJ9KX0pfX0pKCkuY2F0Y2goZT0+e3MoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSxzZXRJbnRlcnZhbCgoKT0+e30sMWU0KTs=";
|
|
91775
|
-
function
|
|
91861
|
+
function log21(...args) {
|
|
91776
91862
|
core.debug.log("[LocalVariables]", ...args);
|
|
91777
91863
|
}
|
|
91778
91864
|
var localVariablesAsyncIntegration = core.defineIntegration((integrationOptions = {}) => {
|
|
@@ -91816,10 +91902,10 @@ var require_local_variables_async = __commonJS((exports) => {
|
|
|
91816
91902
|
worker.terminate();
|
|
91817
91903
|
});
|
|
91818
91904
|
worker.once("error", (err2) => {
|
|
91819
|
-
|
|
91905
|
+
log21("Worker error", err2);
|
|
91820
91906
|
});
|
|
91821
91907
|
worker.once("exit", (code) => {
|
|
91822
|
-
|
|
91908
|
+
log21("Worker exit", code);
|
|
91823
91909
|
});
|
|
91824
91910
|
worker.unref();
|
|
91825
91911
|
}
|
|
@@ -93073,9 +93159,9 @@ var require_client2 = __commonJS((exports) => {
|
|
|
93073
93159
|
core._INTERNAL_flushLogsBuffer(this);
|
|
93074
93160
|
};
|
|
93075
93161
|
if (serverName) {
|
|
93076
|
-
this.on("beforeCaptureLog", (
|
|
93077
|
-
|
|
93078
|
-
...
|
|
93162
|
+
this.on("beforeCaptureLog", (log21) => {
|
|
93163
|
+
log21.attributes = {
|
|
93164
|
+
...log21.attributes,
|
|
93079
93165
|
"server.address": serverName
|
|
93080
93166
|
};
|
|
93081
93167
|
});
|
|
@@ -93400,7 +93486,7 @@ var require_anr2 = __commonJS((exports) => {
|
|
|
93400
93486
|
var base64WorkerScript = "LyohIEBzZW50cnkvbm9kZS1jb3JlIDEwLjQzLjAgKDNmYjgxMDIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20ibm9kZTppbnNwZWN0b3IiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyBlfWZyb20ibm9kZTp3b3JrZXJfdGhyZWFkcyI7aW1wb3J0e3Bvc2l4IGFzIHIsc2VwIGFzIG99ZnJvbSJub2RlOnBhdGgiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgcyBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ibm9kZTpzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJub2RlOnpsaWIiO2ltcG9ydCphcyBhIGZyb20ibm9kZTpuZXQiO2ltcG9ydCphcyBmIGZyb20ibm9kZTp0bHMiO2NvbnN0IGg9InVuZGVmaW5lZCI9PXR5cGVvZiBfX1NFTlRSWV9ERUJVR19ffHxfX1NFTlRSWV9ERUJVR19fLHA9Z2xvYmFsVGhpcyxkPSIxMC40My4wIjtmdW5jdGlvbiBsKCl7cmV0dXJuIG0ocCkscH1mdW5jdGlvbiBtKHQpe2NvbnN0IG49dC5fX1NFTlRSWV9fPXQuX19TRU5UUllfX3x8e307cmV0dXJuIG4udmVyc2lvbj1uLnZlcnNpb258fGQsbltkXT1uW2RdfHx7fX1mdW5jdGlvbiBnKHQsbixlPXApe2NvbnN0IHI9ZS5fX1NFTlRSWV9fPWUuX19TRU5UUllfX3x8e30sbz1yW2RdPXJbZF18fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHk9e307ZnVuY3Rpb24gYih0KXtpZighKCJjb25zb2xlImluIHApKXJldHVybiB0KCk7Y29uc3Qgbj1wLmNvbnNvbGUsZT17fSxyPU9iamVjdC5rZXlzKHkpO3IuZm9yRWFjaCh0PT57Y29uc3Qgcj15W3RdO2VbdF09blt0XSxuW3RdPXJ9KTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCh0PT57blt0XT1lW3RdfSl9fWZ1bmN0aW9uIHYoKXtyZXR1cm4gdygpLmVuYWJsZWR9ZnVuY3Rpb24gXyh0LC4uLm4pe2gmJnYoKSYmYigoKT0+e3AuY29uc29sZVt0XShgU2VudHJ5IExvZ2dlciBbJHt0fV06YCwuLi5uKX0pfWZ1bmN0aW9uIHcoKXtyZXR1cm4gaD9nKCJsb2dnZXJTZXR0aW5ncyIsKCk9Pih7ZW5hYmxlZDohMX0pKTp7ZW5hYmxlZDohMX19Y29uc3QgUz17ZW5hYmxlOmZ1bmN0aW9uKCl7dygpLmVuYWJsZWQ9ITB9LGRpc2FibGU6ZnVuY3Rpb24oKXt3KCkuZW5hYmxlZD0hMX0saXNFbmFibGVkOnYsbG9nOmZ1bmN0aW9uKC4uLnQpe18oImxvZyIsLi4udCl9LHdhcm46ZnVuY3Rpb24oLi4udCl7Xygid2FybiIsLi4udCl9LGVycm9yOmZ1bmN0aW9uKC4uLnQpe18oImVycm9yIiwuLi50KX19LCQ9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2Z1bmN0aW9uIEUodCl7cmV0dXJuIHRbdC5sZW5ndGgtMV18fHt9fWNvbnN0IHg9Ijxhbm9ueW1vdXM+Ijtjb25zdCBOPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7ZnVuY3Rpb24gQyh0LG4pe3JldHVybiBOLmNhbGwodCk9PT1gW29iamVjdCAke259XWB9ZnVuY3Rpb24gQSh0KXtyZXR1cm4gQyh0LCJTdHJpbmciKX1mdW5jdGlvbiBqKHQpe3JldHVybiBDKHQsIk9iamVjdCIpfWZ1bmN0aW9uIGsodCl7cmV0dXJuIEJvb2xlYW4odD8udGhlbiYmImZ1bmN0aW9uIj09dHlwZW9mIHQudGhlbil9ZnVuY3Rpb24gVCh0LG4pe3RyeXtyZXR1cm4gdCBpbnN0YW5jZW9mIG59Y2F0Y2h7cmV0dXJuITF9fWNvbnN0IEk9cDtmdW5jdGlvbiBSKHQsbil7Y29uc3QgZT10LHI9W107aWYoIWU/LnRhZ05hbWUpcmV0dXJuIiI7aWYoSS5IVE1MRWxlbWVudCYmZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZlLmRhdGFzZXQpe2lmKGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYoZS5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIGUuZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3Qgbz1uPy5sZW5ndGg/bi5maWx0ZXIodD0+ZS5nZXRBdHRyaWJ1dGUodCkpLm1hcCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pOm51bGw7aWYobz8ubGVuZ3RoKW8uZm9yRWFjaCh0PT57ci5wdXNoKGBbJHt0WzBdfT0iJHt0WzFdfSJdYCl9KTtlbHNle2UuaWQmJnIucHVzaChgIyR7ZS5pZH1gKTtjb25zdCB0PWUuY2xhc3NOYW1lO2lmKHQmJkEodCkpe2NvbnN0IG49dC5zcGxpdCgvXHMrLyk7Zm9yKGNvbnN0IHQgb2YgbilyLnB1c2goYC4ke3R9YCl9fWNvbnN0IGk9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcihjb25zdCB0IG9mIGkpe2NvbnN0IG49ZS5nZXRBdHRyaWJ1dGUodCk7biYmci5wdXNoKGBbJHt0fT0iJHtufSJdYCl9cmV0dXJuIHIuam9pbigiIil9ZnVuY3Rpb24gTyh0KXtpZihmdW5jdGlvbih0KXtzd2l0Y2goTi5jYWxsKHQpKXtjYXNlIltvYmplY3QgRXJyb3JdIjpjYXNlIltvYmplY3QgRXhjZXB0aW9uXSI6Y2FzZSJbb2JqZWN0IERPTUV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBXZWJBc3NlbWJseS5FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBUKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uRCh0KX07aWYobj10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJlQobixFdmVudCkpe2NvbnN0IG49e3R5cGU6dC50eXBlLHRhcmdldDpQKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlAodC5jdXJyZW50VGFyZ2V0KSwuLi5EKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZUKHQsQ3VzdG9tRXZlbnQpJiYobi5kZXRhaWw9dC5kZXRhaWwpLG59cmV0dXJuIHQ7dmFyIG59ZnVuY3Rpb24gUCh0KXt0cnl7cmV0dXJuIG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJlQobixFbGVtZW50KT9mdW5jdGlvbih0LG49e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgZT10O2NvbnN0IHI9NSxvPVtdO2xldCBpPTAscz0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkobik/bjpuLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkobikmJm4ubWF4U3RyaW5nTGVuZ3RofHw4MDtmb3IoO2UmJmkrKzxyJiYoYT1SKGUsZiksISgiaHRtbCI9PT1hfHxpPjEmJnMrby5sZW5ndGgqdSthLmxlbmd0aD49aCkpOylvLnB1c2goYSkscys9YS5sZW5ndGgsZT1lLnBhcmVudE5vZGU7cmV0dXJuIG8ucmV2ZXJzZSgpLmpvaW4oYyl9Y2F0Y2h7cmV0dXJuIjx1bmtub3duPiJ9fSh0KTpPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCl9Y2F0Y2h7cmV0dXJuIjx1bmtub3duPiJ9dmFyIG59ZnVuY3Rpb24gRCh0KXtpZigib2JqZWN0Ij09dHlwZW9mIHQmJm51bGwhPT10KXtjb25zdCBuPXt9O2Zvcihjb25zdCBlIGluIHQpT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQsZSkmJihuW2VdPXRbZV0pO3JldHVybiBufXJldHVybnt9fWxldCBVLE07ZnVuY3Rpb24gTCh0KXtpZih2b2lkIDAhPT1VKXJldHVybiBVP1UodCk6dCgpO2NvbnN0IG49U3ltYm9sLmZvcigiX19TRU5UUllfU0FGRV9SQU5ET01fSURfV1JBUFBFUl9fIiksZT1wO3JldHVybiBuIGluIGUmJiJmdW5jdGlvbiI9PXR5cGVvZiBlW25dPyhVPWVbbl0sVSh0KSk6KFU9bnVsbCx0KCkpfWZ1bmN0aW9uIEIoKXtyZXR1cm4gTCgoKT0+TWF0aC5yYW5kb20oKSl9ZnVuY3Rpb24gVygpe3JldHVybiBMKCgpPT5EYXRlLm5vdygpKX1mdW5jdGlvbiB6KHQsbj0wKXtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIHR8fDA9PT1ufHx0Lmxlbmd0aDw9bj90OmAke3Quc2xpY2UoMCxuKX0uLi5gfWZ1bmN0aW9uIEYodD1mdW5jdGlvbigpe2NvbnN0IHQ9cDtyZXR1cm4gdC5jcnlwdG98fHQubXNDcnlwdG99KCkpe3RyeXtpZih0Py5yYW5kb21VVUlEKXJldHVybiBMKCgpPT50LnJhbmRvbVVVSUQoKSkucmVwbGFjZSgvLS9nLCIiKX1jYXRjaHt9cmV0dXJuIE18fChNPVsxZTddKzFlMys0ZTMrOGUzKzFlMTEpLE0ucmVwbGFjZSgvWzAxOF0vZyx0PT4odF4oMTYqQigpJjE1KT4+dC80KS50b1N0cmluZygxNikpfWZ1bmN0aW9uIEcoKXtyZXR1cm4gVygpLzFlM31sZXQgSDtmdW5jdGlvbiBKKCl7cmV0dXJuKEg/PyhIPWZ1bmN0aW9uKCl7Y29uc3R7cGVyZm9ybWFuY2U6dH09cDtpZighdD8ubm93fHwhdC50aW1lT3JpZ2luKXJldHVybiBHO2NvbnN0IG49dC50aW1lT3JpZ2luO3JldHVybigpPT4obitMKCgpPT50Lm5vdygpKSkvMWUzfSgpKSkoKX1mdW5jdGlvbiBZKHQpe2NvbnN0IG49SigpLGU9e3NpZDpGKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybntzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19fShlKX07cmV0dXJuIHQmJlYoZSx0KSxlfWZ1bmN0aW9uIFYodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8SigpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6RigpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9ZnVuY3Rpb24gSyh0LG4sZT0yKXtpZighbnx8Im9iamVjdCIhPXR5cGVvZiBufHxlPD0wKXJldHVybiBuO2lmKHQmJjA9PT1PYmplY3Qua2V5cyhuKS5sZW5ndGgpcmV0dXJuIHQ7Y29uc3Qgcj17Li4udH07Zm9yKGNvbnN0IHQgaW4gbilPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobix0KSYmKHJbdF09SyhyW3RdLG5bdF0sZS0xKSk7cmV0dXJuIHJ9ZnVuY3Rpb24gWigpe3JldHVybiBGKCl9ZnVuY3Rpb24gcSgpe3JldHVybiBGKCkuc3Vic3RyaW5nKDE2KX1jb25zdCBRPSJfc2VudHJ5U3BhbiI7ZnVuY3Rpb24gWCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoe2gmJlMubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxRLG4pOmRlbGV0ZSB0W1FdfWZ1bmN0aW9uIHR0KHQpe3JldHVybiB0W1FdfWNsYXNzIG50e2NvbnN0cnVjdG9yKCl7dGhpcy50PSExLHRoaXMubz1bXSx0aGlzLmk9W10sdGhpcy51PVtdLHRoaXMuaD1bXSx0aGlzLnA9e30sdGhpcy5sPXt9LHRoaXMubT17fSx0aGlzLnY9e30sdGhpcy5fPXt9LHRoaXMuUz17fSx0aGlzLk49e3RyYWNlSWQ6WigpLHNhbXBsZVJhbmQ6QigpfX1jbG9uZSgpe2NvbnN0IHQ9bmV3IG50O3JldHVybiB0LnU9Wy4uLnRoaXMudV0sdC5sPXsuLi50aGlzLmx9LHQubT17Li4udGhpcy5tfSx0LnY9ey4uLnRoaXMudn0sdC5fPXsuLi50aGlzLl99LHRoaXMuXy5mbGFncyYmKHQuXy5mbGFncz17dmFsdWVzOlsuLi50aGlzLl8uZmxhZ3MudmFsdWVzXX0pLHQucD10aGlzLnAsdC5DPXRoaXMuQyx0LkE9dGhpcy5BLHQuaj10aGlzLmosdC5rPXRoaXMuayx0Lmk9Wy4uLnRoaXMuaV0sdC5oPVsuLi50aGlzLmhdLHQuUz17Li4udGhpcy5TfSx0Lk49ey4uLnRoaXMuTn0sdC5UPXRoaXMuVCx0Lkk9dGhpcy5JLHQuUj10aGlzLlIsWCh0LHR0KHRoaXMpKSx0fXNldENsaWVudCh0KXt0aGlzLlQ9dH1zZXRMYXN0RXZlbnRJZCh0KXt0aGlzLkk9dH1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5UfWxhc3RFdmVudElkKCl7cmV0dXJuIHRoaXMuSX1hZGRTY29wZUxpc3RlbmVyKHQpe3RoaXMuby5wdXNoKHQpfWFkZEV2ZW50UHJvY2Vzc29yKHQpe3JldHVybiB0aGlzLmkucHVzaCh0KSx0aGlzfXNldFVzZXIodCl7cmV0dXJuIHRoaXMucD10fHx7ZW1haWw6dm9pZCAwLGlkOnZvaWQgMCxpcF9hZGRyZXNzOnZvaWQgMCx1c2VybmFtZTp2b2lkIDB9LHRoaXMuQSYmVih0aGlzLkEse3VzZXI6dH0pLHRoaXMuTygpLHRoaXN9Z2V0VXNlcigpe3JldHVybiB0aGlzLnB9c2V0Q29udmVyc2F0aW9uSWQodCl7cmV0dXJuIHRoaXMuUj10fHx2b2lkIDAsdGhpcy5PKCksdGhpc31zZXRUYWdzKHQpe3JldHVybiB0aGlzLmw9ey4uLnRoaXMubCwuLi50fSx0aGlzLk8oKSx0aGlzfXNldFRhZyh0LG4pe3JldHVybiB0aGlzLnNldFRhZ3Moe1t0XTpufSl9c2V0QXR0cmlidXRlcyh0KXtyZXR1cm4gdGhpcy5tPXsuLi50aGlzLm0sLi4udH0sdGhpcy5PKCksdGhpc31zZXRBdHRyaWJ1dGUodCxuKXtyZXR1cm4gdGhpcy5zZXRBdHRyaWJ1dGVzKHtbdF06bn0pfXJlbW92ZUF0dHJpYnV0ZSh0KXtyZXR1cm4gdCBpbiB0aGlzLm0mJihkZWxldGUgdGhpcy5tW3RdLHRoaXMuTygpKSx0aGlzfXNldEV4dHJhcyh0KXtyZXR1cm4gdGhpcy52PXsuLi50aGlzLnYsLi4udH0sdGhpcy5PKCksdGhpc31zZXRFeHRyYSh0LG4pe3JldHVybiB0aGlzLnY9ey4uLnRoaXMudixbdF06bn0sdGhpcy5PKCksdGhpc31zZXRGaW5nZXJwcmludCh0KXtyZXR1cm4gdGhpcy5rPXQsdGhpcy5PKCksdGhpc31zZXRMZXZlbCh0KXtyZXR1cm4gdGhpcy5DPXQsdGhpcy5PKCksdGhpc31zZXRUcmFuc2FjdGlvbk5hbWUodCl7cmV0dXJuIHRoaXMuaj10LHRoaXMuTygpLHRoaXN9c2V0Q29udGV4dCh0LG4pe3JldHVybiBudWxsPT09bj9kZWxldGUgdGhpcy5fW3RdOnRoaXMuX1t0XT1uLHRoaXMuTygpLHRoaXN9c2V0U2Vzc2lvbih0KXtyZXR1cm4gdD90aGlzLkE9dDpkZWxldGUgdGhpcy5BLHRoaXMuTygpLHRoaXN9Z2V0U2Vzc2lvbigpe3JldHVybiB0aGlzLkF9dXBkYXRlKHQpe2lmKCF0KXJldHVybiB0aGlzO2NvbnN0IG49ImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCh0aGlzKTp0LGU9biBpbnN0YW5jZW9mIG50P24uZ2V0U2NvcGVEYXRhKCk6aihuKT90OnZvaWQgMCx7dGFnczpyLGF0dHJpYnV0ZXM6byxleHRyYTppLHVzZXI6cyxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zixjb252ZXJzYXRpb25JZDpofT1lfHx7fTtyZXR1cm4gdGhpcy5sPXsuLi50aGlzLmwsLi4ucn0sdGhpcy5tPXsuLi50aGlzLm0sLi4ub30sdGhpcy52PXsuLi50aGlzLnYsLi4uaX0sdGhpcy5fPXsuLi50aGlzLl8sLi4uY30scyYmT2JqZWN0LmtleXMocykubGVuZ3RoJiYodGhpcy5wPXMpLHUmJih0aGlzLkM9dSksYS5sZW5ndGgmJih0aGlzLms9YSksZiYmKHRoaXMuTj1mKSxoJiYodGhpcy5SPWgpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy51PVtdLHRoaXMubD17fSx0aGlzLm09e30sdGhpcy52PXt9LHRoaXMucD17fSx0aGlzLl89e30sdGhpcy5DPXZvaWQgMCx0aGlzLmo9dm9pZCAwLHRoaXMuaz12b2lkIDAsdGhpcy5BPXZvaWQgMCx0aGlzLlI9dm9pZCAwLFgodGhpcyx2b2lkIDApLHRoaXMuaD1bXSx0aGlzLnNldFByb3BhZ2F0aW9uQ29udGV4dCh7dHJhY2VJZDpaKCksc2FtcGxlUmFuZDpCKCl9KSx0aGlzLk8oKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxuKXtjb25zdCBlPSJudW1iZXIiPT10eXBlb2Ygbj9uOjEwMDtpZihlPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpHKCksLi4udCxtZXNzYWdlOnQubWVzc2FnZT96KHQubWVzc2FnZSwyMDQ4KTp0Lm1lc3NhZ2V9O3JldHVybiB0aGlzLnUucHVzaChyKSx0aGlzLnUubGVuZ3RoPmUmJih0aGlzLnU9dGhpcy51LnNsaWNlKC1lKSx0aGlzLlQ/LnJlY29yZERyb3BwZWRFdmVudCgiYnVmZmVyX292ZXJmbG93IiwibG9nX2l0ZW0iKSksdGhpcy5PKCksdGhpc31nZXRMYXN0QnJlYWRjcnVtYigpe3JldHVybiB0aGlzLnVbdGhpcy51Lmxlbmd0aC0xXX1jbGVhckJyZWFkY3J1bWJzKCl7cmV0dXJuIHRoaXMudT1bXSx0aGlzLk8oKSx0aGlzfWFkZEF0dGFjaG1lbnQodCl7cmV0dXJuIHRoaXMuaC5wdXNoKHQpLHRoaXN9Y2xlYXJBdHRhY2htZW50cygpe3JldHVybiB0aGlzLmg9W10sdGhpc31nZXRTY29wZURhdGEoKXtyZXR1cm57YnJlYWRjcnVtYnM6dGhpcy51LGF0dGFjaG1lbnRzOnRoaXMuaCxjb250ZXh0czp0aGlzLl8sdGFnczp0aGlzLmwsYXR0cmlidXRlczp0aGlzLm0sZXh0cmE6dGhpcy52LHVzZXI6dGhpcy5wLGxldmVsOnRoaXMuQyxmaW5nZXJwcmludDp0aGlzLmt8fFtdLGV2ZW50UHJvY2Vzc29yczp0aGlzLmkscHJvcGFnYXRpb25Db250ZXh0OnRoaXMuTixzZGtQcm9jZXNzaW5nTWV0YWRhdGE6dGhpcy5TLHRyYW5zYWN0aW9uTmFtZTp0aGlzLmosc3Bhbjp0dCh0aGlzKSxjb252ZXJzYXRpb25JZDp0aGlzLlJ9fXNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh0KXtyZXR1cm4gdGhpcy5TPUsodGhpcy5TLHQsMiksdGhpc31zZXRQcm9wYWdhdGlvbkNvbnRleHQodCl7cmV0dXJuIHRoaXMuTj10LHRoaXN9Z2V0UHJvcGFnYXRpb25Db250ZXh0KCl7cmV0dXJuIHRoaXMuTn1jYXB0dXJlRXhjZXB0aW9uKHQsbil7Y29uc3QgZT1uPy5ldmVudF9pZHx8RigpO2lmKCF0aGlzLlQpcmV0dXJuIGgmJlMud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEiKSxlO2NvbnN0IHI9bmV3IEVycm9yKCJTZW50cnkgc3ludGhldGljRXhjZXB0aW9uIik7cmV0dXJuIHRoaXMuVC5jYXB0dXJlRXhjZXB0aW9uKHQse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOnIsLi4ubixldmVudF9pZDplfSx0aGlzKSxlfWNhcHR1cmVNZXNzYWdlKHQsbixlKXtjb25zdCByPWU/LmV2ZW50X2lkfHxGKCk7aWYoIXRoaXMuVClyZXR1cm4gaCYmUy53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgbWVzc2FnZSEiKSxyO2NvbnN0IG89ZT8uc3ludGhldGljRXhjZXB0aW9uPz9uZXcgRXJyb3IodCk7cmV0dXJuIHRoaXMuVC5jYXB0dXJlTWVzc2FnZSh0LG4se29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOm8sLi4uZSxldmVudF9pZDpyfSx0aGlzKSxyfWNhcHR1cmVFdmVudCh0LG4pe2NvbnN0IGU9dC5ldmVudF9pZHx8bj8uZXZlbnRfaWR8fEYoKTtyZXR1cm4gdGhpcy5UPyh0aGlzLlQuY2FwdHVyZUV2ZW50KHQsey4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZSk6KGgmJlMud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV2ZW50ISIpLGUpfU8oKXt0aGlzLnR8fCh0aGlzLnQ9ITAsdGhpcy5vLmZvckVhY2godD0+e3QodGhpcyl9KSx0aGlzLnQ9ITEpfX1jbGFzcyBldHtjb25zdHJ1Y3Rvcih0LG4pe2xldCBlLHI7ZT10fHxuZXcgbnQscj1ufHxuZXcgbnQsdGhpcy5QPVt7c2NvcGU6ZX1dLHRoaXMuRD1yfXdpdGhTY29wZSh0KXtjb25zdCBuPXRoaXMuVSgpO2xldCBlO3RyeXtlPXQobil9Y2F0Y2godCl7dGhyb3cgdGhpcy5NKCksdH1yZXR1cm4gayhlKT9lLnRoZW4odD0+KHRoaXMuTSgpLHQpLHQ9Pnt0aHJvdyB0aGlzLk0oKSx0fSk6KHRoaXMuTSgpLGUpfWdldENsaWVudCgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuY2xpZW50fWdldFNjb3BlKCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZX1nZXRJc29sYXRpb25TY29wZSgpe3JldHVybiB0aGlzLkR9Z2V0U3RhY2tUb3AoKXtyZXR1cm4gdGhpcy5QW3RoaXMuUC5sZW5ndGgtMV19VSgpe2NvbnN0IHQ9dGhpcy5nZXRTY29wZSgpLmNsb25lKCk7cmV0dXJuIHRoaXMuUC5wdXNoKHtjbGllbnQ6dGhpcy5nZXRDbGllbnQoKSxzY29wZTp0fSksdH1NKCl7cmV0dXJuISh0aGlzLlAubGVuZ3RoPD0xKSYmISF0aGlzLlAucG9wKCl9fWZ1bmN0aW9uIHJ0KCl7Y29uc3QgdD1tKGwoKSk7cmV0dXJuIHQuc3RhY2s9dC5zdGFja3x8bmV3IGV0KGcoImRlZmF1bHRDdXJyZW50U2NvcGUiLCgpPT5uZXcgbnQpLGcoImRlZmF1bHRJc29sYXRpb25TY29wZSIsKCk9Pm5ldyBudCkpfWZ1bmN0aW9uIG90KHQpe3JldHVybiBydCgpLndpdGhTY29wZSh0KX1mdW5jdGlvbiBpdCh0LG4pe2NvbnN0IGU9cnQoKTtyZXR1cm4gZS53aXRoU2NvcGUoKCk9PihlLmdldFN0YWNrVG9wKCkuc2NvcGU9dCxuKHQpKSl9ZnVuY3Rpb24gc3QodCl7cmV0dXJuIHJ0KCkud2l0aFNjb3BlKCgpPT50KHJ0KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKSkpfWZ1bmN0aW9uIGN0KHQpe2NvbnN0IG49bSh0KTtyZXR1cm4gbi5hY3M/bi5hY3M6e3dpdGhJc29sYXRpb25TY29wZTpzdCx3aXRoU2NvcGU6b3Qsd2l0aFNldFNjb3BlOml0LHdpdGhTZXRJc29sYXRpb25TY29wZToodCxuKT0+c3QobiksZ2V0Q3VycmVudFNjb3BlOigpPT5ydCgpLmdldFNjb3BlKCksZ2V0SXNvbGF0aW9uU2NvcGU6KCk9PnJ0KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKX19ZnVuY3Rpb24gdXQoKXtyZXR1cm4gY3QobCgpKS5nZXRDdXJyZW50U2NvcGUoKS5nZXRDbGllbnQoKX1mdW5jdGlvbiBhdCh0KXtpZih0KXtpZigib2JqZWN0Ij09dHlwZW9mIHQmJiJkZXJlZiJpbiB0JiYiZnVuY3Rpb24iPT10eXBlb2YgdC5kZXJlZil0cnl7cmV0dXJuIHQuZGVyZWYoKX1jYXRjaHtyZXR1cm59cmV0dXJuIHR9fWZ1bmN0aW9uIGZ0KHQpe2NvbnN0IG49dDtyZXR1cm57c2NvcGU6bi5fc2VudHJ5U2NvcGUsaXNvbGF0aW9uU2NvcGU6YXQobi5fc2VudHJ5SXNvbGF0aW9uU2NvcGUpfX1jb25zdCBodD0vXnNlbnRyeS0vO2Z1bmN0aW9uIHB0KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7aWYoIXR8fCFBKHQpJiYhQXJyYXkuaXNBcnJheSh0KSlyZXR1cm47aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5yZWR1Y2UoKHQsbik9Pntjb25zdCBlPWR0KG4pO3JldHVybiBPYmplY3QuZW50cmllcyhlKS5mb3JFYWNoKChbbixlXSk9Pnt0W25dPWV9KSx0fSx7fSk7cmV0dXJuIGR0KHQpfSh0KTtpZighbilyZXR1cm47Y29uc3QgZT1PYmplY3QuZW50cmllcyhuKS5yZWR1Y2UoKHQsW24sZV0pPT57aWYobi5tYXRjaChodCkpe3Rbbi5zbGljZSg3KV09ZX1yZXR1cm4gdH0se30pO3JldHVybiBPYmplY3Qua2V5cyhlKS5sZW5ndGg+MD9lOnZvaWQgMH1mdW5jdGlvbiBkdCh0KXtyZXR1cm4gdC5zcGxpdCgiLCIpLm1hcCh0PT57Y29uc3Qgbj10LmluZGV4T2YoIj0iKTtpZigtMT09PW4pcmV0dXJuW107cmV0dXJuW3Quc2xpY2UoMCxuKSx0LnNsaWNlKG4rMSldLm1hcCh0PT57dHJ5e3JldHVybiBkZWNvZGVVUklDb21wb25lbnQodC50cmltKCkpfWNhdGNoe3JldHVybn19KX0pLnJlZHVjZSgodCxbbixlXSk9PihuJiZlJiYodFtuXT1lKSx0KSx7fSl9Y29uc3QgbHQ9L15vKFxkKylcLi87ZnVuY3Rpb24gbXQodCxuPSExKXtjb25zdHtob3N0OmUscGF0aDpyLHBhc3M6byxwb3J0OmkscHJvamVjdElkOnMscHJvdG9jb2w6YyxwdWJsaWNLZXk6dX09dDtyZXR1cm5gJHtjfTovLyR7dX0ke24mJm8/YDoke299YDoiIn1AJHtlfSR7aT9gOiR7aX1gOiIifS8ke3I/YCR7cn0vYDpyfSR7c31gfWZ1bmN0aW9uIGd0KHQpe2NvbnN0IG49dC5nZXRPcHRpb25zKCkse2hvc3Q6ZX09dC5nZXREc24oKXx8e307bGV0IHI7cmV0dXJuIG4ub3JnSWQ/cj1TdHJpbmcobi5vcmdJZCk6ZSYmKHI9ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lm1hdGNoKGx0KTtyZXR1cm4gbj8uWzFdfShlKSkscn1mdW5jdGlvbiB5dCh0KXtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmUsaXNSZW1vdGU6cn09dC5zcGFuQ29udGV4dCgpLG89cj9uOnd0KHQpLnBhcmVudF9zcGFuX2lkLGk9ZnQodCkuc2NvcGU7cmV0dXJue3BhcmVudF9zcGFuX2lkOm8sc3Bhbl9pZDpyP2k/LmdldFByb3BhZ2F0aW9uQ29udGV4dCgpLnByb3BhZ2F0aW9uU3BhbklkfHxxKCk6bix0cmFjZV9pZDplfX1mdW5jdGlvbiBidCh0KXtyZXR1cm4gdCYmdC5sZW5ndGg+MD90Lm1hcCgoe2NvbnRleHQ6e3NwYW5JZDp0LHRyYWNlSWQ6bix0cmFjZUZsYWdzOmUsLi4ucn0sYXR0cmlidXRlczpvfSk9Pih7c3Bhbl9pZDp0LHRyYWNlX2lkOm4sc2FtcGxlZDoxPT09ZSxhdHRyaWJ1dGVzOm8sLi4ucn0pKTp2b2lkIDB9ZnVuY3Rpb24gdnQodCl7cmV0dXJuIm51bWJlciI9PXR5cGVvZiB0P190KHQpOkFycmF5LmlzQXJyYXkodCk/dFswXSt0WzFdLzFlOTp0IGluc3RhbmNlb2YgRGF0ZT9fdCh0LmdldFRpbWUoKSk6SigpfWZ1bmN0aW9uIF90KHQpe3JldHVybiB0Pjk5OTk5OTk5OTk/dC8xZTM6dH1mdW5jdGlvbiB3dCh0KXtpZihmdW5jdGlvbih0KXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdC5nZXRTcGFuSlNPTn0odCkpcmV0dXJuIHQuZ2V0U3BhbkpTT04oKTtjb25zdHtzcGFuSWQ6bix0cmFjZUlkOmV9PXQuc3BhbkNvbnRleHQoKTtpZihmdW5jdGlvbih0KXtjb25zdCBuPXQ7cmV0dXJuISEobi5hdHRyaWJ1dGVzJiZuLnN0YXJ0VGltZSYmbi5uYW1lJiZuLmVuZFRpbWUmJm4uc3RhdHVzKX0odCkpe2NvbnN0e2F0dHJpYnV0ZXM6cixzdGFydFRpbWU6byxuYW1lOmksZW5kVGltZTpzLHN0YXR1czpjLGxpbmtzOnV9PXQ7cmV0dXJue3NwYW5faWQ6bix0cmFjZV9pZDplLGRhdGE6cixkZXNjcmlwdGlvbjppLHBhcmVudF9zcGFuX2lkOiJwYXJlbnRTcGFuSWQiaW4gdD90LnBhcmVudFNwYW5JZDoicGFyZW50U3BhbkNvbnRleHQiaW4gdD90LnBhcmVudFNwYW5Db250ZXh0Py5zcGFuSWQ6dm9pZCAwLHN0YXJ0X3RpbWVzdGFtcDp2dChvKSx0aW1lc3RhbXA6dnQocyl8fHZvaWQgMCxzdGF0dXM6U3QoYyksb3A6clsic2VudHJ5Lm9wIl0sb3JpZ2luOnJbInNlbnRyeS5vcmlnaW4iXSxsaW5rczpidCh1KX19cmV0dXJue3NwYW5faWQ6bix0cmFjZV9pZDplLHN0YXJ0X3RpbWVzdGFtcDowLGRhdGE6e319fWZ1bmN0aW9uIFN0KHQpe2lmKHQmJjAhPT10LmNvZGUpcmV0dXJuIDE9PT10LmNvZGU/Im9rIjp0Lm1lc3NhZ2V8fCJpbnRlcm5hbF9lcnJvciJ9ZnVuY3Rpb24gJHQodCl7cmV0dXJuIHQuX3NlbnRyeVJvb3RTcGFufHx0fWZ1bmN0aW9uIEV0KHQpe2NvbnN0IG49dXQoKTtpZighbilyZXR1cm57fTtjb25zdCBlPSR0KHQpLHI9d3QoZSksbz1yLmRhdGEsaT1lLnNwYW5Db250ZXh0KCkudHJhY2VTdGF0ZSxzPWk/LmdldCgic2VudHJ5LnNhbXBsZV9yYXRlIik/P29bInNlbnRyeS5zYW1wbGVfcmF0ZSJdPz9vWyJzZW50cnkucHJldmlvdXNfdHJhY2Vfc2FtcGxlX3JhdGUiXTtmdW5jdGlvbiBjKHQpe3JldHVybiJudW1iZXIiIT10eXBlb2YgcyYmInN0cmluZyIhPXR5cGVvZiBzfHwodC5zYW1wbGVfcmF0ZT1gJHtzfWApLHR9Y29uc3QgdT1lLl9mcm96ZW5Ec2M7aWYodSlyZXR1cm4gYyh1KTtjb25zdCBhPWk/LmdldCgic2VudHJ5LmRzYyIpLGY9YSYmcHQoYSk7aWYoZilyZXR1cm4gYyhmKTtjb25zdCBoPWZ1bmN0aW9uKHQsbil7Y29uc3QgZT1uLmdldE9wdGlvbnMoKSx7cHVibGljS2V5OnJ9PW4uZ2V0RHNuKCl8fHt9LG89e2Vudmlyb25tZW50OmUuZW52aXJvbm1lbnR8fCJwcm9kdWN0aW9uIixyZWxlYXNlOmUucmVsZWFzZSxwdWJsaWNfa2V5OnIsdHJhY2VfaWQ6dCxvcmdfaWQ6Z3Qobil9O3JldHVybiBuLmVtaXQoImNyZWF0ZURzYyIsbyksb30odC5zcGFuQ29udGV4dCgpLnRyYWNlSWQsbikscD1vWyJzZW50cnkuc291cmNlIl0sZD1yLmRlc2NyaXB0aW9uO3JldHVybiJ1cmwiIT09cCYmZCYmKGgudHJhbnNhY3Rpb249ZCksZnVuY3Rpb24oKXtpZigiYm9vbGVhbiI9PXR5cGVvZiBfX1NFTlRSWV9UUkFDSU5HX18mJiFfX1NFTlRSWV9UUkFDSU5HX18pcmV0dXJuITE7Y29uc3QgdD11dCgpPy5nZXRPcHRpb25zKCk7cmV0dXJuISghdHx8bnVsbD09dC50cmFjZXNTYW1wbGVSYXRlJiYhdC50cmFjZXNTYW1wbGVyKX0oKSYmKGguc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczpufT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIDE9PT1ufShlKSksaC5zYW1wbGVfcmFuZD1pPy5nZXQoInNlbnRyeS5zYW1wbGVfcmFuZCIpPz9mdChlKS5zY29wZT8uZ2V0UHJvcGFnYXRpb25Db250ZXh0KCkuc2FtcGxlUmFuZC50b1N0cmluZygpKSxjKGgpLG4uZW1pdCgiY3JlYXRlRHNjIixoLGUpLGh9ZnVuY3Rpb24geHQodCxuPTEwMCxlPTEvMCl7dHJ5e3JldHVybiBOdCgiIix0LG4sZSl9Y2F0Y2godCl7cmV0dXJue0VSUk9SOmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX19ZnVuY3Rpb24gTnQodCxuLGU9MS8wLHI9MS8wLG89ZnVuY3Rpb24oKXtjb25zdCB0PW5ldyBXZWFrU2V0O2Z1bmN0aW9uIG4obil7cmV0dXJuISF0LmhhcyhuKXx8KHQuYWRkKG4pLCExKX1mdW5jdGlvbiBlKG4pe3QuZGVsZXRlKG4pfXJldHVybltuLGVdfSgpKXtjb25zdFtpLHNdPW87aWYobnVsbD09bnx8WyJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIG4pfHwibnVtYmVyIj09dHlwZW9mIG4mJk51bWJlci5pc0Zpbml0ZShuKSlyZXR1cm4gbjtjb25zdCBjPWZ1bmN0aW9uKHQsbil7dHJ5e2lmKCJkb21haW4iPT09dCYmbiYmIm9iamVjdCI9PXR5cGVvZiBuJiZuLkwpcmV0dXJuIltEb21haW5dIjtpZigiZG9tYWluRW1pdHRlciI9PT10KXJldHVybiJbRG9tYWluRW1pdHRlcl0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsJiZuPT09Z2xvYmFsKXJldHVybiJbR2xvYmFsXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJm49PT13aW5kb3cpcmV0dXJuIltXaW5kb3ddIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGRvY3VtZW50JiZuPT09ZG9jdW1lbnQpcmV0dXJuIltEb2N1bWVudF0iO2lmKCJvYmplY3QiPT10eXBlb2YoZT1uKSYmbnVsbCE9PWUmJihlLl9faXNWdWV8fGUuQnx8ZS5fX3ZfaXNWTm9kZSkpcmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiJfX3ZfaXNWTm9kZSJpbiB0JiZ0Ll9fdl9pc1ZOb2RlPyJbVnVlVk5vZGVdIjoiW1Z1ZVZpZXdNb2RlbF0ifShuKTtpZihmdW5jdGlvbih0KXtyZXR1cm4gaih0KSYmIm5hdGl2ZUV2ZW50ImluIHQmJiJwcmV2ZW50RGVmYXVsdCJpbiB0JiYic3RvcFByb3BhZ2F0aW9uImluIHR9KG4pKXJldHVybiJbU3ludGhldGljRXZlbnRdIjtpZigibnVtYmVyIj09dHlwZW9mIG4mJiFOdW1iZXIuaXNGaW5pdGUobikpcmV0dXJuYFske259XWA7aWYoImZ1bmN0aW9uIj09dHlwZW9mIG4pcmV0dXJuYFtGdW5jdGlvbjogJHtmdW5jdGlvbih0KXt0cnl7cmV0dXJuIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0Lm5hbWV8fHh9Y2F0Y2h7cmV0dXJuIHh9fShuKX1dYDtpZigic3ltYm9sIj09dHlwZW9mIG4pcmV0dXJuYFske1N0cmluZyhuKX1dYDtpZigiYmlnaW50Ij09dHlwZW9mIG4pcmV0dXJuYFtCaWdJbnQ6ICR7U3RyaW5nKG4pfV1gO2NvbnN0IHI9ZnVuY3Rpb24odCl7Y29uc3Qgbj1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCk7cmV0dXJuIG4/LmNvbnN0cnVjdG9yP24uY29uc3RydWN0b3IubmFtZToibnVsbCBwcm90b3R5cGUifShuKTtyZXR1cm4vXkhUTUwoXHcqKUVsZW1lbnQkLy50ZXN0KHIpP2BbSFRNTEVsZW1lbnQ6ICR7cn1dYDpgW29iamVjdCAke3J9XWB9Y2F0Y2godCl7cmV0dXJuYCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9dmFyIGV9KHQsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihuLl9fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fKXJldHVybiBuO2NvbnN0IHU9Im51bWJlciI9PXR5cGVvZiBuLl9fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXz9uLl9fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXzplO2lmKDA9PT11KXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihpKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGE9bjtpZihhJiYiZnVuY3Rpb24iPT10eXBlb2YgYS50b0pTT04pdHJ5e3JldHVybiBOdCgiIixhLnRvSlNPTigpLHUtMSxyLG8pfWNhdGNoe31jb25zdCBmPUFycmF5LmlzQXJyYXkobik/W106e307bGV0IGg9MDtjb25zdCBwPU8obik7Zm9yKGNvbnN0IHQgaW4gcCl7aWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwLHQpKWNvbnRpbnVlO2lmKGg+PXIpe2ZbdF09IltNYXhQcm9wZXJ0aWVzIH5dIjticmVha31jb25zdCBuPXBbdF07Zlt0XT1OdCh0LG4sdS0xLHIsbyksaCsrfXJldHVybiBzKG4pLGZ9ZnVuY3Rpb24gQ3QodCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2h7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1mdW5jdGlvbiBBdCh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIGp0KHQsbil7Y29uc3QgZT10WzFdO2Zvcihjb25zdCB0IG9mIGUpe2lmKG4odCx0WzBdLnR5cGUpKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIGt0KHQpe2NvbnN0IG49bShwKTtyZXR1cm4gbi5lbmNvZGVQb2x5ZmlsbD9uLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBUdCh0KXtjb25zdFtuLGVdPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkobik7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0OltrdChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P2t0KHQpOnQpfWZvcihjb25zdCB0IG9mIGUpe2NvbnN0W24sZV09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkobil9XG5gKSwic3RyaW5nIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBVaW50OEFycmF5KW8oZSk7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShlKX1jYXRjaHt0PUpTT04uc3RyaW5naWZ5KHh0KGUpKX1vKHQpfX1yZXR1cm4ic3RyaW5nIj09dHlwZW9mIHI/cjpmdW5jdGlvbih0KXtjb25zdCBuPXQucmVkdWNlKCh0LG4pPT50K24ubGVuZ3RoLDApLGU9bmV3IFVpbnQ4QXJyYXkobik7bGV0IHI9MDtmb3IoY29uc3QgbiBvZiB0KWUuc2V0KG4scikscis9bi5sZW5ndGg7cmV0dXJuIGV9KHIpfWNvbnN0IEl0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscHJvZmlsZV9jaHVuazoicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIscmF3X3NlY3VyaXR5OiJzZWN1cml0eSIsbG9nOiJsb2dfaXRlbSIsbWV0cmljOiJtZXRyaWMiLHRyYWNlX21ldHJpYzoibWV0cmljIn07ZnVuY3Rpb24gUnQodCl7aWYoIXQ/LnNkaylyZXR1cm47Y29uc3R7bmFtZTpuLHZlcnNpb246ZX09dC5zZGs7cmV0dXJue25hbWU6bix2ZXJzaW9uOmV9fWZ1bmN0aW9uIE90KHQsbixlLHIpe2NvbnN0IG89UnQoZSksaT10LnR5cGUmJiJyZXBsYXlfZXZlbnQiIT09dC50eXBlP3QudHlwZToiZXZlbnQiOyFmdW5jdGlvbih0LG4pe2lmKCFuKXJldHVybiB0O2NvbnN0IGU9dC5zZGt8fHt9O3Quc2RrPXsuLi5lLG5hbWU6ZS5uYW1lfHxuLm5hbWUsdmVyc2lvbjplLnZlcnNpb258fG4udmVyc2lvbixpbnRlZ3JhdGlvbnM6Wy4uLnQuc2RrPy5pbnRlZ3JhdGlvbnN8fFtdLC4uLm4uaW50ZWdyYXRpb25zfHxbXV0scGFja2FnZXM6Wy4uLnQuc2RrPy5wYWNrYWdlc3x8W10sLi4ubi5wYWNrYWdlc3x8W11dLHNldHRpbmdzOnQuc2RrPy5zZXR0aW5nc3x8bi5zZXR0aW5ncz97Li4udC5zZGs/LnNldHRpbmdzLC4uLm4uc2V0dGluZ3N9OnZvaWQgMH19KHQsZT8uc2RrKTtjb25zdCBzPWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE/LmR5bmFtaWNTYW1wbGluZ0NvbnRleHQ7cmV0dXJue2V2ZW50X2lkOnQuZXZlbnRfaWQsc2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubiYme3NkazpufSwuLi4hIWUmJnImJntkc246bXQocil9LC4uLm8mJnt0cmFjZTpvfX19KHQsbyxyLG4pO2RlbGV0ZSB0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YTtyZXR1cm4gQXQocyxbW3t0eXBlOml9LHRdXSl9Y29uc3QgUHQ9Il9fU0VOVFJZX1NVUFBSRVNTX1RSQUNJTkdfXyI7ZnVuY3Rpb24gRHQodCl7Y29uc3Qgbj1jdChsKCkpO3JldHVybiBuLnN1cHByZXNzVHJhY2luZz9uLnN1cHByZXNzVHJhY2luZyh0KTpmdW5jdGlvbiguLi50KXtjb25zdCBuPWN0KGwoKSk7aWYoMj09PXQubGVuZ3RoKXtjb25zdFtlLHJdPXQ7cmV0dXJuIGU/bi53aXRoU2V0U2NvcGUoZSxyKTpuLndpdGhTY29wZShyKX1yZXR1cm4gbi53aXRoU2NvcGUodFswXSl9KG49PntuLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W1B0XTohMH0pO2NvbnN0IGU9dCgpO3JldHVybiBuLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W1B0XTp2b2lkIDB9KSxlfSl9Y2xhc3MgVXR7Y29uc3RydWN0b3IodCl7dGhpcy5XPTAsdGhpcy5GPVtdLHRoaXMuRyh0KX10aGVuKHQsbil7cmV0dXJuIG5ldyBVdCgoZSxyKT0+e3RoaXMuRi5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy5IKCl9KX1jYXRjaCh0KXtyZXR1cm4gdGhpcy50aGVuKHQ9PnQsdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IFV0KChuLGUpPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKG49PntvPSExLHI9bix0JiZ0KCl9LG49PntvPSEwLHI9bix0JiZ0KCl9KS50aGVuKCgpPT57bz9lKHIpOm4ocil9KX0pfUgoKXtpZigwPT09dGhpcy5XKXJldHVybjtjb25zdCB0PXRoaXMuRi5zbGljZSgpO3RoaXMuRj1bXSx0LmZvckVhY2godD0+e3RbMF18fCgxPT09dGhpcy5XJiZ0WzFdKHRoaXMuSiksMj09PXRoaXMuVyYmdFsyXSh0aGlzLkopLHRbMF09ITApfSl9Ryh0KXtjb25zdCBuPSh0LG4pPT57MD09PXRoaXMuVyYmKGsobik/bi50aGVuKGUscik6KHRoaXMuVz10LHRoaXMuSj1uLHRoaXMuSCgpKSl9LGU9dD0+e24oMSx0KX0scj10PT57bigyLHQpfTt0cnl7dChlLHIpfWNhdGNoKHQpe3IodCl9fX1mdW5jdGlvbiBNdCh0LG4pe2NvbnN0e2ZpbmdlcnByaW50OmUsc3BhbjpyLGJyZWFkY3J1bWJzOm8sc2RrUHJvY2Vzc2luZ01ldGFkYXRhOml9PW47IWZ1bmN0aW9uKHQsbil7Y29uc3R7ZXh0cmE6ZSx0YWdzOnIsdXNlcjpvLGNvbnRleHRzOmksbGV2ZWw6cyx0cmFuc2FjdGlvbk5hbWU6Y309bjtPYmplY3Qua2V5cyhlKS5sZW5ndGgmJih0LmV4dHJhPXsuLi5lLC4uLnQuZXh0cmF9KTtPYmplY3Qua2V5cyhyKS5sZW5ndGgmJih0LnRhZ3M9ey4uLnIsLi4udC50YWdzfSk7T2JqZWN0LmtleXMobykubGVuZ3RoJiYodC51c2VyPXsuLi5vLC4uLnQudXNlcn0pO09iamVjdC5rZXlzKGkpLmxlbmd0aCYmKHQuY29udGV4dHM9ey4uLmksLi4udC5jb250ZXh0c30pO3MmJih0LmxldmVsPXMpO2MmJiJ0cmFuc2FjdGlvbiIhPT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPWMpfSh0LG4pLHImJmZ1bmN0aW9uKHQsbil7dC5jb250ZXh0cz17dHJhY2U6eXQobiksLi4udC5jb250ZXh0c30sdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9e2R5bmFtaWNTYW1wbGluZ0NvbnRleHQ6RXQobiksLi4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGF9O2NvbnN0IGU9JHQobikscj13dChlKS5kZXNjcmlwdGlvbjtyJiYhdC50cmFuc2FjdGlvbiYmInRyYW5zYWN0aW9uIj09PXQudHlwZSYmKHQudHJhbnNhY3Rpb249cil9KHQsciksZnVuY3Rpb24odCxuKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/QXJyYXkuaXNBcnJheSh0LmZpbmdlcnByaW50KT90LmZpbmdlcnByaW50Olt0LmZpbmdlcnByaW50XTpbXSxuJiYodC5maW5nZXJwcmludD10LmZpbmdlcnByaW50LmNvbmNhdChuKSk7dC5maW5nZXJwcmludC5sZW5ndGh8fGRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LGUpLGZ1bmN0aW9uKHQsbil7Y29uc3QgZT1bLi4udC5icmVhZGNydW1ic3x8W10sLi4ubl07dC5icmVhZGNydW1icz1lLmxlbmd0aD9lOnZvaWQgMH0odCxvKSxmdW5jdGlvbih0LG4pe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5ufX0odCxpKX1jb25zdCBMdD1TeW1ib2wuZm9yKCJTZW50cnlCdWZmZXJGdWxsRXJyb3IiKTtmdW5jdGlvbiBCdCh0PTEwMCl7Y29uc3Qgbj1uZXcgU2V0O2Z1bmN0aW9uIGUodCl7bi5kZWxldGUodCl9cmV0dXJue2dldCAkKCl7cmV0dXJuIEFycmF5LmZyb20obil9LGFkZDpmdW5jdGlvbihyKXtpZighKG4uc2l6ZTx0KSlyZXR1cm4gbz1MdCxuZXcgVXQoKHQsbik9PntuKG8pfSk7dmFyIG87Y29uc3QgaT1yKCk7cmV0dXJuIG4uYWRkKGkpLGkudGhlbigoKT0+ZShpKSwoKT0+ZShpKSksaX0sZHJhaW46ZnVuY3Rpb24odCl7aWYoIW4uc2l6ZSlyZXR1cm4gZT0hMCxuZXcgVXQodD0+e3QoZSl9KTt2YXIgZTtjb25zdCByPVByb21pc2UuYWxsU2V0dGxlZChBcnJheS5mcm9tKG4pKS50aGVuKCgpPT4hMCk7aWYoIXQpcmV0dXJuIHI7Y29uc3Qgbz1bcixuZXcgUHJvbWlzZShuPT57cmV0dXJuIm9iamVjdCI9PXR5cGVvZihlPXNldFRpbWVvdXQoKCk9Pm4oITEpLHQpKSYmImZ1bmN0aW9uIj09dHlwZW9mIGUudW5yZWYmJmUudW5yZWYoKSxlO3ZhciBlfSldO3JldHVybiBQcm9taXNlLnJhY2Uobyl9fX1mdW5jdGlvbiBXdCh0LHtzdGF0dXNDb2RlOm4saGVhZGVyczplfSxyPVcoKSl7Y29uc3Qgbz17Li4udH0saT1lPy5bIngtc2VudHJ5LXJhdGUtbGltaXRzIl0scz1lPy5bInJldHJ5LWFmdGVyIl07aWYoaSlmb3IoY29uc3QgdCBvZiBpLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtuLGUsLCxpXT10LnNwbGl0KCI6Iiw1KSxzPXBhcnNlSW50KG4sMTApLGM9MWUzKihpc05hTihzKT82MDpzKTtpZihlKWZvcihjb25zdCB0IG9mIGUuc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZpJiYhaS5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIHM/by5hbGw9citmdW5jdGlvbih0LG49VygpKXtjb25zdCBlPXBhcnNlSW50KGAke3R9YCwxMCk7aWYoIWlzTmFOKGUpKXJldHVybiAxZTMqZTtjb25zdCByPURhdGUucGFyc2UoYCR7dH1gKTtyZXR1cm4gaXNOYU4ocik/NmU0OnItbn0ocyxyKTo0Mjk9PT1uJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWZ1bmN0aW9uIHp0KHQsbixlPUJ0KHQuYnVmZmVyU2l6ZXx8NjQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbih0KXtjb25zdCBvPVtdO2lmKGp0KHQsKHQsbik9Pntjb25zdCBlPWZ1bmN0aW9uKHQpe3JldHVybiBJdFt0XX0obik7KGZ1bmN0aW9uKHQsbixlPVcoKSl7cmV0dXJuIGZ1bmN0aW9uKHQsbil7cmV0dXJuIHRbbl18fHQuYWxsfHwwfSh0LG4pPmV9KShyLGUpfHxvLnB1c2godCl9KSwwPT09by5sZW5ndGgpcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7fSk7Y29uc3QgaT1BdCh0WzBdLG8pLHM9dD0+eyFmdW5jdGlvbih0LG4pe3JldHVybiBqdCh0LCh0LGUpPT5uLmluY2x1ZGVzKGUpKX0oaSxbImNsaWVudF9yZXBvcnQiXSk/anQoaSwodCxuKT0+e30pOmgmJlMud2FybihgRHJvcHBpbmcgY2xpZW50IHJlcG9ydC4gV2lsbCBub3Qgc2VuZCBvdXRjb21lcyAocmVhc29uOiAke3R9KS5gKX07cmV0dXJuIGUuYWRkKCgpPT5uKHtib2R5OlR0KGkpfSkudGhlbih0PT40MTM9PT10LnN0YXR1c0NvZGU/KGgmJlMuZXJyb3IoIlNlbnRyeSByZXNwb25kZWQgd2l0aCBzdGF0dXMgY29kZSA0MTMuIEVudmVsb3BlIHdhcyBkaXNjYXJkZWQgZHVlIHRvIGV4Y2VlZGluZyBzaXplIGxpbWl0cy4iKSxzKCJzZW5kX2Vycm9yIiksdCk6KGgmJnZvaWQgMCE9PXQuc3RhdHVzQ29kZSYmKHQuc3RhdHVzQ29kZTwyMDB8fHQuc3RhdHVzQ29kZT49MzAwKSYmUy53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHt0LnN0YXR1c0NvZGV9IHRvIHNlbnQgZXZlbnQuYCkscj1XdChyLHQpLHQpLHQ9Pnt0aHJvdyBzKCJuZXR3b3JrX2Vycm9yIiksaCYmUy5lcnJvcigiRW5jb3VudGVyZWQgZXJyb3IgcnVubmluZyB0cmFuc3BvcnQgcmVxdWVzdDoiLHQpLHR9KSkudGhlbih0PT50LHQ9PntpZih0PT09THQpcmV0dXJuIGgmJlMuZXJyb3IoIlNraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLiIpLHMoInF1ZXVlX292ZXJmbG93IiksUHJvbWlzZS5yZXNvbHZlKHt9KTt0aHJvdyB0fSl9LGZsdXNoOnQ9PmUuZHJhaW4odCl9fWNvbnN0IEZ0PS9eKFxTKzpcXHxcLz8pKFtcc1xTXSo/KSgoPzpcLnsxLDJ9fFteL1xcXSs/fCkoXC5bXi4vXFxdKnwpKSg/OlsvXFxdKikkLztmdW5jdGlvbiBHdCh0KXtjb25zdCBuPWZ1bmN0aW9uKHQpe2NvbnN0IG49dC5sZW5ndGg+MTAyND9gPHRydW5jYXRlZD4ke3Quc2xpY2UoLTEwMjQpfWA6dCxlPUZ0LmV4ZWMobik7cmV0dXJuIGU/ZS5zbGljZSgxKTpbXX0odCksZT1uWzBdfHwiIjtsZXQgcj1uWzFdO3JldHVybiBlfHxyPyhyJiYocj1yLnNsaWNlKDAsci5sZW5ndGgtMSkpLGUrcik6Ii4ifWZ1bmN0aW9uIEh0KHQsbj0hMSl7cmV0dXJuIShufHx0JiYhdC5zdGFydHNXaXRoKCIvIikmJiF0Lm1hdGNoKC9eW0EtWl06LykmJiF0LnN0YXJ0c1dpdGgoIi4iKSYmIXQubWF0Y2goL15bYS16QS1aXShbYS16QS1aMC05LlwtK10pKjpcL1wvLykpJiZ2b2lkIDAhPT10JiYhdC5pbmNsdWRlcygibm9kZV9tb2R1bGVzLyIpfWNvbnN0IEp0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIFl0IGV4dGVuZHMgaS5BZ2VudHtjb25zdHJ1Y3Rvcih0KXtzdXBlcih0KSx0aGlzW0p0XT17fX1pc1NlY3VyZUVuZHBvaW50KHQpe2lmKHQpe2lmKCJib29sZWFuIj09dHlwZW9mIHQuc2VjdXJlRW5kcG9pbnQpcmV0dXJuIHQuc2VjdXJlRW5kcG9pbnQ7aWYoInN0cmluZyI9PXR5cGVvZiB0LnByb3RvY29sKXJldHVybiJodHRwczoiPT09dC5wcm90b2NvbH1jb25zdHtzdGFjazpufT1uZXcgRXJyb3I7cmV0dXJuInN0cmluZyI9PXR5cGVvZiBuJiZuLnNwbGl0KCJcbiIpLnNvbWUodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpfWNyZWF0ZVNvY2tldCh0LG4sZSl7Y29uc3Qgcj17Li4ubixzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQobil9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCk9PnRoaXMuY29ubmVjdCh0LHIpKS50aGVuKG89PntpZihvIGluc3RhbmNlb2YgaS5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tKdF0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LG4sZSl9LGUpfWNyZWF0ZUNvbm5lY3Rpb24oKXtjb25zdCB0PXRoaXNbSnRdLmN1cnJlbnRTb2NrZXQ7aWYodGhpc1tKdF0uY3VycmVudFNvY2tldD12b2lkIDAsIXQpdGhyb3cgbmV3IEVycm9yKCJObyBzb2NrZXQgd2FzIHJldHVybmVkIGluIHRoZSBgY29ubmVjdCgpYCBmdW5jdGlvbiIpO3JldHVybiB0fWdldCBkZWZhdWx0UG9ydCgpe3JldHVybiB0aGlzW0p0XS5kZWZhdWx0UG9ydD8/KCJodHRwczoiPT09dGhpcy5wcm90b2NvbD80NDM6ODApfXNldCBkZWZhdWx0UG9ydCh0KXt0aGlzW0p0XSYmKHRoaXNbSnRdLmRlZmF1bHRQb3J0PXQpfWdldCBwcm90b2NvbCgpe3JldHVybiB0aGlzW0p0XS5wcm90b2NvbD8/KHRoaXMuaXNTZWN1cmVFbmRwb2ludCgpPyJodHRwczoiOiJodHRwOiIpfXNldCBwcm90b2NvbCh0KXt0aGlzW0p0XSYmKHRoaXNbSnRdLnByb3RvY29sPXQpfX1mdW5jdGlvbiBWdCguLi50KXtTLmxvZygiW2h0dHBzLXByb3h5LWFnZW50OnBhcnNlLXByb3h5LXJlc3BvbnNlXSIsLi4udCl9ZnVuY3Rpb24gS3QodCl7cmV0dXJuIG5ldyBQcm9taXNlKChuLGUpPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIGkoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gVnQoImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBpKCk7Y29uc3QgZj11LnN1YmFycmF5KDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksZD0rKHBbMV18fDApLGw9cC5zbGljZSgyKS5qb2luKCIgIiksbT17fTtmb3IoY29uc3QgbiBvZiBmKXtpZighbiljb250aW51ZTtjb25zdCByPW4uaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7bn0iYCkpO2NvbnN0IG89bi5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCksaT1uLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCkscz1tW29dOyJzdHJpbmciPT10eXBlb2Ygcz9tW29dPVtzLGldOkFycmF5LmlzQXJyYXkocyk/cy5wdXNoKGkpOm1bb109aX1WdCgiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsbSkscygpLG4oe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6ZCxzdGF0dXNUZXh0OmwsaGVhZGVyczptfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLGkpfWZ1bmN0aW9uIHMoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIsaSl9ZnVuY3Rpb24gYygpe3MoKSxWdCgib25lbmQiKSxlKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtzKCksVnQoIm9uZXJyb3IgJW8iLHQpLGUodCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYyksaSgpfSl9ZnVuY3Rpb24gWnQoLi4udCl7Uy5sb2coIltodHRwcy1wcm94eS1hZ2VudF0iLC4uLnQpfWNsYXNzIHF0IGV4dGVuZHMgWXR7c3RhdGljIF9faW5pdFN0YXRpYygpe3RoaXMucHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl19Y29uc3RydWN0b3IodCxuKXtzdXBlcihuKSx0aGlzLm9wdGlvbnM9e30sdGhpcy5wcm94eT0ic3RyaW5nIj09dHlwZW9mIHQ/bmV3IFVSTCh0KTp0LHRoaXMucHJveHlIZWFkZXJzPW4/LmhlYWRlcnM/P3t9LFp0KCJDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbyIsdGhpcy5wcm94eS5ocmVmKTtjb25zdCBlPSh0aGlzLnByb3h5Lmhvc3RuYW1lfHx0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywiIikscj10aGlzLnByb3h5LnBvcnQ/cGFyc2VJbnQodGhpcy5wcm94eS5wb3J0LDEwKToiaHR0cHM6Ij09PXRoaXMucHJveHkucHJvdG9jb2w/NDQzOjgwO3RoaXMuY29ubmVjdE9wdHM9e0FMUE5Qcm90b2NvbHM6WyJodHRwLzEuMSJdLC4uLm4/WHQobiwiaGVhZGVycyIpOm51bGwsaG9zdDplLHBvcnQ6cn19YXN5bmMgY29ubmVjdCh0LG4pe2NvbnN0e3Byb3h5OmV9PXRoaXM7aWYoIW4uaG9zdCl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTtsZXQgcjtpZigiaHR0cHM6Ij09PWUucHJvdG9jb2wpe1p0KCJDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCB0PXRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZXx8dGhpcy5jb25uZWN0T3B0cy5ob3N0O3I9Zi5jb25uZWN0KHsuLi50aGlzLmNvbm5lY3RPcHRzLHNlcnZlcm5hbWU6dCYmYS5pc0lQKHQpP3ZvaWQgMDp0fSl9ZWxzZSBadCgiQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cykscj1hLmNvbm5lY3QodGhpcy5jb25uZWN0T3B0cyk7Y29uc3Qgbz0iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5wcm94eUhlYWRlcnM/dGhpcy5wcm94eUhlYWRlcnMoKTp7Li4udGhpcy5wcm94eUhlYWRlcnN9LGk9YS5pc0lQdjYobi5ob3N0KT9gWyR7bi5ob3N0fV1gOm4uaG9zdDtsZXQgcz1gQ09OTkVDVCAke2l9OiR7bi5wb3J0fSBIVFRQLzEuMVxyXG5gO2lmKGUudXNlcm5hbWV8fGUucGFzc3dvcmQpe2NvbnN0IHQ9YCR7ZGVjb2RlVVJJQ29tcG9uZW50KGUudXNlcm5hbWUpfToke2RlY29kZVVSSUNvbXBvbmVudChlLnBhc3N3b3JkKX1gO29bIlByb3h5LUF1dGhvcml6YXRpb24iXT1gQmFzaWMgJHtCdWZmZXIuZnJvbSh0KS50b1N0cmluZygiYmFzZTY0Iil9YH1vLkhvc3Q9YCR7aX06JHtuLnBvcnR9YCxvWyJQcm94eS1Db25uZWN0aW9uIl18fChvWyJQcm94eS1Db25uZWN0aW9uIl09dGhpcy5rZWVwQWxpdmU/IktlZXAtQWxpdmUiOiJjbG9zZSIpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5rZXlzKG8pKXMrPWAke3R9OiAke29bdF19XHJcbmA7Y29uc3QgYz1LdChyKTtyLndyaXRlKGAke3N9XHJcbmApO2NvbnN0e2Nvbm5lY3Q6dSxidWZmZXJlZDpofT1hd2FpdCBjO2lmKHQuZW1pdCgicHJveHlDb25uZWN0Iix1KSx0aGlzLmVtaXQoInByb3h5Q29ubmVjdCIsdSx0KSwyMDA9PT11LnN0YXR1c0NvZGUpe2lmKHQub25jZSgic29ja2V0IixRdCksbi5zZWN1cmVFbmRwb2ludCl7WnQoIlVwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMiKTtjb25zdCB0PW4uc2VydmVybmFtZXx8bi5ob3N0O3JldHVybiBmLmNvbm5lY3Qoey4uLlh0KG4sImhvc3QiLCJwYXRoIiwicG9ydCIpLHNvY2tldDpyLHNlcnZlcm5hbWU6YS5pc0lQKHQpP3ZvaWQgMDp0fSl9cmV0dXJuIHJ9ci5kZXN0cm95KCk7Y29uc3QgcD1uZXcgYS5Tb2NrZXQoe3dyaXRhYmxlOiExfSk7cmV0dXJuIHAucmVhZGFibGU9ITAsdC5vbmNlKCJzb2NrZXQiLHQ9PntadCgiUmVwbGF5aW5nIHByb3h5IGJ1ZmZlciBmb3IgZmFpbGVkIHJlcXVlc3QiKSx0LnB1c2goaCksdC5wdXNoKG51bGwpfSkscH19ZnVuY3Rpb24gUXQodCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBYdCh0LC4uLm4pe2NvbnN0IGU9e307bGV0IHI7Zm9yKHIgaW4gdCluLmluY2x1ZGVzKHIpfHwoZVtyXT10W3JdKTtyZXR1cm4gZX1xdC5fX2luaXRTdGF0aWMoKTtmdW5jdGlvbiB0bih0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IG5uPW47bGV0IGVuLHJuPTAsb249e307ZnVuY3Rpb24gc24odCl7bm4uZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciBjbix1bixhbjtjb25zdCBmbj1mdW5jdGlvbih0KXtsZXQgbjt0cnl7bj1uZXcgVVJMKHQudXJsKX1jYXRjaChuKXtyZXR1cm4gYigoKT0+e2NvbnNvbGUud2FybigiW0BzZW50cnkvbm9kZV06IEludmFsaWQgZHNuIG9yIHR1bm5lbCBvcHRpb24sIHdpbGwgbm90IHNlbmQgYW55IGV2ZW50cy4gVGhlIHR1bm5lbCBvcHRpb24gbXVzdCBiZSBhIGZ1bGwgVVJMIHdoZW4gdXNlZC4iKX0pLHp0KHQsKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpfWNvbnN0IGU9Imh0dHBzOiI9PT1uLnByb3RvY29sLHI9ZnVuY3Rpb24odCxuKXtjb25zdHtub19wcm94eTplfT1wcm9jZXNzLmVudixyPWU/LnNwbGl0KCIsIikuc29tZShuPT50Lmhvc3QuZW5kc1dpdGgobil8fHQuaG9zdG5hbWUuZW5kc1dpdGgobikpO3JldHVybiByP3ZvaWQgMDpufShuLHQucHJveHl8fChlP3Byb2Nlc3MuZW52Lmh0dHBzX3Byb3h5OnZvaWQgMCl8fHByb2Nlc3MuZW52Lmh0dHBfcHJveHkpLG89ZT9zOmksYT12b2lkIDAhPT10LmtlZXBBbGl2ZSYmdC5rZWVwQWxpdmUsZj1yP25ldyBxdChyKTpuZXcgby5BZ2VudCh7a2VlcEFsaXZlOmEsbWF4U29ja2V0czozMCx0aW1lb3V0OjJlM30pLGg9ZnVuY3Rpb24odCxuLGUpe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OmkscHJvdG9jb2w6cyxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoaCxwKT0+e0R0KCgpPT57bGV0IGQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBjKHtyZWFkKCl7dGhpcy5wdXNoKHQpLHRoaXMucHVzaChudWxsKX19KX0oZi5ib2R5KTtjb25zdCBsPXsuLi50LmhlYWRlcnN9O2YuYm9keS5sZW5ndGg+MzI3NjgmJihsWyJjb250ZW50LWVuY29kaW5nIl09Imd6aXAiLGQ9ZC5waXBlKHUoKSkpO2NvbnN0IG09ci5zdGFydHNXaXRoKCJbIiksZz1uLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6ZSxoZWFkZXJzOmwsaG9zdG5hbWU6bT9yLnNsaWNlKDEsLTEpOnIscGF0aDpgJHtvfSR7YX1gLHBvcnQ6aSxwcm90b2NvbDpzLGNhOnQuY2FDZXJ0c30sdD0+e3Qub24oImRhdGEiLCgpPT57fSksdC5vbigiZW5kIiwoKT0+e30pLHQuc2V0RW5jb2RpbmcoInV0ZjgiKTtjb25zdCBuPXQuaGVhZGVyc1sicmV0cnktYWZ0ZXIiXT8/bnVsbCxlPXQuaGVhZGVyc1sieC1zZW50cnktcmF0ZS1saW1pdHMiXT8/bnVsbDtoKHtzdGF0dXNDb2RlOnQuc3RhdHVzQ29kZSxoZWFkZXJzOnsicmV0cnktYWZ0ZXIiOm4sIngtc2VudHJ5LXJhdGUtbGltaXRzIjpBcnJheS5pc0FycmF5KGUpP2VbMF18fG51bGw6ZX19KX0pO2cub24oImVycm9yIixwKSxkLnBpcGUoZyl9KX0pfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuIHp0KHQsaCl9KHt1cmw6KGNuPW5uLmRzbix1bj1ubi50dW5uZWwsYW49bm4uc2RrTWV0YWRhdGEuc2RrLHVufHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBuPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixlPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7bn0vLyR7dC5ob3N0fSR7ZX0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfShjbil9PyR7ZnVuY3Rpb24odCxuKXtjb25zdCBlPXtzZW50cnlfdmVyc2lvbjoiNyJ9O3JldHVybiB0LnB1YmxpY0tleSYmKGUuc2VudHJ5X2tleT10LnB1YmxpY0tleSksbiYmKGUuc2VudHJ5X2NsaWVudD1gJHtuLm5hbWV9LyR7bi52ZXJzaW9ufWApLG5ldyBVUkxTZWFyY2hQYXJhbXMoZSkudG9TdHJpbmcoKX0oY24sYW4pfWApfSk7YXN5bmMgZnVuY3Rpb24gaG4oKXtpZihlbil7c24oIlNlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbiIpLFYoZW4se3N0YXR1czoiYWJub3JtYWwiLGFibm9ybWFsX21lY2hhbmlzbToiYW5yX2ZvcmVncm91bmQiLHJlbGVhc2U6bm4ucmVsZWFzZSxlbnZpcm9ubWVudDpubi5lbnZpcm9ubWVudH0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz1SdChlKTtyZXR1cm4gQXQoe3NlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm8mJntzZGs6b30sLi4uISFyJiZuJiZ7ZHNuOm10KG4pfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KGVuLG5uLmRzbixubi5zZGtNZXRhZGF0YSxubi50dW5uZWwpO3NuKEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCBmbi5zZW5kKHQpO3RyeXtlPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoe319fWZ1bmN0aW9uIHBuKHQpe2lmKCF0KXJldHVybjtjb25zdCBuPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBuPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoRShuKS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpLG4ucmV2ZXJzZSgpLCQudGVzdChFKG4pLmZ1bmN0aW9ufHwiIikmJihuLnBvcCgpLCQudGVzdChFKG4pLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCkpLG4uc2xpY2UoMCw1MCkubWFwKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHxFKG4pLmZpbGVuYW1lLGZ1bmN0aW9uOnQuZnVuY3Rpb258fCI/In0pKX0odCk7aWYobm4uYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2Ygbil0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1DdCh0LmZpbGVuYW1lLG5uLmFwcFJvb3RQYXRoKSk7cmV0dXJuIG59YXN5bmMgZnVuY3Rpb24gZG4odCxuKXtpZihybj49bm4ubWF4QW5yRXZlbnRzKXJldHVybjtybis9MSxhd2FpdCBobigpLHNuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6RigpLGNvbnRleHRzOm5uLmNvbnRleHRzLHJlbGVhc2U6bm4ucmVsZWFzZSxlbnZpcm9ubWVudDpubi5lbnZpcm9ubWVudCxkaXN0Om5uLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHtubi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6cG4odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczpubi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKE10KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUscGFyZW50U3BhbklkOnIscHJvcGFnYXRpb25TcGFuSWQ6b309bi5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOmUsc3Bhbl9pZDpvfHxxKCkscGFyZW50X3NwYW5faWQ6cn0sLi4udC5jb250ZXh0c319fShlLG4pLGZ1bmN0aW9uKHQpe2lmKDA9PT1PYmplY3Qua2V5cyhvbikubGVuZ3RoKXJldHVybjtjb25zdCBuPW5uLmFwcFJvb3RQYXRoP3t9Om9uO2lmKG5uLmFwcFJvb3RQYXRoKWZvcihjb25zdFt0LGVdb2YgT2JqZWN0LmVudHJpZXMob24pKW5bQ3QodCxubi5hcHBSb290UGF0aCldPWU7Y29uc3QgZT1uZXcgTWFwO2Zvcihjb25zdCByIG9mIHQuZXhjZXB0aW9uPy52YWx1ZXN8fFtdKWZvcihjb25zdCB0IG9mIHIuc3RhY2t0cmFjZT8uZnJhbWVzfHxbXSl7Y29uc3Qgcj10LmFic19wYXRofHx0LmZpbGVuYW1lO3ImJm5bcl0mJmUuc2V0KHIsbltyXSl9aWYoZS5zaXplPjApe2NvbnN0IG49W107Zm9yKGNvbnN0W3Qscl1vZiBlLmVudHJpZXMoKSluLnB1c2goe3R5cGU6InNvdXJjZW1hcCIsY29kZV9maWxlOnQsZGVidWdfaWQ6cn0pO3QuZGVidWdfbWV0YT17aW1hZ2VzOm59fX0oZSk7Y29uc3Qgcj1PdChlLG5uLmRzbixubi5zZGtNZXRhZGF0YSxubi50dW5uZWwpO3NuKEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCBmbi5zZW5kKHIpLGF3YWl0IGZuLmZsdXNoKDJlMykscm4+PW5uLm1heEFuckV2ZW50cyYmc2V0VGltZW91dCgoKT0+e3Byb2Nlc3MuZXhpdCgwKX0sNWUzKX1sZXQgbG47aWYoc24oIlN0YXJ0ZWQiKSxubi5jYXB0dXJlU3RhY2tUcmFjZSl7c24oIkNvbm5lY3RpbmcgdG8gZGVidWdnZXIiKTtjb25zdCBuPW5ldyB0O24uY29ubmVjdFRvTWFpblRocmVhZCgpLHNuKCJDb25uZWN0ZWQgdG8gZGVidWdnZXIiKTtjb25zdCBlPW5ldyBNYXA7bi5vbigiRGVidWdnZXIuc2NyaXB0UGFyc2VkIix0PT57ZS5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pLG4ub24oIkRlYnVnZ2VyLnBhdXNlZCIsdD0+e2lmKCJvdGhlciI9PT10LnBhcmFtcy5yZWFzb24pdHJ5e3NuKCJEZWJ1Z2dlciBwYXVzZWQiKTtjb25zdCBpPVsuLi50LnBhcmFtcy5jYWxsRnJhbWVzXSxzPW5uLmFwcFJvb3RQYXRoP2Z1bmN0aW9uKHQ9KHByb2Nlc3MuYXJndlsxXT9HdChwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLG49IlxcIj09PW8pe2NvbnN0IGU9bj90bih0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89bj90bih0KTp0O2xldHtkaXI6aSxiYXNlOnMsZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwocz1zLnNsaWNlKDAsLTEqYy5sZW5ndGgpKTtjb25zdCB1PWRlY29kZVVSSUNvbXBvbmVudChzKTtpfHwoaT0iLiIpO2NvbnN0IGE9aS5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7aS5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7dX1gO2lmKGkuc3RhcnRzV2l0aChlKSl7Y29uc3QgdD1pLnNsaWNlKGUubGVuZ3RoKzEpLnJlcGxhY2UoL1wvL2csIi4iKTtyZXR1cm4gdD9gJHt0fToke3V9YDp1fXJldHVybiB1fX0obm4uYXBwUm9vdFBhdGgpOigpPT57fSxjPWkubWFwKHQ9PmZ1bmN0aW9uKHQsbixlKXtjb25zdCByPW4/bi5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAsaT10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybntmaWxlbmFtZTpyLG1vZHVsZTplKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHwiPyIsY29sbm86byxsaW5lbm86aSxpbl9hcHA6cj9IdChyKTp2b2lkIDB9fSh0LGUuZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLHMpKSx1PXNldFRpbWVvdXQoKCk9PntkbihjKS50aGVuKG51bGwsKCk9PntzbigiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSl9LDVlMyk7bi5wb3N0KCJSdW50aW1lLmV2YWx1YXRlIix7ZXhwcmVzc2lvbjoiZ2xvYmFsLl9fU0VOVFJZX0dFVF9TQ09QRVNfXygpOyIsc2lsZW50OiEwLHJldHVybkJ5VmFsdWU6ITB9LCh0LGUpPT57dCYmc24oYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9ZT8ucmVzdWx0P2UucmVzdWx0LnZhbHVlOnZvaWQgMDtuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLGRuKGMscikudGhlbihudWxsLCgpPT57c24oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pfSl9Y2F0Y2godCl7dGhyb3cgbi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxuLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pLGxuPSgpPT57dHJ5e24ucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKT0+e24ucG9zdCgiRGVidWdnZXIucGF1c2UiKX0pfWNhdGNoe319fWNvbnN0e3BvbGw6bW59PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dCgpO2xldCBpPSExLHM9ITA7cmV0dXJuIHNldEludGVydmFsKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09aSYmdD5uK2UmJihpPSEwLHMmJnIoKSksdDxuK2UmJihpPSExKX0sMjApLHtwb2xsOigpPT57by5yZXNldCgpfSxlbmFibGVkOnQ9PntzPXR9fX0oZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtuLGVdPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMypuK2UvMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0sbm4ucG9sbEludGVydmFsLG5uLmFuclRocmVzaG9sZCxmdW5jdGlvbigpe3NuKCJXYXRjaGRvZyB0aW1lb3V0IiksbG4/KHNuKCJQYXVzaW5nIGRlYnVnZ2VyIHRvIGNhcHR1cmUgc3RhY2sgdHJhY2UiKSxsbigpKTooc24oIkNhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UiKSxkbigpLnRoZW4obnVsbCwoKT0+e3NuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKX0pO2U/Lm9uKCJtZXNzYWdlIix0PT57dC5zZXNzaW9uJiYoZW49WSh0LnNlc3Npb24pKSx0LmRlYnVnSW1hZ2VzJiYob249dC5kZWJ1Z0ltYWdlcyksbW4oKX0pOw==";
|
|
93401
93487
|
var DEFAULT_INTERVAL = 50;
|
|
93402
93488
|
var DEFAULT_HANG_THRESHOLD = 5000;
|
|
93403
|
-
function
|
|
93489
|
+
function log21(message2, ...args) {
|
|
93404
93490
|
core.debug.log(`[ANR] ${message2}`, ...args);
|
|
93405
93491
|
}
|
|
93406
93492
|
function globalWithScopeFetchFn() {
|
|
@@ -93513,17 +93599,17 @@ var require_anr2 = __commonJS((exports) => {
|
|
|
93513
93599
|
timer2.unref();
|
|
93514
93600
|
worker.on("message", (msg) => {
|
|
93515
93601
|
if (msg === "session-ended") {
|
|
93516
|
-
|
|
93602
|
+
log21("ANR event sent from ANR worker. Clearing session in this thread.");
|
|
93517
93603
|
core.getIsolationScope().setSession(undefined);
|
|
93518
93604
|
}
|
|
93519
93605
|
});
|
|
93520
93606
|
worker.once("error", (err2) => {
|
|
93521
93607
|
clearInterval(timer2);
|
|
93522
|
-
|
|
93608
|
+
log21("ANR worker error", err2);
|
|
93523
93609
|
});
|
|
93524
93610
|
worker.once("exit", (code) => {
|
|
93525
93611
|
clearInterval(timer2);
|
|
93526
|
-
|
|
93612
|
+
log21("ANR worker exit", code);
|
|
93527
93613
|
});
|
|
93528
93614
|
worker.unref();
|
|
93529
93615
|
return () => {
|
|
@@ -113843,7 +113929,7 @@ import { fileURLToPath } from "url";
|
|
|
113843
113929
|
// package.json
|
|
113844
113930
|
var package_default = {
|
|
113845
113931
|
name: "@automagik/omni",
|
|
113846
|
-
version: "2.260423.
|
|
113932
|
+
version: "2.260423.7",
|
|
113847
113933
|
description: "LLM-optimized CLI for Omni",
|
|
113848
113934
|
type: "module",
|
|
113849
113935
|
bin: {
|