@runtypelabs/cli 2.5.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/index.js +581 -52
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -15376,8 +15376,8 @@ var require_provider_routing = __commonJS({
|
|
|
15376
15376
|
});
|
|
15377
15377
|
|
|
15378
15378
|
// src/index.ts
|
|
15379
|
-
import { Command as
|
|
15380
|
-
import
|
|
15379
|
+
import { Command as Command21 } from "commander";
|
|
15380
|
+
import chalk28 from "chalk";
|
|
15381
15381
|
import { config as loadEnv } from "dotenv";
|
|
15382
15382
|
|
|
15383
15383
|
// src/commands/auth.ts
|
|
@@ -31682,14 +31682,542 @@ clientTokensCommand.command("regenerate <id>").description("Regenerate a client
|
|
|
31682
31682
|
await waitUntilExit();
|
|
31683
31683
|
});
|
|
31684
31684
|
|
|
31685
|
-
// src/commands/
|
|
31685
|
+
// src/commands/persona.ts
|
|
31686
31686
|
import { Command as Command17 } from "commander";
|
|
31687
31687
|
import chalk23 from "chalk";
|
|
31688
|
+
import readline3 from "readline";
|
|
31689
|
+
import open5 from "open";
|
|
31690
|
+
import { execFileSync } from "child_process";
|
|
31691
|
+
|
|
31692
|
+
// src/lib/persona-init.ts
|
|
31693
|
+
init_credential_store();
|
|
31694
|
+
|
|
31695
|
+
// src/lib/persona-snippets.ts
|
|
31696
|
+
function mapCliFormatToPersona(cli) {
|
|
31697
|
+
switch (cli) {
|
|
31698
|
+
case "script-installer":
|
|
31699
|
+
return "script-installer";
|
|
31700
|
+
case "script-manual":
|
|
31701
|
+
return "script-advanced";
|
|
31702
|
+
case "esm":
|
|
31703
|
+
case "react":
|
|
31704
|
+
return "react-component";
|
|
31705
|
+
default: {
|
|
31706
|
+
const _exhaustive = cli;
|
|
31707
|
+
return _exhaustive;
|
|
31708
|
+
}
|
|
31709
|
+
}
|
|
31710
|
+
}
|
|
31711
|
+
function parsePersonaInitFormat(raw) {
|
|
31712
|
+
const normalized = raw.trim().toLowerCase();
|
|
31713
|
+
if (normalized === "script-installer" || normalized === "script-manual" || normalized === "esm" || normalized === "react") {
|
|
31714
|
+
return normalized;
|
|
31715
|
+
}
|
|
31716
|
+
throw new Error(
|
|
31717
|
+
`Invalid --format "${raw}". Use: script-installer | script-manual | esm | react`
|
|
31718
|
+
);
|
|
31719
|
+
}
|
|
31720
|
+
var PERSONA_CDN_BASE = "https://cdn.jsdelivr.net/npm/@runtypelabs/persona@latest/dist";
|
|
31721
|
+
function mountIdFromSelector(sel) {
|
|
31722
|
+
const s = sel.trim();
|
|
31723
|
+
if (s.startsWith("#")) return s.slice(1);
|
|
31724
|
+
return s || "chat";
|
|
31725
|
+
}
|
|
31726
|
+
function escapeHtmlAttr(s) {
|
|
31727
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<");
|
|
31728
|
+
}
|
|
31729
|
+
function buildScriptInstaller(input) {
|
|
31730
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31731
|
+
if (!targetSel) {
|
|
31732
|
+
return `<script
|
|
31733
|
+
src="${PERSONA_CDN_BASE}/install.global.js"
|
|
31734
|
+
data-runtype-token="${escapeHtmlAttr(input.clientToken)}"
|
|
31735
|
+
></script>`.trim();
|
|
31736
|
+
}
|
|
31737
|
+
const id = mountIdFromSelector(targetSel);
|
|
31738
|
+
const cfg = JSON.stringify({ target: targetSel, apiUrl: input.apiUrl });
|
|
31739
|
+
return `<div id="${escapeHtmlAttr(id)}"></div>
|
|
31740
|
+
<script
|
|
31741
|
+
src="${PERSONA_CDN_BASE}/install.global.js"
|
|
31742
|
+
data-runtype-token="${escapeHtmlAttr(input.clientToken)}"
|
|
31743
|
+
data-config='${cfg.replace(/'/g, "'")}'
|
|
31744
|
+
></script>`.trim();
|
|
31745
|
+
}
|
|
31746
|
+
function buildScriptAdvancedHtml(input) {
|
|
31747
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31748
|
+
const apiUrl = JSON.stringify(input.apiUrl);
|
|
31749
|
+
const token = JSON.stringify(input.clientToken);
|
|
31750
|
+
const targetJson = JSON.stringify(targetSel || "body");
|
|
31751
|
+
const divLine = targetSel ? `<div id="${escapeHtmlAttr(mountIdFromSelector(targetSel))}"></div>
|
|
31752
|
+
` : "";
|
|
31753
|
+
return `<link rel="stylesheet" href="${PERSONA_CDN_BASE}/widget.css" />
|
|
31754
|
+
${divLine}<script type="module">
|
|
31755
|
+
import { initAgentWidget, markdownPostprocessor } from '${PERSONA_CDN_BASE}/index.js';
|
|
31756
|
+
|
|
31757
|
+
initAgentWidget({
|
|
31758
|
+
target: ${targetJson},
|
|
31759
|
+
config: {
|
|
31760
|
+
apiUrl: ${apiUrl},
|
|
31761
|
+
clientToken: ${token},
|
|
31762
|
+
parserType: 'json',
|
|
31763
|
+
postprocessMessage: ({ text }) => markdownPostprocessor(text),
|
|
31764
|
+
launcher: {
|
|
31765
|
+
enabled: true,
|
|
31766
|
+
title: 'Chat',
|
|
31767
|
+
subtitle: 'How can I help you today?',
|
|
31768
|
+
position: 'bottom-right',
|
|
31769
|
+
},
|
|
31770
|
+
},
|
|
31771
|
+
});
|
|
31772
|
+
</script>`.trim();
|
|
31773
|
+
}
|
|
31774
|
+
function buildReactComponentSnippet(input) {
|
|
31775
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31776
|
+
const apiUrl = JSON.stringify(input.apiUrl);
|
|
31777
|
+
const token = JSON.stringify(input.clientToken);
|
|
31778
|
+
const targetStr = JSON.stringify(targetSel || "body");
|
|
31779
|
+
return `import "@runtypelabs/persona/widget.css";
|
|
31780
|
+
import { DEFAULT_WIDGET_CONFIG, initAgentWidget, markdownPostprocessor } from "@runtypelabs/persona";
|
|
31781
|
+
|
|
31782
|
+
initAgentWidget({
|
|
31783
|
+
target: ${targetStr},
|
|
31784
|
+
config: {
|
|
31785
|
+
...DEFAULT_WIDGET_CONFIG,
|
|
31786
|
+
apiUrl: ${apiUrl},
|
|
31787
|
+
clientToken: ${token},
|
|
31788
|
+
parserType: "json",
|
|
31789
|
+
postprocessMessage: ({ text }) => markdownPostprocessor(text),
|
|
31790
|
+
},
|
|
31791
|
+
});`.trim();
|
|
31792
|
+
}
|
|
31793
|
+
function generatePersonaInitSnippet(input, personaFormat) {
|
|
31794
|
+
switch (personaFormat) {
|
|
31795
|
+
case "script-installer":
|
|
31796
|
+
return buildScriptInstaller(input);
|
|
31797
|
+
case "script-advanced":
|
|
31798
|
+
return buildScriptAdvancedHtml(input);
|
|
31799
|
+
case "react-component":
|
|
31800
|
+
return buildReactComponentSnippet(input);
|
|
31801
|
+
default: {
|
|
31802
|
+
const _exhaustive = personaFormat;
|
|
31803
|
+
return _exhaustive;
|
|
31804
|
+
}
|
|
31805
|
+
}
|
|
31806
|
+
}
|
|
31807
|
+
|
|
31808
|
+
// src/lib/persona-init.ts
|
|
31809
|
+
async function getPersonaInitApiKeyNonInteractive(apiUrl) {
|
|
31810
|
+
const envApiKey = getRuntimeApiKey();
|
|
31811
|
+
if (envApiKey) {
|
|
31812
|
+
try {
|
|
31813
|
+
const apiKeyManager = new ApiKeyManager();
|
|
31814
|
+
const isValid = await apiKeyManager.validateApiKey(envApiKey, apiUrl);
|
|
31815
|
+
if (isValid) {
|
|
31816
|
+
return envApiKey;
|
|
31817
|
+
}
|
|
31818
|
+
} catch {
|
|
31819
|
+
}
|
|
31820
|
+
}
|
|
31821
|
+
const store = new CredentialStore();
|
|
31822
|
+
return store.getApiKey();
|
|
31823
|
+
}
|
|
31824
|
+
async function runPersonaInit(options) {
|
|
31825
|
+
const client = new ApiClient(options.apiKey, options.apiUrl);
|
|
31826
|
+
const agent = await client.post("/agents", {
|
|
31827
|
+
name: options.agentName,
|
|
31828
|
+
description: options.agentDescription || "A Persona test agent",
|
|
31829
|
+
config: {
|
|
31830
|
+
model: "qwen3.5-35b-a3b",
|
|
31831
|
+
systemPrompt: "You are a helpful assistant."
|
|
31832
|
+
}
|
|
31833
|
+
});
|
|
31834
|
+
const tokenBody = {
|
|
31835
|
+
name: options.tokenName,
|
|
31836
|
+
flowIds: [],
|
|
31837
|
+
agentIds: [agent.id],
|
|
31838
|
+
allowedOrigins: options.allowedOrigins,
|
|
31839
|
+
environment: options.environment,
|
|
31840
|
+
rateLimitPerMinute: 10,
|
|
31841
|
+
rateLimitPerHour: 100,
|
|
31842
|
+
maxMessagesPerSession: 100,
|
|
31843
|
+
sessionIdleTimeoutMinutes: 30
|
|
31844
|
+
};
|
|
31845
|
+
const tokenRes = await client.post("/client-tokens", tokenBody);
|
|
31846
|
+
const personaFormat = mapCliFormatToPersona(options.format);
|
|
31847
|
+
const code = generatePersonaInitSnippet(
|
|
31848
|
+
{
|
|
31849
|
+
clientToken: tokenRes.token,
|
|
31850
|
+
apiUrl: options.apiUrl,
|
|
31851
|
+
targetSelector: options.targetSelector
|
|
31852
|
+
},
|
|
31853
|
+
personaFormat
|
|
31854
|
+
);
|
|
31855
|
+
const dashboardBase = getDashboardUrl();
|
|
31856
|
+
const dashboardUrl = `${dashboardBase}/agents/${agent.id}`;
|
|
31857
|
+
return {
|
|
31858
|
+
status: "created",
|
|
31859
|
+
agent: { id: agent.id, name: agent.name },
|
|
31860
|
+
clientToken: {
|
|
31861
|
+
id: tokenRes.clientToken.id,
|
|
31862
|
+
name: tokenRes.clientToken.name,
|
|
31863
|
+
token: tokenRes.token,
|
|
31864
|
+
environment: options.environment
|
|
31865
|
+
},
|
|
31866
|
+
snippet: { format: options.format, code },
|
|
31867
|
+
dashboardUrl,
|
|
31868
|
+
warnings: tokenRes.warnings
|
|
31869
|
+
};
|
|
31870
|
+
}
|
|
31871
|
+
|
|
31872
|
+
// src/commands/persona.ts
|
|
31873
|
+
var FORMAT_CYCLE = [
|
|
31874
|
+
"script-installer",
|
|
31875
|
+
"react",
|
|
31876
|
+
"script-manual",
|
|
31877
|
+
"esm"
|
|
31878
|
+
];
|
|
31879
|
+
function defaultTokenName(agentName) {
|
|
31880
|
+
return `${agentName} Widget`;
|
|
31881
|
+
}
|
|
31882
|
+
async function promptLine(rl, question, defaultValue) {
|
|
31883
|
+
const hint = defaultValue ? chalk23.dim(` (${defaultValue})`) : "";
|
|
31884
|
+
const answer = await new Promise((resolve8) => {
|
|
31885
|
+
rl.question(`${question}${hint}: `, resolve8);
|
|
31886
|
+
});
|
|
31887
|
+
const trimmed = answer.trim();
|
|
31888
|
+
if (!trimmed && defaultValue !== void 0) {
|
|
31889
|
+
return defaultValue;
|
|
31890
|
+
}
|
|
31891
|
+
return trimmed;
|
|
31892
|
+
}
|
|
31893
|
+
async function promptConfirm2(rl, message, defaultYes = false) {
|
|
31894
|
+
const hint = defaultYes ? chalk23.dim(" (Y/n)") : chalk23.dim(" (y/N)");
|
|
31895
|
+
const answer = await new Promise((resolve8) => {
|
|
31896
|
+
rl.question(`${message}${hint}: `, resolve8);
|
|
31897
|
+
});
|
|
31898
|
+
const t = answer.trim().toLowerCase();
|
|
31899
|
+
if (t === "") return defaultYes;
|
|
31900
|
+
return t === "y" || t === "yes";
|
|
31901
|
+
}
|
|
31902
|
+
function copyToClipboard2(text) {
|
|
31903
|
+
if (process.platform === "darwin") {
|
|
31904
|
+
execFileSync("pbcopy", [], { input: text });
|
|
31905
|
+
return;
|
|
31906
|
+
}
|
|
31907
|
+
if (process.platform === "win32") {
|
|
31908
|
+
execFileSync("clip", [], { shell: true, input: text });
|
|
31909
|
+
return;
|
|
31910
|
+
}
|
|
31911
|
+
try {
|
|
31912
|
+
execFileSync("xclip", ["-selection", "clipboard"], { input: text });
|
|
31913
|
+
} catch {
|
|
31914
|
+
execFileSync("wl-copy", [], { input: text });
|
|
31915
|
+
}
|
|
31916
|
+
}
|
|
31917
|
+
function isProbablyLocalDev(origins) {
|
|
31918
|
+
return origins.some(
|
|
31919
|
+
(o) => o === "http://localhost:*" || o.startsWith("http://localhost:") || o.startsWith("http://127.0.0.1:")
|
|
31920
|
+
);
|
|
31921
|
+
}
|
|
31922
|
+
function snippetWithFormat(format, token, apiUrl, targetSelector) {
|
|
31923
|
+
const personaFmt = mapCliFormatToPersona(format);
|
|
31924
|
+
const code = generatePersonaInitSnippet(
|
|
31925
|
+
{ clientToken: token, apiUrl, targetSelector },
|
|
31926
|
+
personaFmt
|
|
31927
|
+
);
|
|
31928
|
+
return { format, code };
|
|
31929
|
+
}
|
|
31930
|
+
async function runSuccessKeyLoop(initial, apiUrl, targetSelector) {
|
|
31931
|
+
if (!process.stdin.isTTY) {
|
|
31932
|
+
return;
|
|
31933
|
+
}
|
|
31934
|
+
let currentFormat = initial.snippet.format;
|
|
31935
|
+
let currentCode = initial.snippet.code;
|
|
31936
|
+
const token = initial.clientToken.token;
|
|
31937
|
+
console.log(chalk23.cyan("\nPersona setup complete\n"));
|
|
31938
|
+
console.log(`${chalk23.bold("Agent ID:")} ${initial.agent.id}`);
|
|
31939
|
+
console.log(`${chalk23.bold("Client Token ID:")} ${initial.clientToken.id}`);
|
|
31940
|
+
console.log(`${chalk23.bold("Client Token:")} ${chalk23.yellow(token)}`);
|
|
31941
|
+
console.log(`${chalk23.bold("Snippet format:")} ${currentFormat}`);
|
|
31942
|
+
console.log(chalk23.dim(`
|
|
31943
|
+
Dashboard: ${initial.dashboardUrl}`));
|
|
31944
|
+
if (initial.warnings?.length) {
|
|
31945
|
+
for (const w of initial.warnings) {
|
|
31946
|
+
console.log(chalk23.yellow(`\u26A0 ${w.message}`));
|
|
31947
|
+
}
|
|
31948
|
+
}
|
|
31949
|
+
console.log(chalk23.cyan("\nKeys:"));
|
|
31950
|
+
console.log(` ${chalk23.green("c")} Copy snippet to clipboard`);
|
|
31951
|
+
console.log(` ${chalk23.green("p")} Print snippet to the terminal`);
|
|
31952
|
+
console.log(` ${chalk23.green("f")} Switch snippet format`);
|
|
31953
|
+
console.log(` ${chalk23.green("o")} Open dashboard in browser`);
|
|
31954
|
+
console.log(` ${chalk23.green("q")} Quit`);
|
|
31955
|
+
readline3.emitKeypressEvents(process.stdin);
|
|
31956
|
+
if (process.stdin.isTTY) {
|
|
31957
|
+
process.stdin.setRawMode(true);
|
|
31958
|
+
}
|
|
31959
|
+
process.stdin.resume();
|
|
31960
|
+
const cleanup = () => {
|
|
31961
|
+
process.stdin.setRawMode(false);
|
|
31962
|
+
process.stdin.removeAllListeners("keypress");
|
|
31963
|
+
process.stdin.pause();
|
|
31964
|
+
};
|
|
31965
|
+
await new Promise((resolve8) => {
|
|
31966
|
+
const onKeypress = async (_str, key) => {
|
|
31967
|
+
if (!key) return;
|
|
31968
|
+
if (key.ctrl && key.name === "c") {
|
|
31969
|
+
cleanup();
|
|
31970
|
+
resolve8();
|
|
31971
|
+
process.exit(0);
|
|
31972
|
+
}
|
|
31973
|
+
const name = key.name;
|
|
31974
|
+
if (name === "q" || name === "escape") {
|
|
31975
|
+
cleanup();
|
|
31976
|
+
resolve8();
|
|
31977
|
+
return;
|
|
31978
|
+
}
|
|
31979
|
+
if (name === "c") {
|
|
31980
|
+
try {
|
|
31981
|
+
copyToClipboard2(currentCode);
|
|
31982
|
+
console.log(chalk23.green("Snippet copied to clipboard."));
|
|
31983
|
+
} catch {
|
|
31984
|
+
console.log(chalk23.red("Could not copy (install xclip/wl-copy on Linux, or use p)."));
|
|
31985
|
+
}
|
|
31986
|
+
return;
|
|
31987
|
+
}
|
|
31988
|
+
if (name === "p") {
|
|
31989
|
+
console.log(chalk23.cyan("\n--- snippet ---\n"));
|
|
31990
|
+
console.log(currentCode);
|
|
31991
|
+
console.log(chalk23.cyan("\n--- end snippet ---\n"));
|
|
31992
|
+
return;
|
|
31993
|
+
}
|
|
31994
|
+
if (name === "f") {
|
|
31995
|
+
const idx = FORMAT_CYCLE.indexOf(currentFormat);
|
|
31996
|
+
const next = FORMAT_CYCLE[(idx + 1) % FORMAT_CYCLE.length] ?? "script-installer";
|
|
31997
|
+
const nextSnippet = snippetWithFormat(next, token, apiUrl, targetSelector);
|
|
31998
|
+
currentFormat = nextSnippet.format;
|
|
31999
|
+
currentCode = nextSnippet.code;
|
|
32000
|
+
console.log(chalk23.dim(`Format: ${currentFormat}`));
|
|
32001
|
+
return;
|
|
32002
|
+
}
|
|
32003
|
+
if (name === "o") {
|
|
32004
|
+
try {
|
|
32005
|
+
await open5(initial.dashboardUrl);
|
|
32006
|
+
} catch {
|
|
32007
|
+
console.log(chalk23.red("Could not open browser."));
|
|
32008
|
+
}
|
|
32009
|
+
}
|
|
32010
|
+
};
|
|
32011
|
+
process.stdin.on("keypress", onKeypress);
|
|
32012
|
+
});
|
|
32013
|
+
}
|
|
32014
|
+
var personaCommand = new Command17("persona").description(
|
|
32015
|
+
"Set up Persona: create an agent, client token, and embed snippet"
|
|
32016
|
+
);
|
|
32017
|
+
personaCommand.command("init").description("Create agent + client token and output a Persona embed snippet").option("--agent-name <name>", "Name for the new agent").option("--agent-description <text", "Optional agent description").option("--token-name <name>", "Name for the new client token").option("--environment <env>", "Token environment: test or live", "test").option("--origins <origins...>", "Allowed origins (default: * \u2014 broad; prefer explicit URLs in production)").option(
|
|
32018
|
+
"--format <fmt>",
|
|
32019
|
+
"Snippet format: script-installer | script-manual | esm | react",
|
|
32020
|
+
"script-installer"
|
|
32021
|
+
).option("--print-snippet", "Print the generated snippet to stdout (non-interactive summary mode)").option("--target-selector <selector>", "CSS selector for widget mount target (omit to use body)").option("--api-url <url>", "Override API base URL").option("--json", "Structured JSON output (includes snippet body)").option("--yes", "Accept defaults in interactive prompts where sensible").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
|
|
32022
|
+
async (options, cmd) => {
|
|
32023
|
+
const globals = cmd.optsWithGlobals();
|
|
32024
|
+
const jsonMode = !!(options.json ?? globals.json);
|
|
32025
|
+
const tty = isTTY(options);
|
|
32026
|
+
let formatCli;
|
|
32027
|
+
try {
|
|
32028
|
+
formatCli = parsePersonaInitFormat(options.format);
|
|
32029
|
+
} catch (e) {
|
|
32030
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
32031
|
+
if (jsonMode) {
|
|
32032
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "INVALID_FORMAT" }, null, 2));
|
|
32033
|
+
} else {
|
|
32034
|
+
console.error(chalk23.red(msg));
|
|
32035
|
+
}
|
|
32036
|
+
process.exit(1);
|
|
32037
|
+
}
|
|
32038
|
+
const apiUrl = options.apiUrl || globals.apiUrl || getApiUrl();
|
|
32039
|
+
const targetSelector = options.targetSelector || void 0;
|
|
32040
|
+
let env;
|
|
32041
|
+
if (options.environment === "test" || options.environment === "live") {
|
|
32042
|
+
env = options.environment;
|
|
32043
|
+
} else {
|
|
32044
|
+
const msg = 'Error: --environment must be "test" or "live"';
|
|
32045
|
+
if (jsonMode) {
|
|
32046
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "INVALID_ENV" }, null, 2));
|
|
32047
|
+
} else {
|
|
32048
|
+
console.error(chalk23.red(msg));
|
|
32049
|
+
}
|
|
32050
|
+
process.exit(1);
|
|
32051
|
+
}
|
|
32052
|
+
const interactive = tty && !jsonMode;
|
|
32053
|
+
let agentName = options.agentName?.trim();
|
|
32054
|
+
let tokenName = options.tokenName?.trim();
|
|
32055
|
+
let allowedOrigins = options.origins;
|
|
32056
|
+
let chosenEnv = env;
|
|
32057
|
+
const rl = interactive && process.stdin.isTTY && process.stdout.isTTY ? readline3.createInterface({ input: process.stdin, output: process.stdout }) : null;
|
|
32058
|
+
if (!interactive) {
|
|
32059
|
+
if (!agentName) {
|
|
32060
|
+
const msg = "Non-interactive mode requires --agent-name";
|
|
32061
|
+
if (jsonMode) {
|
|
32062
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "MISSING_AGENT_NAME" }, null, 2));
|
|
32063
|
+
} else {
|
|
32064
|
+
console.error(chalk23.red(msg));
|
|
32065
|
+
}
|
|
32066
|
+
process.exit(1);
|
|
32067
|
+
}
|
|
32068
|
+
if (!tokenName) {
|
|
32069
|
+
tokenName = defaultTokenName(agentName);
|
|
32070
|
+
}
|
|
32071
|
+
if (!allowedOrigins || allowedOrigins.length === 0) {
|
|
32072
|
+
allowedOrigins = ["*"];
|
|
32073
|
+
}
|
|
32074
|
+
} else {
|
|
32075
|
+
if (!agentName) {
|
|
32076
|
+
agentName = await promptLine(rl, "Agent name", "Persona Test");
|
|
32077
|
+
if (!agentName) {
|
|
32078
|
+
console.error(chalk23.red("Agent name is required"));
|
|
32079
|
+
process.exit(1);
|
|
32080
|
+
}
|
|
32081
|
+
}
|
|
32082
|
+
if (!tokenName) {
|
|
32083
|
+
const def = options.yes ? defaultTokenName(agentName) : defaultTokenName(agentName);
|
|
32084
|
+
tokenName = await promptLine(rl, "Client token name", def);
|
|
32085
|
+
if (!tokenName) {
|
|
32086
|
+
tokenName = def;
|
|
32087
|
+
}
|
|
32088
|
+
}
|
|
32089
|
+
if (!allowedOrigins?.length) {
|
|
32090
|
+
if (options.yes) {
|
|
32091
|
+
allowedOrigins = ["*"];
|
|
32092
|
+
} else {
|
|
32093
|
+
const originsInput = await promptLine(
|
|
32094
|
+
rl,
|
|
32095
|
+
"Allowed origins (space-separated URLs, or * for any)",
|
|
32096
|
+
"*"
|
|
32097
|
+
);
|
|
32098
|
+
allowedOrigins = originsInput === "*" ? ["*"] : originsInput.split(/\s+/).filter(Boolean);
|
|
32099
|
+
}
|
|
32100
|
+
}
|
|
32101
|
+
if (chosenEnv === "live") {
|
|
32102
|
+
const ok = await promptConfirm2(rl, chalk23.yellow("Create a LIVE token? This is shown only once."), false);
|
|
32103
|
+
if (!ok) {
|
|
32104
|
+
console.log(chalk23.gray("Aborted."));
|
|
32105
|
+
rl.close();
|
|
32106
|
+
process.exit(0);
|
|
32107
|
+
}
|
|
32108
|
+
} else if (!options.yes) {
|
|
32109
|
+
const envAns = await promptLine(rl, "Environment (test/live)", "test");
|
|
32110
|
+
if (envAns === "live") {
|
|
32111
|
+
const ok = await promptConfirm2(rl, chalk23.yellow("Create a LIVE token?"), false);
|
|
32112
|
+
if (!ok) {
|
|
32113
|
+
chosenEnv = "test";
|
|
32114
|
+
} else {
|
|
32115
|
+
chosenEnv = "live";
|
|
32116
|
+
}
|
|
32117
|
+
}
|
|
32118
|
+
}
|
|
32119
|
+
}
|
|
32120
|
+
if (rl) {
|
|
32121
|
+
rl.close();
|
|
32122
|
+
}
|
|
32123
|
+
if (allowedOrigins.includes("*") && chosenEnv === "live" && !isProbablyLocalDev(allowedOrigins)) {
|
|
32124
|
+
console.log(
|
|
32125
|
+
chalk23.yellow(
|
|
32126
|
+
'Warning: allowedOrigins is "*" for a live token. Prefer explicit https:// origins in production.'
|
|
32127
|
+
)
|
|
32128
|
+
);
|
|
32129
|
+
}
|
|
32130
|
+
let apiKey;
|
|
32131
|
+
if (jsonMode || !tty) {
|
|
32132
|
+
apiKey = await getPersonaInitApiKeyNonInteractive(apiUrl);
|
|
32133
|
+
if (!apiKey) {
|
|
32134
|
+
if (jsonMode) {
|
|
32135
|
+
console.log(
|
|
32136
|
+
JSON.stringify(
|
|
32137
|
+
{
|
|
32138
|
+
status: "unauthenticated",
|
|
32139
|
+
message: "Set RUNTYPE_API_KEY or run `runtype auth login` (uses saved credentials)"
|
|
32140
|
+
},
|
|
32141
|
+
null,
|
|
32142
|
+
2
|
|
32143
|
+
)
|
|
32144
|
+
);
|
|
32145
|
+
} else {
|
|
32146
|
+
console.error(
|
|
32147
|
+
chalk23.red(
|
|
32148
|
+
"Authentication required: set RUNTYPE_API_KEY or run `runtype auth login` for stored credentials"
|
|
32149
|
+
)
|
|
32150
|
+
);
|
|
32151
|
+
}
|
|
32152
|
+
process.exit(1);
|
|
32153
|
+
}
|
|
32154
|
+
} else {
|
|
32155
|
+
apiKey = await ensureAuth({ apiUrl });
|
|
32156
|
+
if (!apiKey) {
|
|
32157
|
+
process.exit(1);
|
|
32158
|
+
}
|
|
32159
|
+
}
|
|
32160
|
+
let success;
|
|
32161
|
+
try {
|
|
32162
|
+
success = await runPersonaInit({
|
|
32163
|
+
apiKey,
|
|
32164
|
+
apiUrl,
|
|
32165
|
+
agentName,
|
|
32166
|
+
agentDescription: options.agentDescription,
|
|
32167
|
+
tokenName,
|
|
32168
|
+
environment: chosenEnv,
|
|
32169
|
+
allowedOrigins,
|
|
32170
|
+
format: formatCli,
|
|
32171
|
+
targetSelector
|
|
32172
|
+
});
|
|
32173
|
+
} catch (err) {
|
|
32174
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32175
|
+
if (jsonMode) {
|
|
32176
|
+
console.log(JSON.stringify({ status: "error", error: message, code: "API_ERROR" }, null, 2));
|
|
32177
|
+
} else {
|
|
32178
|
+
console.error(chalk23.red("Persona init failed"));
|
|
32179
|
+
console.error(chalk23.red(message));
|
|
32180
|
+
}
|
|
32181
|
+
process.exit(1);
|
|
32182
|
+
}
|
|
32183
|
+
if (jsonMode) {
|
|
32184
|
+
printJson(success);
|
|
32185
|
+
return;
|
|
32186
|
+
}
|
|
32187
|
+
if (!tty || options.printSnippet) {
|
|
32188
|
+
console.log(chalk23.green("\nPersona setup complete\n"));
|
|
32189
|
+
console.log(`${chalk23.bold("Agent ID:")} ${success.agent.id}`);
|
|
32190
|
+
console.log(`${chalk23.bold("Client Token ID:")} ${success.clientToken.id}`);
|
|
32191
|
+
console.log(`${chalk23.bold("Client Token:")} ${chalk23.yellow(success.clientToken.token)}`);
|
|
32192
|
+
console.log(`${chalk23.bold("Format:")} ${success.snippet.format}`);
|
|
32193
|
+
console.log(chalk23.dim(`
|
|
32194
|
+
Dashboard: ${success.dashboardUrl}`));
|
|
32195
|
+
if (success.warnings?.length) {
|
|
32196
|
+
for (const w of success.warnings) {
|
|
32197
|
+
console.log(chalk23.yellow(`\u26A0 ${w.message}`));
|
|
32198
|
+
}
|
|
32199
|
+
}
|
|
32200
|
+
console.log(chalk23.cyan("\nRecommended next step: npm install @runtypelabs/persona"));
|
|
32201
|
+
if (options.printSnippet) {
|
|
32202
|
+
console.log(chalk23.cyan("\n--- snippet ---\n"));
|
|
32203
|
+
console.log(success.snippet.code);
|
|
32204
|
+
} else {
|
|
32205
|
+
console.log(chalk23.dim("\nUse --print-snippet to print the embed code, or run interactively for copy shortcuts."));
|
|
32206
|
+
}
|
|
32207
|
+
return;
|
|
32208
|
+
}
|
|
32209
|
+
await runSuccessKeyLoop(success, apiUrl, targetSelector);
|
|
32210
|
+
}
|
|
32211
|
+
);
|
|
32212
|
+
|
|
32213
|
+
// src/commands/analytics.ts
|
|
32214
|
+
import { Command as Command18 } from "commander";
|
|
32215
|
+
import chalk24 from "chalk";
|
|
31688
32216
|
import React16 from "react";
|
|
31689
32217
|
import { render as render16 } from "ink";
|
|
31690
32218
|
import { useState as useState30, useEffect as useEffect27 } from "react";
|
|
31691
32219
|
import { Text as Text33 } from "ink";
|
|
31692
|
-
var analyticsCommand = new
|
|
32220
|
+
var analyticsCommand = new Command18("analytics").description("View analytics and execution results");
|
|
31693
32221
|
analyticsCommand.command("stats").description("Show account statistics").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
31694
32222
|
const apiKey = await ensureAuth();
|
|
31695
32223
|
if (!apiKey) return;
|
|
@@ -31709,8 +32237,8 @@ analyticsCommand.command("stats").description("Show account statistics").option(
|
|
|
31709
32237
|
}
|
|
31710
32238
|
} catch (error) {
|
|
31711
32239
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31712
|
-
console.error(
|
|
31713
|
-
console.error(
|
|
32240
|
+
console.error(chalk24.red("Failed to fetch stats"));
|
|
32241
|
+
console.error(chalk24.red(message));
|
|
31714
32242
|
process.exit(1);
|
|
31715
32243
|
}
|
|
31716
32244
|
return;
|
|
@@ -31774,27 +32302,27 @@ analyticsCommand.command("results").description("List execution results").option
|
|
|
31774
32302
|
} else {
|
|
31775
32303
|
const results = data.data ?? [];
|
|
31776
32304
|
if (results.length === 0) {
|
|
31777
|
-
console.log(
|
|
32305
|
+
console.log(chalk24.gray("No results found"));
|
|
31778
32306
|
return;
|
|
31779
32307
|
}
|
|
31780
|
-
console.log(
|
|
32308
|
+
console.log(chalk24.cyan("Execution Results:"));
|
|
31781
32309
|
for (const result of results) {
|
|
31782
32310
|
const statusColor = result.status === "completed" ? "green" : "red";
|
|
31783
|
-
const date = result.createdAt ?
|
|
32311
|
+
const date = result.createdAt ? chalk24.gray(` ${result.createdAt}`) : "";
|
|
31784
32312
|
console.log(
|
|
31785
|
-
` ${
|
|
32313
|
+
` ${chalk24.green(result.id)} ${chalk24[statusColor](`[${result.status}]`)} flow=${chalk24.gray(result.flowId)} record=${chalk24.gray(result.recordId)}${date}`
|
|
31786
32314
|
);
|
|
31787
32315
|
}
|
|
31788
32316
|
const total = getTotalCount(data.pagination);
|
|
31789
32317
|
if (total !== void 0) {
|
|
31790
|
-
console.log(
|
|
32318
|
+
console.log(chalk24.dim(`
|
|
31791
32319
|
Total: ${total} results`));
|
|
31792
32320
|
}
|
|
31793
32321
|
}
|
|
31794
32322
|
} catch (error) {
|
|
31795
32323
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31796
|
-
console.error(
|
|
31797
|
-
console.error(
|
|
32324
|
+
console.error(chalk24.red("Failed to fetch results"));
|
|
32325
|
+
console.error(chalk24.red(message));
|
|
31798
32326
|
process.exit(1);
|
|
31799
32327
|
}
|
|
31800
32328
|
return;
|
|
@@ -31845,13 +32373,13 @@ analyticsCommand.command("results").description("List execution results").option
|
|
|
31845
32373
|
);
|
|
31846
32374
|
|
|
31847
32375
|
// src/commands/billing.ts
|
|
31848
|
-
import { Command as
|
|
31849
|
-
import
|
|
32376
|
+
import { Command as Command19 } from "commander";
|
|
32377
|
+
import chalk25 from "chalk";
|
|
31850
32378
|
import React17 from "react";
|
|
31851
32379
|
import { render as render17 } from "ink";
|
|
31852
32380
|
import { useState as useState31, useEffect as useEffect28 } from "react";
|
|
31853
|
-
import
|
|
31854
|
-
var billingCommand = new
|
|
32381
|
+
import open6 from "open";
|
|
32382
|
+
var billingCommand = new Command19("billing").description("View billing and subscription info");
|
|
31855
32383
|
billingCommand.command("status").description("Show current plan and usage").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
31856
32384
|
const apiKey = await ensureAuth();
|
|
31857
32385
|
if (!apiKey) return;
|
|
@@ -31888,8 +32416,8 @@ billingCommand.command("status").description("Show current plan and usage").opti
|
|
|
31888
32416
|
}
|
|
31889
32417
|
} catch (error) {
|
|
31890
32418
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31891
|
-
console.error(
|
|
31892
|
-
console.error(
|
|
32419
|
+
console.error(chalk25.red("Failed to fetch billing status"));
|
|
32420
|
+
console.error(chalk25.red(message));
|
|
31893
32421
|
process.exit(1);
|
|
31894
32422
|
}
|
|
31895
32423
|
return;
|
|
@@ -31953,14 +32481,14 @@ billingCommand.command("portal").description("Open the billing portal in your br
|
|
|
31953
32481
|
if (data.url) {
|
|
31954
32482
|
console.log("Opening billing portal...");
|
|
31955
32483
|
console.log(data.url);
|
|
31956
|
-
await
|
|
32484
|
+
await open6(data.url);
|
|
31957
32485
|
} else {
|
|
31958
32486
|
console.log("No portal URL returned. You may need to set up billing first.");
|
|
31959
32487
|
}
|
|
31960
32488
|
} catch (error) {
|
|
31961
32489
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31962
|
-
console.error(
|
|
31963
|
-
console.error(
|
|
32490
|
+
console.error(chalk25.red("Failed to open billing portal"));
|
|
32491
|
+
console.error(chalk25.red(message));
|
|
31964
32492
|
process.exit(1);
|
|
31965
32493
|
}
|
|
31966
32494
|
return;
|
|
@@ -31975,7 +32503,7 @@ billingCommand.command("portal").description("Open the billing portal in your br
|
|
|
31975
32503
|
try {
|
|
31976
32504
|
const data = await client.post("/billing/portal");
|
|
31977
32505
|
if (data.url) {
|
|
31978
|
-
await
|
|
32506
|
+
await open6(data.url);
|
|
31979
32507
|
setMsg("Billing portal opened in browser");
|
|
31980
32508
|
setSuccess(true);
|
|
31981
32509
|
} else {
|
|
@@ -32009,11 +32537,11 @@ billingCommand.command("refresh").description("Refresh plan data from billing pr
|
|
|
32009
32537
|
if (!isTTY(options)) {
|
|
32010
32538
|
try {
|
|
32011
32539
|
await client.post("/billing/refresh");
|
|
32012
|
-
console.log(
|
|
32540
|
+
console.log(chalk25.green("Plan data refreshed"));
|
|
32013
32541
|
} catch (error) {
|
|
32014
32542
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32015
|
-
console.error(
|
|
32016
|
-
console.error(
|
|
32543
|
+
console.error(chalk25.red("Failed to refresh plan data"));
|
|
32544
|
+
console.error(chalk25.red(message));
|
|
32017
32545
|
process.exit(1);
|
|
32018
32546
|
}
|
|
32019
32547
|
return;
|
|
@@ -32049,13 +32577,13 @@ billingCommand.command("refresh").description("Refresh plan data from billing pr
|
|
|
32049
32577
|
});
|
|
32050
32578
|
|
|
32051
32579
|
// src/commands/flow-versions.ts
|
|
32052
|
-
import { Command as
|
|
32053
|
-
import
|
|
32580
|
+
import { Command as Command20 } from "commander";
|
|
32581
|
+
import chalk26 from "chalk";
|
|
32054
32582
|
import React18 from "react";
|
|
32055
32583
|
import { render as render18 } from "ink";
|
|
32056
32584
|
import { useState as useState32, useEffect as useEffect29 } from "react";
|
|
32057
32585
|
import { Text as Text34 } from "ink";
|
|
32058
|
-
var flowVersionsCommand = new
|
|
32586
|
+
var flowVersionsCommand = new Command20("flow-versions").description(
|
|
32059
32587
|
"Manage flow versions"
|
|
32060
32588
|
);
|
|
32061
32589
|
flowVersionsCommand.command("list <flowId>").description("List all versions for a flow").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (flowId, options) => {
|
|
@@ -32070,21 +32598,21 @@ flowVersionsCommand.command("list <flowId>").description("List all versions for
|
|
|
32070
32598
|
} else {
|
|
32071
32599
|
const versions = data.data ?? [];
|
|
32072
32600
|
if (versions.length === 0) {
|
|
32073
|
-
console.log(
|
|
32601
|
+
console.log(chalk26.gray("No versions found"));
|
|
32074
32602
|
return;
|
|
32075
32603
|
}
|
|
32076
|
-
console.log(
|
|
32604
|
+
console.log(chalk26.cyan(`Versions for flow ${flowId}:`));
|
|
32077
32605
|
for (const v of versions) {
|
|
32078
|
-
const publishedTag = v.published ?
|
|
32606
|
+
const publishedTag = v.published ? chalk26.green(" [published]") : "";
|
|
32079
32607
|
const versionNum = v.version !== void 0 ? `v${v.version}` : v.id;
|
|
32080
|
-
const date = v.createdAt ?
|
|
32081
|
-
console.log(` ${
|
|
32608
|
+
const date = v.createdAt ? chalk26.gray(` ${v.createdAt}`) : "";
|
|
32609
|
+
console.log(` ${chalk26.green(v.id)} ${versionNum}${publishedTag}${date}`);
|
|
32082
32610
|
}
|
|
32083
32611
|
}
|
|
32084
32612
|
} catch (error) {
|
|
32085
32613
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32086
|
-
console.error(
|
|
32087
|
-
console.error(
|
|
32614
|
+
console.error(chalk26.red("Failed to fetch versions"));
|
|
32615
|
+
console.error(chalk26.red(message));
|
|
32088
32616
|
process.exit(1);
|
|
32089
32617
|
}
|
|
32090
32618
|
return;
|
|
@@ -32144,8 +32672,8 @@ flowVersionsCommand.command("get <flowId> <versionId>").description("Get a speci
|
|
|
32144
32672
|
}
|
|
32145
32673
|
} catch (error) {
|
|
32146
32674
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32147
|
-
console.error(
|
|
32148
|
-
console.error(
|
|
32675
|
+
console.error(chalk26.red("Failed to fetch version"));
|
|
32676
|
+
console.error(chalk26.red(message));
|
|
32149
32677
|
process.exit(1);
|
|
32150
32678
|
}
|
|
32151
32679
|
return;
|
|
@@ -32210,8 +32738,8 @@ flowVersionsCommand.command("published <flowId>").description("Get the published
|
|
|
32210
32738
|
}
|
|
32211
32739
|
} catch (error) {
|
|
32212
32740
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32213
|
-
console.error(
|
|
32214
|
-
console.error(
|
|
32741
|
+
console.error(chalk26.red("Failed to fetch published version"));
|
|
32742
|
+
console.error(chalk26.red(message));
|
|
32215
32743
|
process.exit(1);
|
|
32216
32744
|
}
|
|
32217
32745
|
return;
|
|
@@ -32264,11 +32792,11 @@ flowVersionsCommand.command("publish <flowId>").description("Publish a version")
|
|
|
32264
32792
|
await client.post(`/flow-versions/${flowId}/publish`, {
|
|
32265
32793
|
versionId: options.version
|
|
32266
32794
|
});
|
|
32267
|
-
console.log(
|
|
32795
|
+
console.log(chalk26.green("Version published"));
|
|
32268
32796
|
} catch (error) {
|
|
32269
32797
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32270
|
-
console.error(
|
|
32271
|
-
console.error(
|
|
32798
|
+
console.error(chalk26.red("Failed to publish version"));
|
|
32799
|
+
console.error(chalk26.red(message));
|
|
32272
32800
|
process.exit(1);
|
|
32273
32801
|
}
|
|
32274
32802
|
return;
|
|
@@ -32309,7 +32837,7 @@ flowVersionsCommand.command("publish <flowId>").description("Publish a version")
|
|
|
32309
32837
|
init_credential_store();
|
|
32310
32838
|
|
|
32311
32839
|
// src/lib/update-check.ts
|
|
32312
|
-
import
|
|
32840
|
+
import chalk27 from "chalk";
|
|
32313
32841
|
import Conf3 from "conf";
|
|
32314
32842
|
var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
|
|
32315
32843
|
var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -32403,7 +32931,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
|
|
|
32403
32931
|
console.error(message);
|
|
32404
32932
|
});
|
|
32405
32933
|
notify(
|
|
32406
|
-
`${
|
|
32934
|
+
`${chalk27.yellow("Update available:")} ${chalk27.red(currentVersion)} ${chalk27.gray("->")} ${chalk27.green(latestVersion)} ${chalk27.gray(`(${getUpgradeCommand()})`)}`
|
|
32407
32935
|
);
|
|
32408
32936
|
store.set("lastNotifiedAt", now.toISOString());
|
|
32409
32937
|
store.set("lastNotifiedVersion", latestVersion);
|
|
@@ -32445,7 +32973,7 @@ function maybeNotifyAboutCliUpdate(args, options = {}) {
|
|
|
32445
32973
|
// src/index.ts
|
|
32446
32974
|
loadEnv();
|
|
32447
32975
|
setCliTitle();
|
|
32448
|
-
var program = new
|
|
32976
|
+
var program = new Command21();
|
|
32449
32977
|
program.name("runtype").description("CLI for Runtype AI Platform").version(getCliVersion()).option("-v, --verbose", "Enable verbose output").option("--api-url <url>", "Override API URL").option("--json", "Output in JSON format");
|
|
32450
32978
|
program.addCommand(initCommand);
|
|
32451
32979
|
program.addCommand(loginCommand);
|
|
@@ -32463,6 +32991,7 @@ program.addCommand(schedulesCommand);
|
|
|
32463
32991
|
program.addCommand(evalCommand);
|
|
32464
32992
|
program.addCommand(apiKeysCommand);
|
|
32465
32993
|
program.addCommand(clientTokensCommand);
|
|
32994
|
+
program.addCommand(personaCommand);
|
|
32466
32995
|
program.addCommand(analyticsCommand);
|
|
32467
32996
|
program.addCommand(billingCommand);
|
|
32468
32997
|
program.addCommand(flowVersionsCommand);
|
|
@@ -32480,15 +33009,15 @@ try {
|
|
|
32480
33009
|
} catch (error) {
|
|
32481
33010
|
const commanderError = error;
|
|
32482
33011
|
if (commanderError.code === "commander.missingArgument") {
|
|
32483
|
-
console.error(
|
|
33012
|
+
console.error(chalk28.red(`Error: ${commanderError.message}`));
|
|
32484
33013
|
process.exit(1);
|
|
32485
33014
|
} else if (commanderError.code === "commander.unknownOption") {
|
|
32486
|
-
console.error(
|
|
33015
|
+
console.error(chalk28.red(`Error: ${commanderError.message}`));
|
|
32487
33016
|
process.exit(1);
|
|
32488
33017
|
} else if (commanderError.code === "commander.help" || commanderError.code === "commander.version") {
|
|
32489
33018
|
process.exit(0);
|
|
32490
33019
|
} else {
|
|
32491
|
-
console.error(
|
|
33020
|
+
console.error(chalk28.red("An unexpected error occurred:"));
|
|
32492
33021
|
console.error(error);
|
|
32493
33022
|
process.exit(1);
|
|
32494
33023
|
}
|
|
@@ -32497,12 +33026,12 @@ async function handleNoCommand() {
|
|
|
32497
33026
|
const store = new CredentialStore();
|
|
32498
33027
|
const hasCredentials = await store.hasCredentials();
|
|
32499
33028
|
if (!hasCredentials) {
|
|
32500
|
-
console.log(
|
|
33029
|
+
console.log(chalk28.cyan("\nWelcome to Runtype CLI!\n"));
|
|
32501
33030
|
console.log("It looks like this is your first time. Run the setup wizard:");
|
|
32502
|
-
console.log(` ${
|
|
33031
|
+
console.log(` ${chalk28.green("runtype init")}
|
|
32503
33032
|
`);
|
|
32504
33033
|
console.log("Or see all available commands:");
|
|
32505
|
-
console.log(` ${
|
|
33034
|
+
console.log(` ${chalk28.green("runtype --help")}
|
|
32506
33035
|
`);
|
|
32507
33036
|
} else {
|
|
32508
33037
|
try {
|