mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 15:36:57 +10:00
297 lines
37 KiB
TypeScript
297 lines
37 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import chalk from 'chalk';
|
||
|
|
import * as React from 'react';
|
||
|
|
import type { CommandResultDisplay } from '../../commands.js';
|
||
|
|
import { ModelPicker } from '../../components/ModelPicker.js';
|
||
|
|
import { COMMON_HELP_ARGS, COMMON_INFO_ARGS } from '../../constants/xml.js';
|
||
|
|
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from '../../services/analytics/index.js';
|
||
|
|
import { useAppState, useSetAppState } from '../../state/AppState.js';
|
||
|
|
import type { LocalJSXCommandCall } from '../../types/command.js';
|
||
|
|
import type { EffortLevel } from '../../utils/effort.js';
|
||
|
|
import { isBilledAsExtraUsage } from '../../utils/extraUsage.js';
|
||
|
|
import { clearFastModeCooldown, isFastModeAvailable, isFastModeEnabled, isFastModeSupportedByModel } from '../../utils/fastMode.js';
|
||
|
|
import { MODEL_ALIASES } from '../../utils/model/aliases.js';
|
||
|
|
import { checkOpus1mAccess, checkSonnet1mAccess } from '../../utils/model/check1mAccess.js';
|
||
|
|
import { getDefaultMainLoopModelSetting, isOpus1mMergeEnabled, renderDefaultModelSetting } from '../../utils/model/model.js';
|
||
|
|
import { isModelAllowed } from '../../utils/model/modelAllowlist.js';
|
||
|
|
import { validateModel } from '../../utils/model/validateModel.js';
|
||
|
|
function ModelPickerWrapper(t0) {
|
||
|
|
const $ = _c(17);
|
||
|
|
const {
|
||
|
|
onDone
|
||
|
|
} = t0;
|
||
|
|
const mainLoopModel = useAppState(_temp);
|
||
|
|
const mainLoopModelForSession = useAppState(_temp2);
|
||
|
|
const isFastMode = useAppState(_temp3);
|
||
|
|
const setAppState = useSetAppState();
|
||
|
|
let t1;
|
||
|
|
if ($[0] !== mainLoopModel || $[1] !== onDone) {
|
||
|
|
t1 = function handleCancel() {
|
||
|
|
logEvent("tengu_model_command_menu", {
|
||
|
|
action: "cancel" as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||
|
|
});
|
||
|
|
const displayModel = renderModelLabel(mainLoopModel);
|
||
|
|
onDone(`Kept model as ${chalk.bold(displayModel)}`, {
|
||
|
|
display: "system"
|
||
|
|
});
|
||
|
|
};
|
||
|
|
$[0] = mainLoopModel;
|
||
|
|
$[1] = onDone;
|
||
|
|
$[2] = t1;
|
||
|
|
} else {
|
||
|
|
t1 = $[2];
|
||
|
|
}
|
||
|
|
const handleCancel = t1;
|
||
|
|
let t2;
|
||
|
|
if ($[3] !== isFastMode || $[4] !== mainLoopModel || $[5] !== onDone || $[6] !== setAppState) {
|
||
|
|
t2 = function handleSelect(model, effort) {
|
||
|
|
logEvent("tengu_model_command_menu", {
|
||
|
|
action: model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||
|
|
from_model: mainLoopModel as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||
|
|
to_model: model as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||
|
|
});
|
||
|
|
setAppState(prev => ({
|
||
|
|
...prev,
|
||
|
|
mainLoopModel: model,
|
||
|
|
mainLoopModelForSession: null
|
||
|
|
}));
|
||
|
|
let message = `Set model to ${chalk.bold(renderModelLabel(model))}`;
|
||
|
|
if (effort !== undefined) {
|
||
|
|
message = message + ` with ${chalk.bold(effort)} effort`;
|
||
|
|
}
|
||
|
|
let wasFastModeToggledOn = undefined;
|
||
|
|
if (isFastModeEnabled()) {
|
||
|
|
clearFastModeCooldown();
|
||
|
|
if (!isFastModeSupportedByModel(model) && isFastMode) {
|
||
|
|
setAppState(_temp4);
|
||
|
|
wasFastModeToggledOn = false;
|
||
|
|
} else {
|
||
|
|
if (isFastModeSupportedByModel(model) && isFastModeAvailable() && isFastMode) {
|
||
|
|
message = message + " \xB7 Fast mode ON";
|
||
|
|
wasFastModeToggledOn = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (isBilledAsExtraUsage(model, wasFastModeToggledOn === true, isOpus1mMergeEnabled())) {
|
||
|
|
message = message + " \xB7 Billed as extra usage";
|
||
|
|
}
|
||
|
|
if (wasFastModeToggledOn === false) {
|
||
|
|
message = message + " \xB7 Fast mode OFF";
|
||
|
|
}
|
||
|
|
onDone(message);
|
||
|
|
};
|
||
|
|
$[3] = isFastMode;
|
||
|
|
$[4] = mainLoopModel;
|
||
|
|
$[5] = onDone;
|
||
|
|
$[6] = setAppState;
|
||
|
|
$[7] = t2;
|
||
|
|
} else {
|
||
|
|
t2 = $[7];
|
||
|
|
}
|
||
|
|
const handleSelect = t2;
|
||
|
|
let t3;
|
||
|
|
if ($[8] !== isFastMode || $[9] !== mainLoopModel) {
|
||
|
|
t3 = isFastModeEnabled() && isFastMode && isFastModeSupportedByModel(mainLoopModel) && isFastModeAvailable();
|
||
|
|
$[8] = isFastMode;
|
||
|
|
$[9] = mainLoopModel;
|
||
|
|
$[10] = t3;
|
||
|
|
} else {
|
||
|
|
t3 = $[10];
|
||
|
|
}
|
||
|
|
let t4;
|
||
|
|
if ($[11] !== handleCancel || $[12] !== handleSelect || $[13] !== mainLoopModel || $[14] !== mainLoopModelForSession || $[15] !== t3) {
|
||
|
|
t4 = <ModelPicker initial={mainLoopModel} sessionModel={mainLoopModelForSession} onSelect={handleSelect} onCancel={handleCancel} isStandaloneCommand={true} showFastModeNotice={t3} />;
|
||
|
|
$[11] = handleCancel;
|
||
|
|
$[12] = handleSelect;
|
||
|
|
$[13] = mainLoopModel;
|
||
|
|
$[14] = mainLoopModelForSession;
|
||
|
|
$[15] = t3;
|
||
|
|
$[16] = t4;
|
||
|
|
} else {
|
||
|
|
t4 = $[16];
|
||
|
|
}
|
||
|
|
return t4;
|
||
|
|
}
|
||
|
|
function _temp4(prev_0) {
|
||
|
|
return {
|
||
|
|
...prev_0,
|
||
|
|
fastMode: false
|
||
|
|
};
|
||
|
|
}
|
||
|
|
function _temp3(s_1) {
|
||
|
|
return s_1.fastMode;
|
||
|
|
}
|
||
|
|
function _temp2(s_0) {
|
||
|
|
return s_0.mainLoopModelForSession;
|
||
|
|
}
|
||
|
|
function _temp(s) {
|
||
|
|
return s.mainLoopModel;
|
||
|
|
}
|
||
|
|
function SetModelAndClose({
|
||
|
|
args,
|
||
|
|
onDone
|
||
|
|
}: {
|
||
|
|
args: string;
|
||
|
|
onDone: (result?: string, options?: {
|
||
|
|
display?: CommandResultDisplay;
|
||
|
|
}) => void;
|
||
|
|
}): React.ReactNode {
|
||
|
|
const isFastMode = useAppState(s => s.fastMode);
|
||
|
|
const setAppState = useSetAppState();
|
||
|
|
const model = args === 'default' ? null : args;
|
||
|
|
React.useEffect(() => {
|
||
|
|
async function handleModelChange(): Promise<void> {
|
||
|
|
if (model && !isModelAllowed(model)) {
|
||
|
|
onDone(`Model '${model}' is not available. Your organization restricts model selection.`, {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// @[MODEL LAUNCH]: Update check for 1M access.
|
||
|
|
if (model && isOpus1mUnavailable(model)) {
|
||
|
|
onDone(`Opus 4.6 with 1M context is not available for your account. Learn more: https://code.claude.com/docs/en/model-config#extended-context-with-1m`, {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (model && isSonnet1mUnavailable(model)) {
|
||
|
|
onDone(`Sonnet 4.6 with 1M context is not available for your account. Learn more: https://code.claude.com/docs/en/model-config#extended-context-with-1m`, {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Skip validation for default model
|
||
|
|
if (!model) {
|
||
|
|
setModel(null);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Skip validation for known aliases - they're predefined and should work
|
||
|
|
if (isKnownAlias(model)) {
|
||
|
|
setModel(model);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate and set custom model
|
||
|
|
try {
|
||
|
|
// Don't use parseUserSpecifiedModel for non-aliases since it lowercases the input
|
||
|
|
// and model names are case-sensitive
|
||
|
|
const {
|
||
|
|
valid,
|
||
|
|
error: error_0
|
||
|
|
} = await validateModel(model);
|
||
|
|
if (valid) {
|
||
|
|
setModel(model);
|
||
|
|
} else {
|
||
|
|
onDone(error_0 || `Model '${model}' not found`, {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
onDone(`Failed to validate model: ${(error as Error).message}`, {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function setModel(modelValue: string | null): void {
|
||
|
|
setAppState(prev => ({
|
||
|
|
...prev,
|
||
|
|
mainLoopModel: modelValue,
|
||
|
|
mainLoopModelForSession: null
|
||
|
|
}));
|
||
|
|
let message = `Set model to ${chalk.bold(renderModelLabel(modelValue))}`;
|
||
|
|
let wasFastModeToggledOn = undefined;
|
||
|
|
if (isFastModeEnabled()) {
|
||
|
|
clearFastModeCooldown();
|
||
|
|
if (!isFastModeSupportedByModel(modelValue) && isFastMode) {
|
||
|
|
setAppState(prev_0 => ({
|
||
|
|
...prev_0,
|
||
|
|
fastMode: false
|
||
|
|
}));
|
||
|
|
wasFastModeToggledOn = false;
|
||
|
|
// Do not update fast mode in settings since this is an automatic downgrade
|
||
|
|
} else if (isFastModeSupportedByModel(modelValue) && isFastMode) {
|
||
|
|
message += ` · Fast mode ON`;
|
||
|
|
wasFastModeToggledOn = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (isBilledAsExtraUsage(modelValue, wasFastModeToggledOn === true, isOpus1mMergeEnabled())) {
|
||
|
|
message += ` · Billed as extra usage`;
|
||
|
|
}
|
||
|
|
if (wasFastModeToggledOn === false) {
|
||
|
|
// Fast mode was toggled off, show suffix after extra usage billing
|
||
|
|
message += ` · Fast mode OFF`;
|
||
|
|
}
|
||
|
|
onDone(message);
|
||
|
|
}
|
||
|
|
void handleModelChange();
|
||
|
|
}, [model, onDone, setAppState]);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
function isKnownAlias(model: string): boolean {
|
||
|
|
return (MODEL_ALIASES as readonly string[]).includes(model.toLowerCase().trim());
|
||
|
|
}
|
||
|
|
function isOpus1mUnavailable(model: string): boolean {
|
||
|
|
const m = model.toLowerCase();
|
||
|
|
return !checkOpus1mAccess() && !isOpus1mMergeEnabled() && m.includes('opus') && m.includes('[1m]');
|
||
|
|
}
|
||
|
|
function isSonnet1mUnavailable(model: string): boolean {
|
||
|
|
const m = model.toLowerCase();
|
||
|
|
// Warn about Sonnet and Sonnet 4.6, but not Sonnet 4.5 since that had
|
||
|
|
// a different access criteria.
|
||
|
|
return !checkSonnet1mAccess() && (m.includes('sonnet[1m]') || m.includes('sonnet-4-6[1m]'));
|
||
|
|
}
|
||
|
|
function ShowModelAndClose(t0) {
|
||
|
|
const {
|
||
|
|
onDone
|
||
|
|
} = t0;
|
||
|
|
const mainLoopModel = useAppState(_temp7);
|
||
|
|
const mainLoopModelForSession = useAppState(_temp8);
|
||
|
|
const effortValue = useAppState(_temp9);
|
||
|
|
const displayModel = renderModelLabel(mainLoopModel);
|
||
|
|
const effortInfo = effortValue !== undefined ? ` (effort: ${effortValue})` : "";
|
||
|
|
if (mainLoopModelForSession) {
|
||
|
|
onDone(`Current model: ${chalk.bold(renderModelLabel(mainLoopModelForSession))} (session override from plan mode)\nBase model: ${displayModel}${effortInfo}`);
|
||
|
|
} else {
|
||
|
|
onDone(`Current model: ${displayModel}${effortInfo}`);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
function _temp9(s_1) {
|
||
|
|
return s_1.effortValue;
|
||
|
|
}
|
||
|
|
function _temp8(s_0) {
|
||
|
|
return s_0.mainLoopModelForSession;
|
||
|
|
}
|
||
|
|
function _temp7(s) {
|
||
|
|
return s.mainLoopModel;
|
||
|
|
}
|
||
|
|
export const call: LocalJSXCommandCall = async (onDone, _context, args) => {
|
||
|
|
args = args?.trim() || '';
|
||
|
|
if (COMMON_INFO_ARGS.includes(args)) {
|
||
|
|
logEvent('tengu_model_command_inline_help', {
|
||
|
|
args: args as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||
|
|
});
|
||
|
|
return <ShowModelAndClose onDone={onDone} />;
|
||
|
|
}
|
||
|
|
if (COMMON_HELP_ARGS.includes(args)) {
|
||
|
|
onDone('Run /model to open the model selection menu, or /model [modelName] to set the model.', {
|
||
|
|
display: 'system'
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (args) {
|
||
|
|
logEvent('tengu_model_command_inline', {
|
||
|
|
args: args as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||
|
|
});
|
||
|
|
return <SetModelAndClose args={args} onDone={onDone} />;
|
||
|
|
}
|
||
|
|
return <ModelPickerWrapper onDone={onDone} />;
|
||
|
|
};
|
||
|
|
function renderModelLabel(model: string | null): string {
|
||
|
|
const rendered = renderDefaultModelSetting(model ?? getDefaultMainLoopModelSetting());
|
||
|
|
return model === null ? `${rendered} (default)` : rendered;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjaGFsayIsIlJlYWN0IiwiQ29tbWFuZFJlc3VsdERpc3BsYXkiLCJNb2RlbFBpY2tlciIsIkNPTU1PTl9IRUxQX0FSR1MiLCJDT01NT05fSU5GT19BUkdTIiwiQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyIsImxvZ0V2ZW50IiwidXNlQXBwU3RhdGUiLCJ1c2VTZXRBcHBTdGF0ZSIsIkxvY2FsSlNYQ29tbWFuZENhbGwiLCJFZmZvcnRMZXZlbCIsImlzQmlsbGVkQXNFeHRyYVVzYWdlIiwiY2xlYXJGYXN0TW9kZUNvb2xkb3duIiwiaXNGYXN0TW9kZUF2YWlsYWJsZSIsImlzRmFzdE1vZGVFbmFibGVkIiwiaXNGYXN0TW9kZVN1cHBvcnRlZEJ5TW9kZWwiLCJNT0RFTF9BTElBU0VTIiwiY2hlY2tPcHVzMW1BY2Nlc3MiLCJjaGVja1Nvbm5ldDFtQWNjZXNzIiwiZ2V0RGVmYXVsdE1haW5Mb29wTW9kZWxTZXR0aW5nIiwiaXNPcHVzMW1NZXJnZUVuYWJsZWQiLCJyZW5kZXJEZWZhdWx0TW9kZWxTZXR0aW5nIiwiaXNNb2RlbEFsbG93ZWQiLCJ2YWxpZGF0ZU1vZGVsIiwiTW9kZWxQaWNrZXJXcmFwcGVyIiwidDAiLCIkIiwiX2MiLCJvbkRvbmUiLCJtYWluTG9vcE1vZGVsIiwiX3RlbXAiLCJtYWluTG9vcE1vZGVsRm9yU2Vzc2lvbiIsIl90ZW1wMiIsImlzRmFzdE1vZGUiLCJfdGVtcDMiLCJzZXRBcHBTdGF0ZSIsInQxIiwiaGFuZGxlQ2FuY2VsIiwiYWN0aW9uIiwiZGlzcGxheU1vZGVsIiwicmVuZGVyTW9kZWxMYWJlbCIsImJvbGQiLCJkaXNwbGF5IiwidDIiLCJoYW5kbGVTZWxlY3QiLCJtb2RlbCIsImVmZm9ydCIsImZyb21fbW9kZWwiLCJ0b19tb2RlbCIsInByZXYiLCJtZXNzYWdlIiwidW5kZWZpbmVkIiwid2FzRmFzdE1vZGVUb2dnbGVkT24iLCJfdGVtcDQiLCJ0MyIsInQ0IiwicHJldl8wIiwiZmFzdE1vZGUiLCJzXzEiLCJzIiwic18wIiwiU2V0TW9kZWxBbmRDbG9zZSIsImFyZ3MiLCJyZXN1bHQiLCJvcHRpb25zIiwiUmVhY3ROb2RlIiwidXNlRWZmZWN0IiwiaGFuZGxlTW9kZWxDaGFuZ2UiLCJQcm9taXNlIiwiaXNPcHVzMW1VbmF2YWlsYWJsZSIsImlzU29ubmV0MW1VbmF2YWlsYWJsZSIsInNldE1vZGVsIiwiaXNLbm93bkFsaWFzIiwidmFsaWQiLCJlcnJvciIsIkVycm9yIiwibW9kZWxWYWx1ZSIsImluY2x1ZGVzIiwidG9Mb3dlckNhc2UiLCJ0cmltIiwibSIsIlNob3dNb2RlbEFuZENsb3NlIiwiX3RlbXA3IiwiX3RlbXA4IiwiZWZmb3J0VmFsdWUiLCJfdGVtcDkiLCJlZmZvcnRJbmZvIiwiY2FsbCIsIl9jb250ZXh0IiwicmVuZGVyZWQiXSwic291cmNlcyI6WyJtb2RlbC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJ1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IENvbW1hbmRSZXN1bHREaXNwbGF5IH0gZnJvbSAnLi4vLi4vY29tbWFuZHMuanMnXG5pbXBvcnQgeyBNb2RlbFBpY2tlciB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvTW9kZWxQaWNrZXIuanMnXG5pbXBvcnQgeyBDT01NT05fSEVMUF9BUkdTLCBDT01NT05fSU5GT19BUkdTIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL3htbC5qcydcbmltcG9ydCB7XG4gIHR5cGUgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyxcbiAgbG9nRXZlbnQsXG59IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB7IHVzZUFwcFN0YXRlLCB1c2VTZXRBcHBTdGF0ZSB9IGZyb20gJy4uLy4uL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHR5cGUgeyBMb2NhbEpTWENvbW1hbmRDYWxsIH0gZnJvbSAnLi4vLi4vdHlwZXMvY29tbWFuZC5qcydcbmltcG9ydCB0eXBlIHsgRWZmb3J0TGV2ZWwgfSBmcm9tICcuLi8uLi91dGlscy9lZmZvcnQuanMnXG5pbXBvcnQgeyBpc0JpbGxlZEFzRXh0cmFVc2FnZSB9IGZyb20gJy4uLy4uL3V0aWxzL2V4dHJhVXNhZ2UuanMnXG5pbXBvcnQge1xuICBjbGVhckZhc3RNb2RlQ29vbGRvd24sXG4gIGlzRmFzdE1vZGVBdmFpbGFibGUsXG4gIGlzRmFzdE1vZGVFbmFibGVkLFxuICBpc0Zhc3RNb2RlU3VwcG9ydGVkQnlNb2RlbCxcbn0gZnJvbSAnLi4vLi4vdXRpbHMvZmFzdE1vZGUuanMnXG5pbXBvcnQgeyBNT0RFTF9BTElBU0VTIH0gZnJvbSAnLi4vLi4vdXRpbHMvbW9kZWwvYWxpYXNlcy5qcydcbmltcG9ydCB7XG4gIGNoZWNrT3B1czFtQWNjZXNzLFxuICBjaGVja1Nvbm5ldDFtQWNjZXNzLFxufSBmcm9tICcuLi8uLi91dGlscy9tb2RlbC9jaGVjazFtQWNjZXNzLmpzJ1xuaW1wb3J0IHtcbiAgZ2V0RGVmYXVsdE1haW5Mb29wTW9kZWxTZXR0aW5nLFxuICBpc09wdXMxbU1lcmdlRW5hYmxlZCxcbiAgcmVuZGVyRGVmYXVsdE1vZGVsU2V0dGluZyxcbn0gZnJvbSAnLi4vLi4vdXRpbHMvbW9kZWwvbW9kZWwuanMnXG5pbXBvcnQgeyBpc01vZGVsQWxsb3dlZCB9IGZyb20gJy4uLy4uL3V0aWxzL21vZGVsL21vZGVsQWxsb3dsaXN0LmpzJ1xuaW1wb3J0IHsgdmFsaWRhdGVNb2RlbCB9IGZyb20gJy4uLy4uL3V0aWxzL21vZGVsL3ZhbGlkYXRlTW9kZWwuanMnXG5cbmZ1bmN0aW9uIE1vZGVsUGlja2VyV3JhcHBlcih7XG4gIG9uRG9uZSxcbn06IHtcbiAgb25Eb25lOiAoXG4gICAgcmVzdWx0Pzogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiB7IGRpc3BsYXk/OiBDb21tYW5kUmVzdWx0RGlzcGxheSB9LFxuICApID0+IHZvaWRcbn0pOiBSZWFjdC5SZWFjdE5vZGUge1xuICBjb25zdCBtYWluTG9vcE1vZGVsID0gdXNlQXBwU3RhdGUocyA9PiBzLm1haW5Mb29wTW9kZWwpXG4gIGNvbnN0IG1haW5Mb29wTW9kZWxGb3JTZXNzaW9uID0gdXNlQXBwU3RhdGUocyA9PiBzLm1haW5Mb29wTW9kZWxGb3JTZXNzaW9uKVxuICBjb25zdCBpc0Zhc3RNb2RlID0gdXNlQXBwU3RhdGUocyA9PiBzLmZhc3RNb2RlKVxuICBjb25zdCBzZXRBcHBTdGF0ZSA9IHVzZVNldEFwcFN0YXRlKClcblxuICBmdW5jdGlvbiBoYW5kbGVDYW5jZWwoKTogdm9pZCB7XG4gICAgbG9nRXZlbnQoJ3Rlbmd
|