@runtypelabs/cli 2.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/index.js +743 -57
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -11636,6 +11636,7 @@ var require_generated_model_routing = __commonJS({
|
|
|
11636
11636
|
"gemini-3.1-flash-lite-preview": ["vercel"],
|
|
11637
11637
|
"gemini-3.1-pro-preview": ["vercel"],
|
|
11638
11638
|
"gemini-embedding-001": ["vercel"],
|
|
11639
|
+
"gemini-embedding-2": ["vercel"],
|
|
11639
11640
|
"gemini-flash-1.5-8b": ["google"],
|
|
11640
11641
|
"gemini-pro": ["google"],
|
|
11641
11642
|
"gemma-2-9b": ["vercel"],
|
|
@@ -11785,8 +11786,11 @@ var require_generated_model_routing = __commonJS({
|
|
|
11785
11786
|
"grok-4-fast-reasoning": ["vercel"],
|
|
11786
11787
|
"grok-4.1-fast-non-reasoning": ["vercel"],
|
|
11787
11788
|
"grok-4.1-fast-reasoning": ["vercel"],
|
|
11789
|
+
"grok-4.20-multi-agent": ["vercel"],
|
|
11788
11790
|
"grok-4.20-multi-agent-beta": ["vercel"],
|
|
11791
|
+
"grok-4.20-non-reasoning": ["vercel"],
|
|
11789
11792
|
"grok-4.20-non-reasoning-beta": ["vercel"],
|
|
11793
|
+
"grok-4.20-reasoning": ["vercel"],
|
|
11790
11794
|
"grok-4.20-reasoning-beta": ["vercel"],
|
|
11791
11795
|
"grok-beta": ["xai"],
|
|
11792
11796
|
"grok-code-fast-1": ["vercel", "xai"],
|
|
@@ -11843,6 +11847,7 @@ var require_generated_model_routing = __commonJS({
|
|
|
11843
11847
|
"Meta-Llama-3.3-70B-Instruct-Turbo": ["togetherai"],
|
|
11844
11848
|
"meta.llama3-8b-instruct-v1%3A0": ["bedrock"],
|
|
11845
11849
|
"mimo-v2-flash": ["vercel"],
|
|
11850
|
+
"mimo-v2-pro": ["vercel"],
|
|
11846
11851
|
"minimax-m2": ["vercel"],
|
|
11847
11852
|
"minimax-m2.1": ["vercel"],
|
|
11848
11853
|
"minimax-m2.1-lightning": ["vercel"],
|
|
@@ -12091,6 +12096,7 @@ var require_generated_model_routing = __commonJS({
|
|
|
12091
12096
|
"gemini-3-flash": ["google", "vercel"],
|
|
12092
12097
|
"gemini-3-pro-image": ["vercel"],
|
|
12093
12098
|
"gemini-embedding-001": ["vercel"],
|
|
12099
|
+
"gemini-embedding-2": ["vercel"],
|
|
12094
12100
|
"gemini-flash-1-5-8b": ["google"],
|
|
12095
12101
|
"gemini-pro": ["google"],
|
|
12096
12102
|
"gemma-2-9b": ["vercel"],
|
|
@@ -12231,8 +12237,11 @@ var require_generated_model_routing = __commonJS({
|
|
|
12231
12237
|
"grok-4": ["vercel", "xai"],
|
|
12232
12238
|
"grok-4-1-fast-non-reasoning": ["vercel"],
|
|
12233
12239
|
"grok-4-1-fast-reasoning": ["vercel"],
|
|
12240
|
+
"grok-4-20-multi-agent": ["vercel"],
|
|
12234
12241
|
"grok-4-20-multi-agent-beta": ["vercel"],
|
|
12242
|
+
"grok-4-20-non-reasoning": ["vercel"],
|
|
12235
12243
|
"grok-4-20-non-reasoning-beta": ["vercel"],
|
|
12244
|
+
"grok-4-20-reasoning": ["vercel"],
|
|
12236
12245
|
"grok-4-20-reasoning-beta": ["vercel"],
|
|
12237
12246
|
"grok-4-fast": ["xai"],
|
|
12238
12247
|
"grok-4-fast-non-reasoning": ["vercel"],
|
|
@@ -12284,6 +12293,7 @@ var require_generated_model_routing = __commonJS({
|
|
|
12284
12293
|
"meta-llama-3-8b-instruct-turbo": ["togetherai"],
|
|
12285
12294
|
"meta.llama3-8b-instruct-v1%3a0": ["bedrock"],
|
|
12286
12295
|
"mimo-v2-flash": ["vercel"],
|
|
12296
|
+
"mimo-v2-pro": ["vercel"],
|
|
12287
12297
|
"minimax-m2": ["vercel"],
|
|
12288
12298
|
"minimax-m2-1": ["vercel"],
|
|
12289
12299
|
"minimax-m2-1-lightning": ["vercel"],
|
|
@@ -12817,6 +12827,9 @@ var require_generated_model_routing = __commonJS({
|
|
|
12817
12827
|
"gemini-embedding-001": {
|
|
12818
12828
|
"vercel": "google/gemini-embedding-001"
|
|
12819
12829
|
},
|
|
12830
|
+
"gemini-embedding-2": {
|
|
12831
|
+
"vercel": "google/gemini-embedding-2"
|
|
12832
|
+
},
|
|
12820
12833
|
"gemini-flash-1-5-8b": {
|
|
12821
12834
|
"google": "gemini-flash-1.5-8b"
|
|
12822
12835
|
},
|
|
@@ -13455,12 +13468,21 @@ var require_generated_model_routing = __commonJS({
|
|
|
13455
13468
|
"grok-4-1-fast-reasoning": {
|
|
13456
13469
|
"vercel": "xai/grok-4.1-fast-reasoning"
|
|
13457
13470
|
},
|
|
13471
|
+
"grok-4-20-multi-agent": {
|
|
13472
|
+
"vercel": "xai/grok-4.20-multi-agent"
|
|
13473
|
+
},
|
|
13458
13474
|
"grok-4-20-multi-agent-beta": {
|
|
13459
13475
|
"vercel": "xai/grok-4.20-multi-agent-beta"
|
|
13460
13476
|
},
|
|
13477
|
+
"grok-4-20-non-reasoning": {
|
|
13478
|
+
"vercel": "xai/grok-4.20-non-reasoning"
|
|
13479
|
+
},
|
|
13461
13480
|
"grok-4-20-non-reasoning-beta": {
|
|
13462
13481
|
"vercel": "xai/grok-4.20-non-reasoning-beta"
|
|
13463
13482
|
},
|
|
13483
|
+
"grok-4-20-reasoning": {
|
|
13484
|
+
"vercel": "xai/grok-4.20-reasoning"
|
|
13485
|
+
},
|
|
13464
13486
|
"grok-4-20-reasoning-beta": {
|
|
13465
13487
|
"vercel": "xai/grok-4.20-reasoning-beta"
|
|
13466
13488
|
},
|
|
@@ -13479,12 +13501,21 @@ var require_generated_model_routing = __commonJS({
|
|
|
13479
13501
|
"grok-4.1-fast-reasoning": {
|
|
13480
13502
|
"vercel": "xai/grok-4.1-fast-reasoning"
|
|
13481
13503
|
},
|
|
13504
|
+
"grok-4.20-multi-agent": {
|
|
13505
|
+
"vercel": "xai/grok-4.20-multi-agent"
|
|
13506
|
+
},
|
|
13482
13507
|
"grok-4.20-multi-agent-beta": {
|
|
13483
13508
|
"vercel": "xai/grok-4.20-multi-agent-beta"
|
|
13484
13509
|
},
|
|
13510
|
+
"grok-4.20-non-reasoning": {
|
|
13511
|
+
"vercel": "xai/grok-4.20-non-reasoning"
|
|
13512
|
+
},
|
|
13485
13513
|
"grok-4.20-non-reasoning-beta": {
|
|
13486
13514
|
"vercel": "xai/grok-4.20-non-reasoning-beta"
|
|
13487
13515
|
},
|
|
13516
|
+
"grok-4.20-reasoning": {
|
|
13517
|
+
"vercel": "xai/grok-4.20-reasoning"
|
|
13518
|
+
},
|
|
13488
13519
|
"grok-4.20-reasoning-beta": {
|
|
13489
13520
|
"vercel": "xai/grok-4.20-reasoning-beta"
|
|
13490
13521
|
},
|
|
@@ -13726,6 +13757,9 @@ var require_generated_model_routing = __commonJS({
|
|
|
13726
13757
|
"mimo-v2-flash": {
|
|
13727
13758
|
"vercel": "xiaomi/mimo-v2-flash"
|
|
13728
13759
|
},
|
|
13760
|
+
"mimo-v2-pro": {
|
|
13761
|
+
"vercel": "xiaomi/mimo-v2-pro"
|
|
13762
|
+
},
|
|
13729
13763
|
"minimax-m2": {
|
|
13730
13764
|
"vercel": "minimax/minimax-m2"
|
|
13731
13765
|
},
|
|
@@ -15342,8 +15376,8 @@ var require_provider_routing = __commonJS({
|
|
|
15342
15376
|
});
|
|
15343
15377
|
|
|
15344
15378
|
// src/index.ts
|
|
15345
|
-
import { Command as
|
|
15346
|
-
import
|
|
15379
|
+
import { Command as Command21 } from "commander";
|
|
15380
|
+
import chalk28 from "chalk";
|
|
15347
15381
|
import { config as loadEnv } from "dotenv";
|
|
15348
15382
|
|
|
15349
15383
|
// src/commands/auth.ts
|
|
@@ -21552,12 +21586,21 @@ function isRecord(value) {
|
|
|
21552
21586
|
function parseSandboxProvider(value) {
|
|
21553
21587
|
if (!value) return void 0;
|
|
21554
21588
|
const normalized = value.trim().toLowerCase();
|
|
21555
|
-
if (normalized === "quickjs" || normalized === "daytona" || normalized === "cloudflare-worker")
|
|
21589
|
+
if (normalized === "quickjs" || normalized === "daytona" || normalized === "cloudflare-worker" || normalized === "cloudflare-shell")
|
|
21556
21590
|
return normalized;
|
|
21557
21591
|
return void 0;
|
|
21558
21592
|
}
|
|
21559
21593
|
function parseSandboxLanguage(provider, value) {
|
|
21560
21594
|
if (provider === "quickjs" || provider === "cloudflare-worker") return "javascript";
|
|
21595
|
+
if (provider === "cloudflare-shell") {
|
|
21596
|
+
if (typeof value === "string") {
|
|
21597
|
+
const normalized = value.trim().toLowerCase();
|
|
21598
|
+
if (normalized === "javascript" || normalized === "typescript") {
|
|
21599
|
+
return normalized;
|
|
21600
|
+
}
|
|
21601
|
+
}
|
|
21602
|
+
return "javascript";
|
|
21603
|
+
}
|
|
21561
21604
|
if (typeof value === "string") {
|
|
21562
21605
|
const normalized = value.trim().toLowerCase();
|
|
21563
21606
|
if (normalized === "javascript" || normalized === "typescript" || normalized === "python") {
|
|
@@ -21637,6 +21680,44 @@ function createSandboxInstructions(provider) {
|
|
|
21637
21680
|
"return { sum, count: nums.length }"
|
|
21638
21681
|
].join("\n");
|
|
21639
21682
|
}
|
|
21683
|
+
if (provider === "cloudflare-shell") {
|
|
21684
|
+
return [
|
|
21685
|
+
"--- Sandbox Tooling (Cloudflare Shell) ---",
|
|
21686
|
+
"You can execute JavaScript/TypeScript code with the local tool `run_sandbox_code`.",
|
|
21687
|
+
"Call shape:",
|
|
21688
|
+
'{ "code": "...", "parameters": { ... }, "language": "javascript|typescript", "timeoutMs": 30000 }',
|
|
21689
|
+
"Cloudflare Shell rules:",
|
|
21690
|
+
"1. Choose one language: javascript or typescript.",
|
|
21691
|
+
"2. TypeScript is fully supported with runtime compilation and npm dependency resolution.",
|
|
21692
|
+
"3. Inputs are passed via the `parameters` object (for example: `const x = parameters.x`).",
|
|
21693
|
+
"4. async/await and Promises are fully supported.",
|
|
21694
|
+
"5. The snippet is wrapped in an async function. Use top-level `return ...` to produce the result.",
|
|
21695
|
+
"6. Return JSON-serializable values (object, array, string, number, boolean, null).",
|
|
21696
|
+
"7. Helper functions are available under `helpers.*` namespace (e.g., `helpers.extractEmails(text)`).",
|
|
21697
|
+
"8. Persistent filesystem: `state.writeFile()`, `state.readFile()`, `state.glob()` are available for working with files.",
|
|
21698
|
+
"9. Files persist across multiple `run_sandbox_code` calls within the same sandbox.",
|
|
21699
|
+
"10. No Python support \u2014 use Daytona for Python workloads.",
|
|
21700
|
+
"11. No network access (fetch calls are blocked by default).",
|
|
21701
|
+
"Example:",
|
|
21702
|
+
"const nums = parameters.nums || []",
|
|
21703
|
+
"const sum = nums.reduce((acc: number, n: number) => acc + n, 0)",
|
|
21704
|
+
"return { sum, count: nums.length }",
|
|
21705
|
+
"",
|
|
21706
|
+
"--- Deploy with Preview (Cloudflare Shell) ---",
|
|
21707
|
+
"You also have `deploy_sandbox` to deploy a persistent web server and get a live preview URL.",
|
|
21708
|
+
"Call shape:",
|
|
21709
|
+
'{ "code": "...", "files": { "public/index.html": "..." }, "packageJson": "{\\"dependencies\\": {\\"hono\\": \\"^4.0.0\\"}}", "language": "typescript", "port": 3000 }',
|
|
21710
|
+
"Deploy rules:",
|
|
21711
|
+
"1. Use this when you need to run a web server (Hono, etc.) that the user can visit in their browser.",
|
|
21712
|
+
"2. The `code` is the main entry point file. The `packageJson` string provides npm dependencies.",
|
|
21713
|
+
"3. The `files` parameter writes additional files (path \u2192 content). Keys must be plain file paths.",
|
|
21714
|
+
"4. The code must export a fetch handler (Cloudflare Workers format): `export default { fetch(req) { ... } }`",
|
|
21715
|
+
"5. The sandbox is persistent \u2014 each sandbox has its own Durable Object with isolated state.",
|
|
21716
|
+
"6. The returned `previewUrl` is a REAL live URL (e.g., https://api.runtype.com/preview/{sandboxId}/) that the user can open in their browser.",
|
|
21717
|
+
"7. The sandbox persists for 2 hours after the last activity, then auto-cleans up.",
|
|
21718
|
+
"8. Prefer this over `run_sandbox_code` when building web apps, APIs, or anything with a UI."
|
|
21719
|
+
].join("\n");
|
|
21720
|
+
}
|
|
21640
21721
|
return [
|
|
21641
21722
|
"--- Sandbox Tooling (Daytona) ---",
|
|
21642
21723
|
"You can execute code snippets with the local tool `run_sandbox_code`.",
|
|
@@ -21666,7 +21747,7 @@ function createSandboxInstructions(provider) {
|
|
|
21666
21747
|
}
|
|
21667
21748
|
function createSandboxLocalTool(client, provider, debugMode) {
|
|
21668
21749
|
return {
|
|
21669
|
-
description: provider === "cloudflare-worker" ? "Execute JavaScript code in Cloudflare Worker sandbox. Async/await supported. Inputs are passed via parameters object." : provider === "quickjs" ? "Execute JavaScript code in QuickJS sandbox (legacy). Inputs are passed via parameters object." : "Execute JavaScript/TypeScript/Python code in Daytona sandbox. Inputs are injected as top-level variables.",
|
|
21750
|
+
description: provider === "cloudflare-worker" ? "Execute JavaScript code in Cloudflare Worker sandbox. Async/await supported. Inputs are passed via parameters object." : provider === "quickjs" ? "Execute JavaScript code in QuickJS sandbox (legacy). Inputs are passed via parameters object." : provider === "cloudflare-shell" ? "Execute JavaScript/TypeScript code in Cloudflare Shell sandbox. TypeScript and npm dependencies supported. Inputs are passed via parameters object." : "Execute JavaScript/TypeScript/Python code in Daytona sandbox. Inputs are injected as top-level variables.",
|
|
21670
21751
|
parametersSchema: {
|
|
21671
21752
|
type: "object",
|
|
21672
21753
|
properties: {
|
|
@@ -21677,8 +21758,8 @@ function createSandboxLocalTool(client, provider, debugMode) {
|
|
|
21677
21758
|
},
|
|
21678
21759
|
language: {
|
|
21679
21760
|
type: "string",
|
|
21680
|
-
enum: provider === "quickjs" || provider === "cloudflare-worker" ? ["javascript"] : ["javascript", "typescript", "python"],
|
|
21681
|
-
description: provider === "quickjs" ? "QuickJS only accepts javascript" : provider === "cloudflare-worker" ? "Cloudflare Worker only accepts javascript" : "Daytona code language"
|
|
21761
|
+
enum: provider === "quickjs" || provider === "cloudflare-worker" ? ["javascript"] : provider === "cloudflare-shell" ? ["javascript", "typescript"] : ["javascript", "typescript", "python"],
|
|
21762
|
+
description: provider === "quickjs" ? "QuickJS only accepts javascript" : provider === "cloudflare-worker" ? "Cloudflare Worker only accepts javascript" : provider === "cloudflare-shell" ? "Cloudflare Shell accepts javascript or typescript" : "Daytona code language"
|
|
21682
21763
|
},
|
|
21683
21764
|
timeoutMs: { type: "number", description: "Execution timeout in ms (max 30000)" }
|
|
21684
21765
|
},
|
|
@@ -21709,7 +21790,7 @@ function createSandboxLocalTool(client, provider, debugMode) {
|
|
|
21709
21790
|
{
|
|
21710
21791
|
allowedToolTypes: ["custom"],
|
|
21711
21792
|
allowedSandboxProviders: [provider],
|
|
21712
|
-
allowedLanguages: provider === "quickjs" || provider === "cloudflare-worker" ? ["javascript"] : ["javascript", "typescript", "python"],
|
|
21793
|
+
allowedLanguages: provider === "quickjs" || provider === "cloudflare-worker" ? ["javascript"] : provider === "cloudflare-shell" ? ["javascript", "typescript"] : ["javascript", "typescript", "python"],
|
|
21713
21794
|
maxTimeoutMs: 3e4,
|
|
21714
21795
|
maxCodeLength: 12e3
|
|
21715
21796
|
}
|
|
@@ -21871,6 +21952,84 @@ function createDeploySandboxLocalTool(client, debugMode) {
|
|
|
21871
21952
|
}
|
|
21872
21953
|
};
|
|
21873
21954
|
}
|
|
21955
|
+
var activeCfShellWorkerId;
|
|
21956
|
+
function createDeployCfShellLocalTool(client, debugMode) {
|
|
21957
|
+
return {
|
|
21958
|
+
description: "Deploy code to a persistent Cloudflare Shell Dynamic Worker and get a live preview URL. Use this to run web servers, APIs, or UIs that the user can visit in their browser. Supports JavaScript and TypeScript with npm dependencies.",
|
|
21959
|
+
parametersSchema: {
|
|
21960
|
+
type: "object",
|
|
21961
|
+
properties: {
|
|
21962
|
+
code: { type: "string", description: "Code to deploy (main entry point file)" },
|
|
21963
|
+
packageJson: {
|
|
21964
|
+
type: "object",
|
|
21965
|
+
description: 'package.json content as a JSON object, e.g. { "dependencies": { "hono": "^4.0.0" } }'
|
|
21966
|
+
},
|
|
21967
|
+
language: {
|
|
21968
|
+
type: "string",
|
|
21969
|
+
enum: ["javascript", "typescript"],
|
|
21970
|
+
description: "Language of the code (default: typescript)"
|
|
21971
|
+
},
|
|
21972
|
+
port: {
|
|
21973
|
+
type: "number",
|
|
21974
|
+
description: "Port the server listens on (default: 3000)"
|
|
21975
|
+
},
|
|
21976
|
+
files: {
|
|
21977
|
+
type: "object",
|
|
21978
|
+
description: 'Additional files to write (path \u2192 content), e.g. { "public/index.html": "<html>..." }. Keys must be plain file paths. Use this for multi-file projects.',
|
|
21979
|
+
additionalProperties: { type: "string" }
|
|
21980
|
+
}
|
|
21981
|
+
},
|
|
21982
|
+
required: ["code"]
|
|
21983
|
+
},
|
|
21984
|
+
execute: async (args) => {
|
|
21985
|
+
const code = typeof args.code === "string" ? args.code : "";
|
|
21986
|
+
if (!code.trim()) {
|
|
21987
|
+
return { success: false, error: "code is required" };
|
|
21988
|
+
}
|
|
21989
|
+
const request = {
|
|
21990
|
+
code,
|
|
21991
|
+
...args.packageJson && typeof args.packageJson === "object" ? { packageJson: JSON.stringify(args.packageJson) } : typeof args.packageJson === "string" ? { packageJson: args.packageJson } : {},
|
|
21992
|
+
...typeof args.language === "string" ? { language: args.language } : {},
|
|
21993
|
+
...typeof args.port === "number" ? { port: args.port } : {},
|
|
21994
|
+
...args.files && typeof args.files === "object" && !Array.isArray(args.files) ? { files: args.files } : {},
|
|
21995
|
+
// Reuse existing worker if one was created
|
|
21996
|
+
...activeCfShellWorkerId ? { workerId: activeCfShellWorkerId } : {}
|
|
21997
|
+
};
|
|
21998
|
+
try {
|
|
21999
|
+
const result = await client.tools.deployCfShell(request);
|
|
22000
|
+
if (result.workerId) {
|
|
22001
|
+
activeCfShellWorkerId = result.workerId;
|
|
22002
|
+
}
|
|
22003
|
+
if (result.previewUrl) {
|
|
22004
|
+
activeDeploySandboxPreviewUrl = result.previewUrl;
|
|
22005
|
+
}
|
|
22006
|
+
if (debugMode) {
|
|
22007
|
+
console.log(
|
|
22008
|
+
chalk11.gray(
|
|
22009
|
+
` [deploy_cf_shell] ${result.status} \u2014 ${result.previewUrl || "no preview URL"}`
|
|
22010
|
+
)
|
|
22011
|
+
);
|
|
22012
|
+
}
|
|
22013
|
+
return {
|
|
22014
|
+
success: result.status === "running",
|
|
22015
|
+
workerId: result.workerId,
|
|
22016
|
+
previewUrl: result.previewUrl,
|
|
22017
|
+
output: result.output,
|
|
22018
|
+
...result.error ? { error: result.error } : {}
|
|
22019
|
+
};
|
|
22020
|
+
} catch (error) {
|
|
22021
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
22022
|
+
if (debugMode) {
|
|
22023
|
+
console.log(chalk11.gray(` [deploy_cf_shell] error: ${message}`));
|
|
22024
|
+
}
|
|
22025
|
+
return {
|
|
22026
|
+
success: false,
|
|
22027
|
+
error: message
|
|
22028
|
+
};
|
|
22029
|
+
}
|
|
22030
|
+
}
|
|
22031
|
+
};
|
|
22032
|
+
}
|
|
21874
22033
|
|
|
21875
22034
|
// src/marathon/event-log.ts
|
|
21876
22035
|
import * as fs3 from "fs";
|
|
@@ -27364,6 +27523,8 @@ function buildLocalTools(client, sandboxProvider, options, context) {
|
|
|
27364
27523
|
enabledTools.run_sandbox_code = createSandboxLocalTool(client, sandboxProvider, options.debug);
|
|
27365
27524
|
if (sandboxProvider === "daytona") {
|
|
27366
27525
|
enabledTools.deploy_sandbox = createDeploySandboxLocalTool(client, options.debug);
|
|
27526
|
+
} else if (sandboxProvider === "cloudflare-shell") {
|
|
27527
|
+
enabledTools.deploy_sandbox = createDeployCfShellLocalTool(client, options.debug);
|
|
27367
27528
|
}
|
|
27368
27529
|
}
|
|
27369
27530
|
return Object.keys(enabledTools).length > 0 ? enabledTools : void 0;
|
|
@@ -31521,14 +31682,538 @@ clientTokensCommand.command("regenerate <id>").description("Regenerate a client
|
|
|
31521
31682
|
await waitUntilExit();
|
|
31522
31683
|
});
|
|
31523
31684
|
|
|
31524
|
-
// src/commands/
|
|
31685
|
+
// src/commands/persona.ts
|
|
31525
31686
|
import { Command as Command17 } from "commander";
|
|
31526
31687
|
import chalk23 from "chalk";
|
|
31688
|
+
import readline3 from "readline";
|
|
31689
|
+
import open5 from "open";
|
|
31690
|
+
import { execFile as execFileCallback } from "child_process";
|
|
31691
|
+
import { promisify } from "util";
|
|
31692
|
+
|
|
31693
|
+
// src/lib/persona-init.ts
|
|
31694
|
+
init_credential_store();
|
|
31695
|
+
|
|
31696
|
+
// src/lib/persona-snippets.ts
|
|
31697
|
+
function mapCliFormatToPersona(cli) {
|
|
31698
|
+
switch (cli) {
|
|
31699
|
+
case "script-installer":
|
|
31700
|
+
return "script-installer";
|
|
31701
|
+
case "script-manual":
|
|
31702
|
+
return "script-advanced";
|
|
31703
|
+
case "esm":
|
|
31704
|
+
case "react":
|
|
31705
|
+
return "react-component";
|
|
31706
|
+
default: {
|
|
31707
|
+
const _exhaustive = cli;
|
|
31708
|
+
return _exhaustive;
|
|
31709
|
+
}
|
|
31710
|
+
}
|
|
31711
|
+
}
|
|
31712
|
+
function parsePersonaInitFormat(raw) {
|
|
31713
|
+
const normalized = raw.trim().toLowerCase();
|
|
31714
|
+
if (normalized === "script-installer" || normalized === "script-manual" || normalized === "esm" || normalized === "react") {
|
|
31715
|
+
return normalized;
|
|
31716
|
+
}
|
|
31717
|
+
throw new Error(
|
|
31718
|
+
`Invalid --format "${raw}". Use: script-installer | script-manual | esm | react`
|
|
31719
|
+
);
|
|
31720
|
+
}
|
|
31721
|
+
var PERSONA_CDN_BASE = "https://cdn.jsdelivr.net/npm/@runtypelabs/persona@latest/dist";
|
|
31722
|
+
function mountIdFromSelector(sel) {
|
|
31723
|
+
const s = sel.trim();
|
|
31724
|
+
if (s.startsWith("#")) return s.slice(1);
|
|
31725
|
+
return s || "chat";
|
|
31726
|
+
}
|
|
31727
|
+
function escapeHtmlAttr(s) {
|
|
31728
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<");
|
|
31729
|
+
}
|
|
31730
|
+
function buildScriptInstaller(input) {
|
|
31731
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31732
|
+
if (!targetSel) {
|
|
31733
|
+
return `<script
|
|
31734
|
+
src="${PERSONA_CDN_BASE}/install.global.js"
|
|
31735
|
+
data-runtype-token="${escapeHtmlAttr(input.clientToken)}"
|
|
31736
|
+
></script>`.trim();
|
|
31737
|
+
}
|
|
31738
|
+
const id = mountIdFromSelector(targetSel);
|
|
31739
|
+
const cfg = JSON.stringify({ target: targetSel, apiUrl: input.apiUrl });
|
|
31740
|
+
return `<div id="${escapeHtmlAttr(id)}"></div>
|
|
31741
|
+
<script
|
|
31742
|
+
src="${PERSONA_CDN_BASE}/install.global.js"
|
|
31743
|
+
data-runtype-token="${escapeHtmlAttr(input.clientToken)}"
|
|
31744
|
+
data-config='${cfg.replace(/'/g, "'")}'
|
|
31745
|
+
></script>`.trim();
|
|
31746
|
+
}
|
|
31747
|
+
function buildScriptAdvancedHtml(input) {
|
|
31748
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31749
|
+
const apiUrl = JSON.stringify(input.apiUrl);
|
|
31750
|
+
const token = JSON.stringify(input.clientToken);
|
|
31751
|
+
const targetJson = JSON.stringify(targetSel || "body");
|
|
31752
|
+
const divLine = targetSel ? `<div id="${escapeHtmlAttr(mountIdFromSelector(targetSel))}"></div>
|
|
31753
|
+
` : "";
|
|
31754
|
+
return `<link rel="stylesheet" href="${PERSONA_CDN_BASE}/widget.css" />
|
|
31755
|
+
${divLine}<script type="module">
|
|
31756
|
+
import { initAgentWidget, markdownPostprocessor } from '${PERSONA_CDN_BASE}/index.js';
|
|
31757
|
+
|
|
31758
|
+
initAgentWidget({
|
|
31759
|
+
target: ${targetJson},
|
|
31760
|
+
config: {
|
|
31761
|
+
apiUrl: ${apiUrl},
|
|
31762
|
+
clientToken: ${token},
|
|
31763
|
+
parserType: 'json',
|
|
31764
|
+
postprocessMessage: ({ text }) => markdownPostprocessor(text),
|
|
31765
|
+
launcher: {
|
|
31766
|
+
enabled: true,
|
|
31767
|
+
title: 'Chat',
|
|
31768
|
+
subtitle: 'How can I help you today?',
|
|
31769
|
+
position: 'bottom-right',
|
|
31770
|
+
},
|
|
31771
|
+
},
|
|
31772
|
+
});
|
|
31773
|
+
</script>`.trim();
|
|
31774
|
+
}
|
|
31775
|
+
function buildReactComponentSnippet(input) {
|
|
31776
|
+
const targetSel = input.targetSelector?.trim() || void 0;
|
|
31777
|
+
const apiUrl = JSON.stringify(input.apiUrl);
|
|
31778
|
+
const token = JSON.stringify(input.clientToken);
|
|
31779
|
+
const targetStr = JSON.stringify(targetSel || "body");
|
|
31780
|
+
return `import "@runtypelabs/persona/widget.css";
|
|
31781
|
+
import { DEFAULT_WIDGET_CONFIG, initAgentWidget, markdownPostprocessor } from "@runtypelabs/persona";
|
|
31782
|
+
|
|
31783
|
+
initAgentWidget({
|
|
31784
|
+
target: ${targetStr},
|
|
31785
|
+
config: {
|
|
31786
|
+
...DEFAULT_WIDGET_CONFIG,
|
|
31787
|
+
apiUrl: ${apiUrl},
|
|
31788
|
+
clientToken: ${token},
|
|
31789
|
+
parserType: "json",
|
|
31790
|
+
postprocessMessage: ({ text }) => markdownPostprocessor(text),
|
|
31791
|
+
},
|
|
31792
|
+
});`.trim();
|
|
31793
|
+
}
|
|
31794
|
+
function generatePersonaInitSnippet(input, personaFormat) {
|
|
31795
|
+
switch (personaFormat) {
|
|
31796
|
+
case "script-installer":
|
|
31797
|
+
return buildScriptInstaller(input);
|
|
31798
|
+
case "script-advanced":
|
|
31799
|
+
return buildScriptAdvancedHtml(input);
|
|
31800
|
+
case "react-component":
|
|
31801
|
+
return buildReactComponentSnippet(input);
|
|
31802
|
+
default: {
|
|
31803
|
+
const _exhaustive = personaFormat;
|
|
31804
|
+
return _exhaustive;
|
|
31805
|
+
}
|
|
31806
|
+
}
|
|
31807
|
+
}
|
|
31808
|
+
|
|
31809
|
+
// src/lib/persona-init.ts
|
|
31810
|
+
async function getPersonaInitApiKeyNonInteractive(apiUrl) {
|
|
31811
|
+
const envApiKey = getRuntimeApiKey();
|
|
31812
|
+
if (envApiKey) {
|
|
31813
|
+
try {
|
|
31814
|
+
const apiKeyManager = new ApiKeyManager();
|
|
31815
|
+
const isValid = await apiKeyManager.validateApiKey(envApiKey, apiUrl);
|
|
31816
|
+
if (isValid) {
|
|
31817
|
+
return envApiKey;
|
|
31818
|
+
}
|
|
31819
|
+
} catch {
|
|
31820
|
+
}
|
|
31821
|
+
}
|
|
31822
|
+
const store = new CredentialStore();
|
|
31823
|
+
return store.getApiKey();
|
|
31824
|
+
}
|
|
31825
|
+
async function runPersonaInit(options) {
|
|
31826
|
+
const client = new ApiClient(options.apiKey, options.apiUrl);
|
|
31827
|
+
const agent = await client.post("/agents", {
|
|
31828
|
+
name: options.agentName,
|
|
31829
|
+
description: options.agentDescription
|
|
31830
|
+
});
|
|
31831
|
+
const tokenBody = {
|
|
31832
|
+
name: options.tokenName,
|
|
31833
|
+
flowIds: [],
|
|
31834
|
+
agentIds: [agent.id],
|
|
31835
|
+
allowedOrigins: options.allowedOrigins,
|
|
31836
|
+
environment: options.environment,
|
|
31837
|
+
rateLimitPerMinute: 10,
|
|
31838
|
+
rateLimitPerHour: 100,
|
|
31839
|
+
maxMessagesPerSession: 100,
|
|
31840
|
+
sessionIdleTimeoutMinutes: 30
|
|
31841
|
+
};
|
|
31842
|
+
const tokenRes = await client.post("/client-tokens", tokenBody);
|
|
31843
|
+
const personaFormat = mapCliFormatToPersona(options.format);
|
|
31844
|
+
const code = generatePersonaInitSnippet(
|
|
31845
|
+
{
|
|
31846
|
+
clientToken: tokenRes.token,
|
|
31847
|
+
apiUrl: options.apiUrl,
|
|
31848
|
+
targetSelector: options.targetSelector
|
|
31849
|
+
},
|
|
31850
|
+
personaFormat
|
|
31851
|
+
);
|
|
31852
|
+
const dashboardBase = getDashboardUrl();
|
|
31853
|
+
const dashboardUrl = `${dashboardBase}/agents/${agent.id}`;
|
|
31854
|
+
return {
|
|
31855
|
+
status: "created",
|
|
31856
|
+
agent: { id: agent.id, name: agent.name },
|
|
31857
|
+
clientToken: {
|
|
31858
|
+
id: tokenRes.clientToken.id,
|
|
31859
|
+
name: tokenRes.clientToken.name,
|
|
31860
|
+
token: tokenRes.token,
|
|
31861
|
+
environment: options.environment
|
|
31862
|
+
},
|
|
31863
|
+
snippet: { format: options.format, code },
|
|
31864
|
+
dashboardUrl,
|
|
31865
|
+
warnings: tokenRes.warnings
|
|
31866
|
+
};
|
|
31867
|
+
}
|
|
31868
|
+
|
|
31869
|
+
// src/commands/persona.ts
|
|
31870
|
+
var execFile = promisify(execFileCallback);
|
|
31871
|
+
var FORMAT_CYCLE = [
|
|
31872
|
+
"script-installer",
|
|
31873
|
+
"react",
|
|
31874
|
+
"script-manual",
|
|
31875
|
+
"esm"
|
|
31876
|
+
];
|
|
31877
|
+
function defaultTokenName(agentName) {
|
|
31878
|
+
return `${agentName} Widget`;
|
|
31879
|
+
}
|
|
31880
|
+
async function promptLine(rl, question, defaultValue) {
|
|
31881
|
+
const hint = defaultValue ? chalk23.dim(` (${defaultValue})`) : "";
|
|
31882
|
+
const answer = await new Promise((resolve8) => {
|
|
31883
|
+
rl.question(`${question}${hint}: `, resolve8);
|
|
31884
|
+
});
|
|
31885
|
+
const trimmed = answer.trim();
|
|
31886
|
+
if (!trimmed && defaultValue !== void 0) {
|
|
31887
|
+
return defaultValue;
|
|
31888
|
+
}
|
|
31889
|
+
return trimmed;
|
|
31890
|
+
}
|
|
31891
|
+
async function promptConfirm2(rl, message, defaultYes = false) {
|
|
31892
|
+
const hint = defaultYes ? chalk23.dim(" (Y/n)") : chalk23.dim(" (y/N)");
|
|
31893
|
+
const answer = await new Promise((resolve8) => {
|
|
31894
|
+
rl.question(`${message}${hint}: `, resolve8);
|
|
31895
|
+
});
|
|
31896
|
+
const t = answer.trim().toLowerCase();
|
|
31897
|
+
if (t === "") return defaultYes;
|
|
31898
|
+
return t === "y" || t === "yes";
|
|
31899
|
+
}
|
|
31900
|
+
async function copyToClipboard2(text) {
|
|
31901
|
+
if (process.platform === "darwin") {
|
|
31902
|
+
await execFile("pbcopy", [], { input: text });
|
|
31903
|
+
return;
|
|
31904
|
+
}
|
|
31905
|
+
if (process.platform === "win32") {
|
|
31906
|
+
await execFile("clip", [], { shell: true, input: text });
|
|
31907
|
+
return;
|
|
31908
|
+
}
|
|
31909
|
+
try {
|
|
31910
|
+
await execFile("xclip", ["-selection", "clipboard"], { input: text });
|
|
31911
|
+
} catch {
|
|
31912
|
+
await execFile("wl-copy", [], { input: text });
|
|
31913
|
+
}
|
|
31914
|
+
}
|
|
31915
|
+
function isProbablyLocalDev(origins) {
|
|
31916
|
+
return origins.some(
|
|
31917
|
+
(o) => o === "http://localhost:*" || o.startsWith("http://localhost:") || o.startsWith("http://127.0.0.1:")
|
|
31918
|
+
);
|
|
31919
|
+
}
|
|
31920
|
+
function snippetWithFormat(format, token, apiUrl, targetSelector) {
|
|
31921
|
+
const personaFmt = mapCliFormatToPersona(format);
|
|
31922
|
+
const code = generatePersonaInitSnippet(
|
|
31923
|
+
{ clientToken: token, apiUrl, targetSelector },
|
|
31924
|
+
personaFmt
|
|
31925
|
+
);
|
|
31926
|
+
return { format, code };
|
|
31927
|
+
}
|
|
31928
|
+
async function runSuccessKeyLoop(initial, apiUrl, targetSelector) {
|
|
31929
|
+
if (!process.stdin.isTTY) {
|
|
31930
|
+
return;
|
|
31931
|
+
}
|
|
31932
|
+
let currentFormat = initial.snippet.format;
|
|
31933
|
+
let currentCode = initial.snippet.code;
|
|
31934
|
+
const token = initial.clientToken.token;
|
|
31935
|
+
console.log(chalk23.cyan("\nPersona setup complete\n"));
|
|
31936
|
+
console.log(`${chalk23.bold("Agent ID:")} ${initial.agent.id}`);
|
|
31937
|
+
console.log(`${chalk23.bold("Client Token ID:")} ${initial.clientToken.id}`);
|
|
31938
|
+
console.log(`${chalk23.bold("Client Token:")} ${chalk23.yellow(token)}`);
|
|
31939
|
+
console.log(`${chalk23.bold("Snippet format:")} ${currentFormat}`);
|
|
31940
|
+
console.log(chalk23.dim(`
|
|
31941
|
+
Dashboard: ${initial.dashboardUrl}`));
|
|
31942
|
+
if (initial.warnings?.length) {
|
|
31943
|
+
for (const w of initial.warnings) {
|
|
31944
|
+
console.log(chalk23.yellow(`\u26A0 ${w.message}`));
|
|
31945
|
+
}
|
|
31946
|
+
}
|
|
31947
|
+
console.log(chalk23.cyan("\nKeys:"));
|
|
31948
|
+
console.log(` ${chalk23.green("c")} Copy snippet to clipboard`);
|
|
31949
|
+
console.log(` ${chalk23.green("p")} Print snippet to the terminal`);
|
|
31950
|
+
console.log(` ${chalk23.green("f")} Switch snippet format`);
|
|
31951
|
+
console.log(` ${chalk23.green("o")} Open dashboard in browser`);
|
|
31952
|
+
console.log(` ${chalk23.green("q")} Quit`);
|
|
31953
|
+
readline3.emitKeypressEvents(process.stdin);
|
|
31954
|
+
if (process.stdin.isTTY) {
|
|
31955
|
+
process.stdin.setRawMode(true);
|
|
31956
|
+
}
|
|
31957
|
+
const cleanup = () => {
|
|
31958
|
+
process.stdin.setRawMode(false);
|
|
31959
|
+
process.stdin.removeAllListeners("keypress");
|
|
31960
|
+
};
|
|
31961
|
+
await new Promise((resolve8) => {
|
|
31962
|
+
const onKeypress = async (_str, key) => {
|
|
31963
|
+
if (!key) return;
|
|
31964
|
+
if (key.ctrl && key.name === "c") {
|
|
31965
|
+
cleanup();
|
|
31966
|
+
resolve8();
|
|
31967
|
+
process.exit(0);
|
|
31968
|
+
}
|
|
31969
|
+
const name = key.name;
|
|
31970
|
+
if (name === "q" || name === "escape") {
|
|
31971
|
+
cleanup();
|
|
31972
|
+
resolve8();
|
|
31973
|
+
return;
|
|
31974
|
+
}
|
|
31975
|
+
if (name === "c") {
|
|
31976
|
+
try {
|
|
31977
|
+
await copyToClipboard2(currentCode);
|
|
31978
|
+
console.log(chalk23.green("Snippet copied to clipboard."));
|
|
31979
|
+
} catch {
|
|
31980
|
+
console.log(chalk23.red("Could not copy (install xclip/wl-copy on Linux, or use p)."));
|
|
31981
|
+
}
|
|
31982
|
+
return;
|
|
31983
|
+
}
|
|
31984
|
+
if (name === "p") {
|
|
31985
|
+
console.log(chalk23.cyan("\n--- snippet ---\n"));
|
|
31986
|
+
console.log(currentCode);
|
|
31987
|
+
console.log(chalk23.cyan("\n--- end snippet ---\n"));
|
|
31988
|
+
return;
|
|
31989
|
+
}
|
|
31990
|
+
if (name === "f") {
|
|
31991
|
+
const idx = FORMAT_CYCLE.indexOf(currentFormat);
|
|
31992
|
+
const next = FORMAT_CYCLE[(idx + 1) % FORMAT_CYCLE.length] ?? "script-installer";
|
|
31993
|
+
const nextSnippet = snippetWithFormat(next, token, apiUrl, targetSelector);
|
|
31994
|
+
currentFormat = nextSnippet.format;
|
|
31995
|
+
currentCode = nextSnippet.code;
|
|
31996
|
+
console.log(chalk23.dim(`Format: ${currentFormat}`));
|
|
31997
|
+
return;
|
|
31998
|
+
}
|
|
31999
|
+
if (name === "o") {
|
|
32000
|
+
try {
|
|
32001
|
+
await open5(initial.dashboardUrl);
|
|
32002
|
+
} catch {
|
|
32003
|
+
console.log(chalk23.red("Could not open browser."));
|
|
32004
|
+
}
|
|
32005
|
+
}
|
|
32006
|
+
};
|
|
32007
|
+
process.stdin.on("keypress", onKeypress);
|
|
32008
|
+
});
|
|
32009
|
+
}
|
|
32010
|
+
var personaCommand = new Command17("persona").description(
|
|
32011
|
+
"Set up Persona: create an agent, client token, and embed snippet"
|
|
32012
|
+
);
|
|
32013
|
+
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(
|
|
32014
|
+
"--format <fmt>",
|
|
32015
|
+
"Snippet format: script-installer | script-manual | esm | react",
|
|
32016
|
+
"script-installer"
|
|
32017
|
+
).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(
|
|
32018
|
+
async (options, cmd) => {
|
|
32019
|
+
const globals = cmd.optsWithGlobals();
|
|
32020
|
+
const jsonMode = !!(options.json ?? globals.json);
|
|
32021
|
+
const tty = isTTY(options);
|
|
32022
|
+
let formatCli;
|
|
32023
|
+
try {
|
|
32024
|
+
formatCli = parsePersonaInitFormat(options.format);
|
|
32025
|
+
} catch (e) {
|
|
32026
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
32027
|
+
if (jsonMode) {
|
|
32028
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "INVALID_FORMAT" }, null, 2));
|
|
32029
|
+
} else {
|
|
32030
|
+
console.error(chalk23.red(msg));
|
|
32031
|
+
}
|
|
32032
|
+
process.exit(1);
|
|
32033
|
+
}
|
|
32034
|
+
const apiUrl = options.apiUrl || globals.apiUrl || getApiUrl();
|
|
32035
|
+
const targetSelector = options.targetSelector || void 0;
|
|
32036
|
+
let env;
|
|
32037
|
+
if (options.environment === "test" || options.environment === "live") {
|
|
32038
|
+
env = options.environment;
|
|
32039
|
+
} else {
|
|
32040
|
+
const msg = 'Error: --environment must be "test" or "live"';
|
|
32041
|
+
if (jsonMode) {
|
|
32042
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "INVALID_ENV" }, null, 2));
|
|
32043
|
+
} else {
|
|
32044
|
+
console.error(chalk23.red(msg));
|
|
32045
|
+
}
|
|
32046
|
+
process.exit(1);
|
|
32047
|
+
}
|
|
32048
|
+
const interactive = tty && !jsonMode;
|
|
32049
|
+
let agentName = options.agentName?.trim();
|
|
32050
|
+
let tokenName = options.tokenName?.trim();
|
|
32051
|
+
let allowedOrigins = options.origins;
|
|
32052
|
+
let chosenEnv = env;
|
|
32053
|
+
const rl = interactive && process.stdin.isTTY && process.stdout.isTTY ? readline3.createInterface({ input: process.stdin, output: process.stdout }) : null;
|
|
32054
|
+
if (!interactive) {
|
|
32055
|
+
if (!agentName) {
|
|
32056
|
+
const msg = "Non-interactive mode requires --agent-name";
|
|
32057
|
+
if (jsonMode) {
|
|
32058
|
+
console.log(JSON.stringify({ status: "error", error: msg, code: "MISSING_AGENT_NAME" }, null, 2));
|
|
32059
|
+
} else {
|
|
32060
|
+
console.error(chalk23.red(msg));
|
|
32061
|
+
}
|
|
32062
|
+
process.exit(1);
|
|
32063
|
+
}
|
|
32064
|
+
if (!tokenName) {
|
|
32065
|
+
tokenName = defaultTokenName(agentName);
|
|
32066
|
+
}
|
|
32067
|
+
if (!allowedOrigins || allowedOrigins.length === 0) {
|
|
32068
|
+
allowedOrigins = ["*"];
|
|
32069
|
+
}
|
|
32070
|
+
} else {
|
|
32071
|
+
if (!agentName) {
|
|
32072
|
+
agentName = await promptLine(rl, "Agent name");
|
|
32073
|
+
if (!agentName) {
|
|
32074
|
+
console.error(chalk23.red("Agent name is required"));
|
|
32075
|
+
process.exit(1);
|
|
32076
|
+
}
|
|
32077
|
+
}
|
|
32078
|
+
if (!tokenName) {
|
|
32079
|
+
const def = options.yes ? defaultTokenName(agentName) : defaultTokenName(agentName);
|
|
32080
|
+
tokenName = await promptLine(rl, "Client token name", def);
|
|
32081
|
+
if (!tokenName) {
|
|
32082
|
+
tokenName = def;
|
|
32083
|
+
}
|
|
32084
|
+
}
|
|
32085
|
+
if (!allowedOrigins?.length) {
|
|
32086
|
+
if (options.yes) {
|
|
32087
|
+
allowedOrigins = ["*"];
|
|
32088
|
+
} else {
|
|
32089
|
+
const originsInput = await promptLine(
|
|
32090
|
+
rl,
|
|
32091
|
+
"Allowed origins (space-separated URLs, or * for any)",
|
|
32092
|
+
"*"
|
|
32093
|
+
);
|
|
32094
|
+
allowedOrigins = originsInput === "*" ? ["*"] : originsInput.split(/\s+/).filter(Boolean);
|
|
32095
|
+
}
|
|
32096
|
+
}
|
|
32097
|
+
if (chosenEnv === "live") {
|
|
32098
|
+
const ok = await promptConfirm2(rl, chalk23.yellow("Create a LIVE token? This is shown only once."), false);
|
|
32099
|
+
if (!ok) {
|
|
32100
|
+
console.log(chalk23.gray("Aborted."));
|
|
32101
|
+
rl.close();
|
|
32102
|
+
process.exit(0);
|
|
32103
|
+
}
|
|
32104
|
+
} else if (!options.yes) {
|
|
32105
|
+
const envAns = await promptLine(rl, "Environment (test/live)", "test");
|
|
32106
|
+
if (envAns === "live") {
|
|
32107
|
+
const ok = await promptConfirm2(rl, chalk23.yellow("Create a LIVE token?"), false);
|
|
32108
|
+
if (!ok) {
|
|
32109
|
+
chosenEnv = "test";
|
|
32110
|
+
} else {
|
|
32111
|
+
chosenEnv = "live";
|
|
32112
|
+
}
|
|
32113
|
+
}
|
|
32114
|
+
}
|
|
32115
|
+
}
|
|
32116
|
+
if (rl) {
|
|
32117
|
+
rl.close();
|
|
32118
|
+
}
|
|
32119
|
+
if (allowedOrigins.includes("*") && chosenEnv === "live" && !isProbablyLocalDev(allowedOrigins)) {
|
|
32120
|
+
console.log(
|
|
32121
|
+
chalk23.yellow(
|
|
32122
|
+
'Warning: allowedOrigins is "*" for a live token. Prefer explicit https:// origins in production.'
|
|
32123
|
+
)
|
|
32124
|
+
);
|
|
32125
|
+
}
|
|
32126
|
+
let apiKey;
|
|
32127
|
+
if (jsonMode || !tty) {
|
|
32128
|
+
apiKey = await getPersonaInitApiKeyNonInteractive(apiUrl);
|
|
32129
|
+
if (!apiKey) {
|
|
32130
|
+
if (jsonMode) {
|
|
32131
|
+
console.log(
|
|
32132
|
+
JSON.stringify(
|
|
32133
|
+
{
|
|
32134
|
+
status: "unauthenticated",
|
|
32135
|
+
message: "Set RUNTYPE_API_KEY or run `runtype auth login` (uses saved credentials)"
|
|
32136
|
+
},
|
|
32137
|
+
null,
|
|
32138
|
+
2
|
|
32139
|
+
)
|
|
32140
|
+
);
|
|
32141
|
+
} else {
|
|
32142
|
+
console.error(
|
|
32143
|
+
chalk23.red(
|
|
32144
|
+
"Authentication required: set RUNTYPE_API_KEY or run `runtype auth login` for stored credentials"
|
|
32145
|
+
)
|
|
32146
|
+
);
|
|
32147
|
+
}
|
|
32148
|
+
process.exit(1);
|
|
32149
|
+
}
|
|
32150
|
+
} else {
|
|
32151
|
+
apiKey = await ensureAuth({ apiUrl });
|
|
32152
|
+
if (!apiKey) {
|
|
32153
|
+
process.exit(1);
|
|
32154
|
+
}
|
|
32155
|
+
}
|
|
32156
|
+
let success;
|
|
32157
|
+
try {
|
|
32158
|
+
success = await runPersonaInit({
|
|
32159
|
+
apiKey,
|
|
32160
|
+
apiUrl,
|
|
32161
|
+
agentName,
|
|
32162
|
+
agentDescription: options.agentDescription,
|
|
32163
|
+
tokenName,
|
|
32164
|
+
environment: chosenEnv,
|
|
32165
|
+
allowedOrigins,
|
|
32166
|
+
format: formatCli,
|
|
32167
|
+
targetSelector
|
|
32168
|
+
});
|
|
32169
|
+
} catch (err) {
|
|
32170
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32171
|
+
if (jsonMode) {
|
|
32172
|
+
console.log(JSON.stringify({ status: "error", error: message, code: "API_ERROR" }, null, 2));
|
|
32173
|
+
} else {
|
|
32174
|
+
console.error(chalk23.red("Persona init failed"));
|
|
32175
|
+
console.error(chalk23.red(message));
|
|
32176
|
+
}
|
|
32177
|
+
process.exit(1);
|
|
32178
|
+
}
|
|
32179
|
+
if (jsonMode) {
|
|
32180
|
+
printJson(success);
|
|
32181
|
+
return;
|
|
32182
|
+
}
|
|
32183
|
+
if (!tty || options.printSnippet) {
|
|
32184
|
+
console.log(chalk23.green("\nPersona setup complete\n"));
|
|
32185
|
+
console.log(`${chalk23.bold("Agent ID:")} ${success.agent.id}`);
|
|
32186
|
+
console.log(`${chalk23.bold("Client Token ID:")} ${success.clientToken.id}`);
|
|
32187
|
+
console.log(`${chalk23.bold("Client Token:")} ${chalk23.yellow(success.clientToken.token)}`);
|
|
32188
|
+
console.log(`${chalk23.bold("Format:")} ${success.snippet.format}`);
|
|
32189
|
+
console.log(chalk23.dim(`
|
|
32190
|
+
Dashboard: ${success.dashboardUrl}`));
|
|
32191
|
+
if (success.warnings?.length) {
|
|
32192
|
+
for (const w of success.warnings) {
|
|
32193
|
+
console.log(chalk23.yellow(`\u26A0 ${w.message}`));
|
|
32194
|
+
}
|
|
32195
|
+
}
|
|
32196
|
+
console.log(chalk23.cyan("\nRecommended next step: npm install @runtypelabs/persona"));
|
|
32197
|
+
if (options.printSnippet) {
|
|
32198
|
+
console.log(chalk23.cyan("\n--- snippet ---\n"));
|
|
32199
|
+
console.log(success.snippet.code);
|
|
32200
|
+
} else {
|
|
32201
|
+
console.log(chalk23.dim("\nUse --print-snippet to print the embed code, or run interactively for copy shortcuts."));
|
|
32202
|
+
}
|
|
32203
|
+
return;
|
|
32204
|
+
}
|
|
32205
|
+
await runSuccessKeyLoop(success, apiUrl, targetSelector);
|
|
32206
|
+
}
|
|
32207
|
+
);
|
|
32208
|
+
|
|
32209
|
+
// src/commands/analytics.ts
|
|
32210
|
+
import { Command as Command18 } from "commander";
|
|
32211
|
+
import chalk24 from "chalk";
|
|
31527
32212
|
import React16 from "react";
|
|
31528
32213
|
import { render as render16 } from "ink";
|
|
31529
32214
|
import { useState as useState30, useEffect as useEffect27 } from "react";
|
|
31530
32215
|
import { Text as Text33 } from "ink";
|
|
31531
|
-
var analyticsCommand = new
|
|
32216
|
+
var analyticsCommand = new Command18("analytics").description("View analytics and execution results");
|
|
31532
32217
|
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) => {
|
|
31533
32218
|
const apiKey = await ensureAuth();
|
|
31534
32219
|
if (!apiKey) return;
|
|
@@ -31548,8 +32233,8 @@ analyticsCommand.command("stats").description("Show account statistics").option(
|
|
|
31548
32233
|
}
|
|
31549
32234
|
} catch (error) {
|
|
31550
32235
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31551
|
-
console.error(
|
|
31552
|
-
console.error(
|
|
32236
|
+
console.error(chalk24.red("Failed to fetch stats"));
|
|
32237
|
+
console.error(chalk24.red(message));
|
|
31553
32238
|
process.exit(1);
|
|
31554
32239
|
}
|
|
31555
32240
|
return;
|
|
@@ -31613,27 +32298,27 @@ analyticsCommand.command("results").description("List execution results").option
|
|
|
31613
32298
|
} else {
|
|
31614
32299
|
const results = data.data ?? [];
|
|
31615
32300
|
if (results.length === 0) {
|
|
31616
|
-
console.log(
|
|
32301
|
+
console.log(chalk24.gray("No results found"));
|
|
31617
32302
|
return;
|
|
31618
32303
|
}
|
|
31619
|
-
console.log(
|
|
32304
|
+
console.log(chalk24.cyan("Execution Results:"));
|
|
31620
32305
|
for (const result of results) {
|
|
31621
32306
|
const statusColor = result.status === "completed" ? "green" : "red";
|
|
31622
|
-
const date = result.createdAt ?
|
|
32307
|
+
const date = result.createdAt ? chalk24.gray(` ${result.createdAt}`) : "";
|
|
31623
32308
|
console.log(
|
|
31624
|
-
` ${
|
|
32309
|
+
` ${chalk24.green(result.id)} ${chalk24[statusColor](`[${result.status}]`)} flow=${chalk24.gray(result.flowId)} record=${chalk24.gray(result.recordId)}${date}`
|
|
31625
32310
|
);
|
|
31626
32311
|
}
|
|
31627
32312
|
const total = getTotalCount(data.pagination);
|
|
31628
32313
|
if (total !== void 0) {
|
|
31629
|
-
console.log(
|
|
32314
|
+
console.log(chalk24.dim(`
|
|
31630
32315
|
Total: ${total} results`));
|
|
31631
32316
|
}
|
|
31632
32317
|
}
|
|
31633
32318
|
} catch (error) {
|
|
31634
32319
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31635
|
-
console.error(
|
|
31636
|
-
console.error(
|
|
32320
|
+
console.error(chalk24.red("Failed to fetch results"));
|
|
32321
|
+
console.error(chalk24.red(message));
|
|
31637
32322
|
process.exit(1);
|
|
31638
32323
|
}
|
|
31639
32324
|
return;
|
|
@@ -31684,13 +32369,13 @@ analyticsCommand.command("results").description("List execution results").option
|
|
|
31684
32369
|
);
|
|
31685
32370
|
|
|
31686
32371
|
// src/commands/billing.ts
|
|
31687
|
-
import { Command as
|
|
31688
|
-
import
|
|
32372
|
+
import { Command as Command19 } from "commander";
|
|
32373
|
+
import chalk25 from "chalk";
|
|
31689
32374
|
import React17 from "react";
|
|
31690
32375
|
import { render as render17 } from "ink";
|
|
31691
32376
|
import { useState as useState31, useEffect as useEffect28 } from "react";
|
|
31692
|
-
import
|
|
31693
|
-
var billingCommand = new
|
|
32377
|
+
import open6 from "open";
|
|
32378
|
+
var billingCommand = new Command19("billing").description("View billing and subscription info");
|
|
31694
32379
|
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) => {
|
|
31695
32380
|
const apiKey = await ensureAuth();
|
|
31696
32381
|
if (!apiKey) return;
|
|
@@ -31727,8 +32412,8 @@ billingCommand.command("status").description("Show current plan and usage").opti
|
|
|
31727
32412
|
}
|
|
31728
32413
|
} catch (error) {
|
|
31729
32414
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31730
|
-
console.error(
|
|
31731
|
-
console.error(
|
|
32415
|
+
console.error(chalk25.red("Failed to fetch billing status"));
|
|
32416
|
+
console.error(chalk25.red(message));
|
|
31732
32417
|
process.exit(1);
|
|
31733
32418
|
}
|
|
31734
32419
|
return;
|
|
@@ -31792,14 +32477,14 @@ billingCommand.command("portal").description("Open the billing portal in your br
|
|
|
31792
32477
|
if (data.url) {
|
|
31793
32478
|
console.log("Opening billing portal...");
|
|
31794
32479
|
console.log(data.url);
|
|
31795
|
-
await
|
|
32480
|
+
await open6(data.url);
|
|
31796
32481
|
} else {
|
|
31797
32482
|
console.log("No portal URL returned. You may need to set up billing first.");
|
|
31798
32483
|
}
|
|
31799
32484
|
} catch (error) {
|
|
31800
32485
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31801
|
-
console.error(
|
|
31802
|
-
console.error(
|
|
32486
|
+
console.error(chalk25.red("Failed to open billing portal"));
|
|
32487
|
+
console.error(chalk25.red(message));
|
|
31803
32488
|
process.exit(1);
|
|
31804
32489
|
}
|
|
31805
32490
|
return;
|
|
@@ -31814,7 +32499,7 @@ billingCommand.command("portal").description("Open the billing portal in your br
|
|
|
31814
32499
|
try {
|
|
31815
32500
|
const data = await client.post("/billing/portal");
|
|
31816
32501
|
if (data.url) {
|
|
31817
|
-
await
|
|
32502
|
+
await open6(data.url);
|
|
31818
32503
|
setMsg("Billing portal opened in browser");
|
|
31819
32504
|
setSuccess(true);
|
|
31820
32505
|
} else {
|
|
@@ -31848,11 +32533,11 @@ billingCommand.command("refresh").description("Refresh plan data from billing pr
|
|
|
31848
32533
|
if (!isTTY(options)) {
|
|
31849
32534
|
try {
|
|
31850
32535
|
await client.post("/billing/refresh");
|
|
31851
|
-
console.log(
|
|
32536
|
+
console.log(chalk25.green("Plan data refreshed"));
|
|
31852
32537
|
} catch (error) {
|
|
31853
32538
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31854
|
-
console.error(
|
|
31855
|
-
console.error(
|
|
32539
|
+
console.error(chalk25.red("Failed to refresh plan data"));
|
|
32540
|
+
console.error(chalk25.red(message));
|
|
31856
32541
|
process.exit(1);
|
|
31857
32542
|
}
|
|
31858
32543
|
return;
|
|
@@ -31888,13 +32573,13 @@ billingCommand.command("refresh").description("Refresh plan data from billing pr
|
|
|
31888
32573
|
});
|
|
31889
32574
|
|
|
31890
32575
|
// src/commands/flow-versions.ts
|
|
31891
|
-
import { Command as
|
|
31892
|
-
import
|
|
32576
|
+
import { Command as Command20 } from "commander";
|
|
32577
|
+
import chalk26 from "chalk";
|
|
31893
32578
|
import React18 from "react";
|
|
31894
32579
|
import { render as render18 } from "ink";
|
|
31895
32580
|
import { useState as useState32, useEffect as useEffect29 } from "react";
|
|
31896
32581
|
import { Text as Text34 } from "ink";
|
|
31897
|
-
var flowVersionsCommand = new
|
|
32582
|
+
var flowVersionsCommand = new Command20("flow-versions").description(
|
|
31898
32583
|
"Manage flow versions"
|
|
31899
32584
|
);
|
|
31900
32585
|
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) => {
|
|
@@ -31909,21 +32594,21 @@ flowVersionsCommand.command("list <flowId>").description("List all versions for
|
|
|
31909
32594
|
} else {
|
|
31910
32595
|
const versions = data.data ?? [];
|
|
31911
32596
|
if (versions.length === 0) {
|
|
31912
|
-
console.log(
|
|
32597
|
+
console.log(chalk26.gray("No versions found"));
|
|
31913
32598
|
return;
|
|
31914
32599
|
}
|
|
31915
|
-
console.log(
|
|
32600
|
+
console.log(chalk26.cyan(`Versions for flow ${flowId}:`));
|
|
31916
32601
|
for (const v of versions) {
|
|
31917
|
-
const publishedTag = v.published ?
|
|
32602
|
+
const publishedTag = v.published ? chalk26.green(" [published]") : "";
|
|
31918
32603
|
const versionNum = v.version !== void 0 ? `v${v.version}` : v.id;
|
|
31919
|
-
const date = v.createdAt ?
|
|
31920
|
-
console.log(` ${
|
|
32604
|
+
const date = v.createdAt ? chalk26.gray(` ${v.createdAt}`) : "";
|
|
32605
|
+
console.log(` ${chalk26.green(v.id)} ${versionNum}${publishedTag}${date}`);
|
|
31921
32606
|
}
|
|
31922
32607
|
}
|
|
31923
32608
|
} catch (error) {
|
|
31924
32609
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31925
|
-
console.error(
|
|
31926
|
-
console.error(
|
|
32610
|
+
console.error(chalk26.red("Failed to fetch versions"));
|
|
32611
|
+
console.error(chalk26.red(message));
|
|
31927
32612
|
process.exit(1);
|
|
31928
32613
|
}
|
|
31929
32614
|
return;
|
|
@@ -31983,8 +32668,8 @@ flowVersionsCommand.command("get <flowId> <versionId>").description("Get a speci
|
|
|
31983
32668
|
}
|
|
31984
32669
|
} catch (error) {
|
|
31985
32670
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
31986
|
-
console.error(
|
|
31987
|
-
console.error(
|
|
32671
|
+
console.error(chalk26.red("Failed to fetch version"));
|
|
32672
|
+
console.error(chalk26.red(message));
|
|
31988
32673
|
process.exit(1);
|
|
31989
32674
|
}
|
|
31990
32675
|
return;
|
|
@@ -32049,8 +32734,8 @@ flowVersionsCommand.command("published <flowId>").description("Get the published
|
|
|
32049
32734
|
}
|
|
32050
32735
|
} catch (error) {
|
|
32051
32736
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32052
|
-
console.error(
|
|
32053
|
-
console.error(
|
|
32737
|
+
console.error(chalk26.red("Failed to fetch published version"));
|
|
32738
|
+
console.error(chalk26.red(message));
|
|
32054
32739
|
process.exit(1);
|
|
32055
32740
|
}
|
|
32056
32741
|
return;
|
|
@@ -32103,11 +32788,11 @@ flowVersionsCommand.command("publish <flowId>").description("Publish a version")
|
|
|
32103
32788
|
await client.post(`/flow-versions/${flowId}/publish`, {
|
|
32104
32789
|
versionId: options.version
|
|
32105
32790
|
});
|
|
32106
|
-
console.log(
|
|
32791
|
+
console.log(chalk26.green("Version published"));
|
|
32107
32792
|
} catch (error) {
|
|
32108
32793
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
32109
|
-
console.error(
|
|
32110
|
-
console.error(
|
|
32794
|
+
console.error(chalk26.red("Failed to publish version"));
|
|
32795
|
+
console.error(chalk26.red(message));
|
|
32111
32796
|
process.exit(1);
|
|
32112
32797
|
}
|
|
32113
32798
|
return;
|
|
@@ -32148,7 +32833,7 @@ flowVersionsCommand.command("publish <flowId>").description("Publish a version")
|
|
|
32148
32833
|
init_credential_store();
|
|
32149
32834
|
|
|
32150
32835
|
// src/lib/update-check.ts
|
|
32151
|
-
import
|
|
32836
|
+
import chalk27 from "chalk";
|
|
32152
32837
|
import Conf3 from "conf";
|
|
32153
32838
|
var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
|
|
32154
32839
|
var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -32242,7 +32927,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
|
|
|
32242
32927
|
console.error(message);
|
|
32243
32928
|
});
|
|
32244
32929
|
notify(
|
|
32245
|
-
`${
|
|
32930
|
+
`${chalk27.yellow("Update available:")} ${chalk27.red(currentVersion)} ${chalk27.gray("->")} ${chalk27.green(latestVersion)} ${chalk27.gray(`(${getUpgradeCommand()})`)}`
|
|
32246
32931
|
);
|
|
32247
32932
|
store.set("lastNotifiedAt", now.toISOString());
|
|
32248
32933
|
store.set("lastNotifiedVersion", latestVersion);
|
|
@@ -32284,7 +32969,7 @@ function maybeNotifyAboutCliUpdate(args, options = {}) {
|
|
|
32284
32969
|
// src/index.ts
|
|
32285
32970
|
loadEnv();
|
|
32286
32971
|
setCliTitle();
|
|
32287
|
-
var program = new
|
|
32972
|
+
var program = new Command21();
|
|
32288
32973
|
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");
|
|
32289
32974
|
program.addCommand(initCommand);
|
|
32290
32975
|
program.addCommand(loginCommand);
|
|
@@ -32302,6 +32987,7 @@ program.addCommand(schedulesCommand);
|
|
|
32302
32987
|
program.addCommand(evalCommand);
|
|
32303
32988
|
program.addCommand(apiKeysCommand);
|
|
32304
32989
|
program.addCommand(clientTokensCommand);
|
|
32990
|
+
program.addCommand(personaCommand);
|
|
32305
32991
|
program.addCommand(analyticsCommand);
|
|
32306
32992
|
program.addCommand(billingCommand);
|
|
32307
32993
|
program.addCommand(flowVersionsCommand);
|
|
@@ -32319,15 +33005,15 @@ try {
|
|
|
32319
33005
|
} catch (error) {
|
|
32320
33006
|
const commanderError = error;
|
|
32321
33007
|
if (commanderError.code === "commander.missingArgument") {
|
|
32322
|
-
console.error(
|
|
33008
|
+
console.error(chalk28.red(`Error: ${commanderError.message}`));
|
|
32323
33009
|
process.exit(1);
|
|
32324
33010
|
} else if (commanderError.code === "commander.unknownOption") {
|
|
32325
|
-
console.error(
|
|
33011
|
+
console.error(chalk28.red(`Error: ${commanderError.message}`));
|
|
32326
33012
|
process.exit(1);
|
|
32327
33013
|
} else if (commanderError.code === "commander.help" || commanderError.code === "commander.version") {
|
|
32328
33014
|
process.exit(0);
|
|
32329
33015
|
} else {
|
|
32330
|
-
console.error(
|
|
33016
|
+
console.error(chalk28.red("An unexpected error occurred:"));
|
|
32331
33017
|
console.error(error);
|
|
32332
33018
|
process.exit(1);
|
|
32333
33019
|
}
|
|
@@ -32336,12 +33022,12 @@ async function handleNoCommand() {
|
|
|
32336
33022
|
const store = new CredentialStore();
|
|
32337
33023
|
const hasCredentials = await store.hasCredentials();
|
|
32338
33024
|
if (!hasCredentials) {
|
|
32339
|
-
console.log(
|
|
33025
|
+
console.log(chalk28.cyan("\nWelcome to Runtype CLI!\n"));
|
|
32340
33026
|
console.log("It looks like this is your first time. Run the setup wizard:");
|
|
32341
|
-
console.log(` ${
|
|
33027
|
+
console.log(` ${chalk28.green("runtype init")}
|
|
32342
33028
|
`);
|
|
32343
33029
|
console.log("Or see all available commands:");
|
|
32344
|
-
console.log(` ${
|
|
33030
|
+
console.log(` ${chalk28.green("runtype --help")}
|
|
32345
33031
|
`);
|
|
32346
33032
|
} else {
|
|
32347
33033
|
try {
|