@runtypelabs/cli 2.12.8 → 2.14.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/dist/index.js +1224 -174
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -131,15 +131,15 @@ var init_credential_store = __esm({
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
// src/index.ts
|
|
134
|
-
import { Command as
|
|
135
|
-
import
|
|
134
|
+
import { Command as Command25 } from "commander";
|
|
135
|
+
import chalk32 from "chalk";
|
|
136
136
|
|
|
137
137
|
// src/lib/load-env.ts
|
|
138
138
|
import { readFileSync } from "fs";
|
|
139
139
|
import { resolve } from "path";
|
|
140
|
-
function loadEnv(
|
|
140
|
+
function loadEnv(path15 = resolve(process.cwd(), ".env")) {
|
|
141
141
|
try {
|
|
142
|
-
const content = readFileSync(
|
|
142
|
+
const content = readFileSync(path15, "utf8").replace(/\r\n?/g, "\n");
|
|
143
143
|
for (const line of content.split("\n")) {
|
|
144
144
|
if (!line.trim() || line.trimStart().startsWith("#")) continue;
|
|
145
145
|
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/);
|
|
@@ -174,8 +174,8 @@ var CallbackServer = class {
|
|
|
174
174
|
expectedState;
|
|
175
175
|
constructor() {
|
|
176
176
|
this.app = express();
|
|
177
|
-
this.codePromise = new Promise((
|
|
178
|
-
this.codeResolve =
|
|
177
|
+
this.codePromise = new Promise((resolve10, reject) => {
|
|
178
|
+
this.codeResolve = resolve10;
|
|
179
179
|
this.codeReject = reject;
|
|
180
180
|
});
|
|
181
181
|
this.app.get("/callback", (req, res) => {
|
|
@@ -1304,10 +1304,10 @@ function mergeDefs(...defs) {
|
|
|
1304
1304
|
function cloneDef(schema) {
|
|
1305
1305
|
return mergeDefs(schema._zod.def);
|
|
1306
1306
|
}
|
|
1307
|
-
function getElementAtPath(obj,
|
|
1308
|
-
if (!
|
|
1307
|
+
function getElementAtPath(obj, path15) {
|
|
1308
|
+
if (!path15)
|
|
1309
1309
|
return obj;
|
|
1310
|
-
return
|
|
1310
|
+
return path15.reduce((acc, key) => acc?.[key], obj);
|
|
1311
1311
|
}
|
|
1312
1312
|
function promiseAllObject(promisesObj) {
|
|
1313
1313
|
const keys = Object.keys(promisesObj);
|
|
@@ -1716,11 +1716,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1716
1716
|
}
|
|
1717
1717
|
return false;
|
|
1718
1718
|
}
|
|
1719
|
-
function prefixIssues(
|
|
1719
|
+
function prefixIssues(path15, issues) {
|
|
1720
1720
|
return issues.map((iss) => {
|
|
1721
1721
|
var _a3;
|
|
1722
1722
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1723
|
-
iss.path.unshift(
|
|
1723
|
+
iss.path.unshift(path15);
|
|
1724
1724
|
return iss;
|
|
1725
1725
|
});
|
|
1726
1726
|
}
|
|
@@ -1867,16 +1867,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1867
1867
|
}
|
|
1868
1868
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1869
1869
|
const fieldErrors = { _errors: [] };
|
|
1870
|
-
const processError = (error52,
|
|
1870
|
+
const processError = (error52, path15 = []) => {
|
|
1871
1871
|
for (const issue2 of error52.issues) {
|
|
1872
1872
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1873
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1873
|
+
issue2.errors.map((issues) => processError({ issues }, [...path15, ...issue2.path]));
|
|
1874
1874
|
} else if (issue2.code === "invalid_key") {
|
|
1875
|
-
processError({ issues: issue2.issues }, [...
|
|
1875
|
+
processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
|
|
1876
1876
|
} else if (issue2.code === "invalid_element") {
|
|
1877
|
-
processError({ issues: issue2.issues }, [...
|
|
1877
|
+
processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
|
|
1878
1878
|
} else {
|
|
1879
|
-
const fullpath = [...
|
|
1879
|
+
const fullpath = [...path15, ...issue2.path];
|
|
1880
1880
|
if (fullpath.length === 0) {
|
|
1881
1881
|
fieldErrors._errors.push(mapper(issue2));
|
|
1882
1882
|
} else {
|
|
@@ -1903,17 +1903,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1903
1903
|
}
|
|
1904
1904
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1905
1905
|
const result = { errors: [] };
|
|
1906
|
-
const processError = (error52,
|
|
1906
|
+
const processError = (error52, path15 = []) => {
|
|
1907
1907
|
var _a3, _b;
|
|
1908
1908
|
for (const issue2 of error52.issues) {
|
|
1909
1909
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1910
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
1910
|
+
issue2.errors.map((issues) => processError({ issues }, [...path15, ...issue2.path]));
|
|
1911
1911
|
} else if (issue2.code === "invalid_key") {
|
|
1912
|
-
processError({ issues: issue2.issues }, [...
|
|
1912
|
+
processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
|
|
1913
1913
|
} else if (issue2.code === "invalid_element") {
|
|
1914
|
-
processError({ issues: issue2.issues }, [...
|
|
1914
|
+
processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
|
|
1915
1915
|
} else {
|
|
1916
|
-
const fullpath = [...
|
|
1916
|
+
const fullpath = [...path15, ...issue2.path];
|
|
1917
1917
|
if (fullpath.length === 0) {
|
|
1918
1918
|
result.errors.push(mapper(issue2));
|
|
1919
1919
|
continue;
|
|
@@ -1945,8 +1945,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1945
1945
|
}
|
|
1946
1946
|
function toDotPath(_path) {
|
|
1947
1947
|
const segs = [];
|
|
1948
|
-
const
|
|
1949
|
-
for (const seg of
|
|
1948
|
+
const path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1949
|
+
for (const seg of path15) {
|
|
1950
1950
|
if (typeof seg === "number")
|
|
1951
1951
|
segs.push(`[${seg}]`);
|
|
1952
1952
|
else if (typeof seg === "symbol")
|
|
@@ -14632,13 +14632,13 @@ function resolveRef(ref, ctx) {
|
|
|
14632
14632
|
if (!ref.startsWith("#")) {
|
|
14633
14633
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14634
14634
|
}
|
|
14635
|
-
const
|
|
14636
|
-
if (
|
|
14635
|
+
const path15 = ref.slice(1).split("/").filter(Boolean);
|
|
14636
|
+
if (path15.length === 0) {
|
|
14637
14637
|
return ctx.rootSchema;
|
|
14638
14638
|
}
|
|
14639
14639
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14640
|
-
if (
|
|
14641
|
-
const key =
|
|
14640
|
+
if (path15[0] === defsKey) {
|
|
14641
|
+
const key = path15[1];
|
|
14642
14642
|
if (!key || !ctx.defs[key]) {
|
|
14643
14643
|
throw new Error(`Reference not found: ${ref}`);
|
|
14644
14644
|
}
|
|
@@ -15423,6 +15423,97 @@ var CONTEXT_STEP_TYPES = [
|
|
|
15423
15423
|
"generate-pdf"
|
|
15424
15424
|
];
|
|
15425
15425
|
var FLOW_STEP_TYPES = ["prompt", ...CONTEXT_STEP_TYPES];
|
|
15426
|
+
var PROVIDER_SECRET_SPECS = [
|
|
15427
|
+
// ----- Explicit-prefix providers -----
|
|
15428
|
+
{
|
|
15429
|
+
providerId: "google-vertex-anthropic",
|
|
15430
|
+
// Must come before google-vertex (shares vertex prefix) and anthropic (matches */claude-*).
|
|
15431
|
+
matches: (m) => m.startsWith("vertex-anthropic/"),
|
|
15432
|
+
secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
|
|
15433
|
+
},
|
|
15434
|
+
{
|
|
15435
|
+
providerId: "google-vertex",
|
|
15436
|
+
// Must come before google (matches */gemini-*).
|
|
15437
|
+
matches: (m) => m.startsWith("vertex/"),
|
|
15438
|
+
secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
|
|
15439
|
+
},
|
|
15440
|
+
{
|
|
15441
|
+
providerId: "vercel-gateway",
|
|
15442
|
+
// Must come before openai — vercel/openai/gpt-4o would otherwise match openai.
|
|
15443
|
+
matches: (m) => m.startsWith("vercel/") || m.startsWith("vercel."),
|
|
15444
|
+
secretNames: ["VERCEL_AI_GATEWAY_API_KEY"]
|
|
15445
|
+
},
|
|
15446
|
+
{
|
|
15447
|
+
providerId: "cloudflare-gateway",
|
|
15448
|
+
// Must come before workers-ai — cloudflare/<provider>/<model> needs gateway routing.
|
|
15449
|
+
matches: (m) => m.startsWith("cloudflare/") || m.startsWith("cloudflare:"),
|
|
15450
|
+
secretNames: ["CF_ACCOUNT_ID", "CF_AI_GATEWAY_ID"]
|
|
15451
|
+
},
|
|
15452
|
+
{
|
|
15453
|
+
providerId: "bedrock",
|
|
15454
|
+
matches: (m) => m.startsWith("bedrock/"),
|
|
15455
|
+
secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"]
|
|
15456
|
+
},
|
|
15457
|
+
{
|
|
15458
|
+
providerId: "tinfoil",
|
|
15459
|
+
matches: (m) => m.startsWith("tinfoil/") || m.startsWith("tinfoil:"),
|
|
15460
|
+
secretNames: ["TINFOIL_API_KEY"]
|
|
15461
|
+
},
|
|
15462
|
+
{
|
|
15463
|
+
providerId: "generic-openai",
|
|
15464
|
+
// Must come before openai — shares the openai substring in its prefix.
|
|
15465
|
+
matches: (m) => m.startsWith("generic-openai/") || m.startsWith("generic-openai:"),
|
|
15466
|
+
secretNames: ["GENERIC_OPENAI_API_KEY", "GENERIC_OPENAI_BASE_URL"]
|
|
15467
|
+
},
|
|
15468
|
+
{
|
|
15469
|
+
providerId: "workers-ai",
|
|
15470
|
+
// Uses a CF platform binding, not a secret — secretNames is intentionally empty.
|
|
15471
|
+
matches: (m) => m.startsWith("@cf/") || m.startsWith("workers-ai/"),
|
|
15472
|
+
secretNames: []
|
|
15473
|
+
},
|
|
15474
|
+
{
|
|
15475
|
+
providerId: "togetherai",
|
|
15476
|
+
matches: (m) => m.startsWith("together/") || m.startsWith("togetherai/"),
|
|
15477
|
+
secretNames: ["TOGETHER_API_KEY"]
|
|
15478
|
+
},
|
|
15479
|
+
// ----- Base providers (broader patterns — must come last) -----
|
|
15480
|
+
{
|
|
15481
|
+
providerId: "anthropic",
|
|
15482
|
+
matches: (m) => m.startsWith("anthropic/") || m.startsWith("claude-") || m.includes("/claude-"),
|
|
15483
|
+
secretNames: ["ANTHROPIC_API_KEY"]
|
|
15484
|
+
},
|
|
15485
|
+
{
|
|
15486
|
+
providerId: "openai",
|
|
15487
|
+
matches: (m) => m.startsWith("openai/") || m.startsWith("gpt-") || m.startsWith("o1-") || m.startsWith("o3-") || m.startsWith("o4-") || m.includes("/gpt-"),
|
|
15488
|
+
secretNames: ["OPENAI_API_KEY"]
|
|
15489
|
+
},
|
|
15490
|
+
{
|
|
15491
|
+
providerId: "google",
|
|
15492
|
+
matches: (m) => m.startsWith("google/") || m.startsWith("gemini-") || m.includes("/gemini-"),
|
|
15493
|
+
secretNames: ["GOOGLE_API_KEY"]
|
|
15494
|
+
},
|
|
15495
|
+
{
|
|
15496
|
+
providerId: "mixlayer",
|
|
15497
|
+
// Matches open-weight models Mixlayer hosts (Qwen 3.5 family, Kimi) plus
|
|
15498
|
+
// explicit prefixes. Does NOT match closed Alibaba models (qwen3.5-flash/plus)
|
|
15499
|
+
// which route through Vercel Gateway. See mixlayer-executor.ts for the
|
|
15500
|
+
// canonical predicate mirrored here.
|
|
15501
|
+
matches: (m) => m.startsWith("mixlayer/") || m.startsWith("modelsocket/") || m.startsWith("qwen/") || m.startsWith("kimi-") || m.includes("/kimi-") || /(?:^|\/)qwen3[.-]5-\d+b(?:-a\d+b)?$/i.test(m),
|
|
15502
|
+
secretNames: ["MIXLAYER_API_KEY"]
|
|
15503
|
+
},
|
|
15504
|
+
{
|
|
15505
|
+
providerId: "xai",
|
|
15506
|
+
matches: (m) => m.startsWith("grok-") || m.startsWith("xai/"),
|
|
15507
|
+
secretNames: ["XAI_API_KEY"]
|
|
15508
|
+
}
|
|
15509
|
+
];
|
|
15510
|
+
function resolveModelSecretNames(model) {
|
|
15511
|
+
const lower = model.toLowerCase();
|
|
15512
|
+
for (const spec of PROVIDER_SECRET_SPECS) {
|
|
15513
|
+
if (spec.matches(lower)) return [...spec.secretNames];
|
|
15514
|
+
}
|
|
15515
|
+
return [];
|
|
15516
|
+
}
|
|
15426
15517
|
var MCPServerCategory = {
|
|
15427
15518
|
COMMUNICATION: "communication",
|
|
15428
15519
|
PRODUCTIVITY: "productivity",
|
|
@@ -30326,12 +30417,162 @@ var TELEGRAM_INTEGRATION = {
|
|
|
30326
30417
|
}
|
|
30327
30418
|
]
|
|
30328
30419
|
};
|
|
30420
|
+
var IMESSAGE_INTEGRATION = {
|
|
30421
|
+
id: "imessage",
|
|
30422
|
+
name: "iMessage",
|
|
30423
|
+
description: "Send iMessage / SMS messages, read conversation history, and react to messages via Sendblue.",
|
|
30424
|
+
transport: "http",
|
|
30425
|
+
url: "",
|
|
30426
|
+
// Credentials live on the iMessage productSurface, not in
|
|
30427
|
+
// organization_integrations. The handler reads them on-demand.
|
|
30428
|
+
requiredCredentials: [],
|
|
30429
|
+
category: MCPServerCategory.COMMUNICATION,
|
|
30430
|
+
documentationUrl: "https://docs.sendblue.com/",
|
|
30431
|
+
icon: "message",
|
|
30432
|
+
// A single agent can register multiple iMessage tool instances pinned to
|
|
30433
|
+
// different surfaces (i.e. different phone numbers) via
|
|
30434
|
+
// `toolConfig.surfaceId`.
|
|
30435
|
+
multiInstance: true,
|
|
30436
|
+
tools: [
|
|
30437
|
+
{
|
|
30438
|
+
name: "send_message",
|
|
30439
|
+
description: "Send an iMessage to a phone number. Falls back to SMS automatically when the recipient is not on iMessage (was_downgraded). Long messages are bubble-split.",
|
|
30440
|
+
parametersSchema: {
|
|
30441
|
+
type: "object",
|
|
30442
|
+
properties: {
|
|
30443
|
+
to: {
|
|
30444
|
+
type: "string",
|
|
30445
|
+
description: "Recipient phone number in E.164 format (e.g. +14155550100)."
|
|
30446
|
+
},
|
|
30447
|
+
text: {
|
|
30448
|
+
type: "string",
|
|
30449
|
+
description: "Message text to send. Markdown is converted to plain iMessage formatting."
|
|
30450
|
+
},
|
|
30451
|
+
// @snake-case-ok: tool input fields use snake_case for LLM ergonomics
|
|
30452
|
+
media_url: {
|
|
30453
|
+
type: "string",
|
|
30454
|
+
description: "Optional public URL of an image/video attachment."
|
|
30455
|
+
}
|
|
30456
|
+
},
|
|
30457
|
+
required: ["to", "text"]
|
|
30458
|
+
}
|
|
30459
|
+
},
|
|
30460
|
+
{
|
|
30461
|
+
name: "send_group_message",
|
|
30462
|
+
description: "Send a message to an iMessage group chat. Provide either group_id (preferred \u2014 preserves the existing thread) or a numbers array (creates an ad-hoc group).",
|
|
30463
|
+
parametersSchema: {
|
|
30464
|
+
type: "object",
|
|
30465
|
+
properties: {
|
|
30466
|
+
// @snake-case-ok-start: Sendblue API uses snake_case for group identifiers
|
|
30467
|
+
group_id: {
|
|
30468
|
+
type: "string",
|
|
30469
|
+
description: "Sendblue group identifier. Required for replying to an existing group; obtain via list_conversations or get_group_info."
|
|
30470
|
+
},
|
|
30471
|
+
numbers: {
|
|
30472
|
+
type: "array",
|
|
30473
|
+
description: "Recipient phone numbers in E.164 format. Used when group_id is not yet known (creates an ad-hoc group). Ignored when group_id is set.",
|
|
30474
|
+
items: { type: "string" }
|
|
30475
|
+
},
|
|
30476
|
+
text: { type: "string", description: "Message text to send." },
|
|
30477
|
+
media_url: {
|
|
30478
|
+
type: "string",
|
|
30479
|
+
description: "Optional public URL of an image/video attachment."
|
|
30480
|
+
}
|
|
30481
|
+
// @snake-case-ok-end
|
|
30482
|
+
},
|
|
30483
|
+
required: ["text"]
|
|
30484
|
+
}
|
|
30485
|
+
},
|
|
30486
|
+
{
|
|
30487
|
+
name: "list_conversations",
|
|
30488
|
+
description: "List recent iMessage conversations (1:1 and group) the bot has participated in, ordered by most recent activity.",
|
|
30489
|
+
parametersSchema: {
|
|
30490
|
+
type: "object",
|
|
30491
|
+
properties: {
|
|
30492
|
+
limit: {
|
|
30493
|
+
type: "number",
|
|
30494
|
+
description: "Maximum number of conversations to return (default 25, max 100).",
|
|
30495
|
+
minimum: 1,
|
|
30496
|
+
maximum: 100
|
|
30497
|
+
},
|
|
30498
|
+
before: {
|
|
30499
|
+
type: "string",
|
|
30500
|
+
description: "ISO 8601 timestamp; only return conversations whose lastMessageAt is earlier."
|
|
30501
|
+
}
|
|
30502
|
+
},
|
|
30503
|
+
required: []
|
|
30504
|
+
}
|
|
30505
|
+
},
|
|
30506
|
+
{
|
|
30507
|
+
name: "get_conversation_history",
|
|
30508
|
+
description: "Read the recent message history of an iMessage conversation. Useful for catching up on context before replying.",
|
|
30509
|
+
parametersSchema: {
|
|
30510
|
+
type: "object",
|
|
30511
|
+
properties: {
|
|
30512
|
+
// @snake-case-ok: tool input fields use snake_case for LLM ergonomics
|
|
30513
|
+
conversation_id: {
|
|
30514
|
+
type: "string",
|
|
30515
|
+
description: "Runtype messaging conversation ID (returned by list_conversations)."
|
|
30516
|
+
},
|
|
30517
|
+
limit: {
|
|
30518
|
+
type: "number",
|
|
30519
|
+
description: "Maximum number of messages to return (default 50, max 200).",
|
|
30520
|
+
minimum: 1,
|
|
30521
|
+
maximum: 200
|
|
30522
|
+
},
|
|
30523
|
+
before: {
|
|
30524
|
+
type: "string",
|
|
30525
|
+
description: "ISO 8601 timestamp; only return messages created before this."
|
|
30526
|
+
}
|
|
30527
|
+
},
|
|
30528
|
+
required: ["conversation_id"]
|
|
30529
|
+
}
|
|
30530
|
+
},
|
|
30531
|
+
{
|
|
30532
|
+
name: "get_group_info",
|
|
30533
|
+
description: "Look up display name and participant phone numbers for an iMessage group, sourced from the most recent inbound webhook for that group.",
|
|
30534
|
+
parametersSchema: {
|
|
30535
|
+
type: "object",
|
|
30536
|
+
properties: {
|
|
30537
|
+
// @snake-case-ok: tool input fields use snake_case for LLM ergonomics
|
|
30538
|
+
group_id: {
|
|
30539
|
+
type: "string",
|
|
30540
|
+
description: "Sendblue group identifier."
|
|
30541
|
+
}
|
|
30542
|
+
},
|
|
30543
|
+
required: ["group_id"]
|
|
30544
|
+
}
|
|
30545
|
+
},
|
|
30546
|
+
{
|
|
30547
|
+
name: "send_reaction",
|
|
30548
|
+
description: "Send a tapback reaction (\u{1F44D} \u2764\uFE0F \u{1F602} \u203C\uFE0F \u2753 \u{1F44E}) to a previous iMessage. iMessage-only \u2014 has no effect on SMS recipients.",
|
|
30549
|
+
parametersSchema: {
|
|
30550
|
+
type: "object",
|
|
30551
|
+
properties: {
|
|
30552
|
+
// @snake-case-ok-start: Sendblue API uses snake_case for message identifiers
|
|
30553
|
+
message_handle: {
|
|
30554
|
+
type: "string",
|
|
30555
|
+
description: "The Sendblue message_handle of the message you are reacting to (from inbound webhooks or earlier outbound responses)."
|
|
30556
|
+
},
|
|
30557
|
+
reaction: {
|
|
30558
|
+
type: "string",
|
|
30559
|
+
enum: ["love", "like", "dislike", "laugh", "emphasize", "question"],
|
|
30560
|
+
description: "Tapback type. love=\u2764\uFE0F, like=\u{1F44D}, dislike=\u{1F44E}, laugh=\u{1F602}, emphasize=\u203C\uFE0F, question=\u2753."
|
|
30561
|
+
}
|
|
30562
|
+
// @snake-case-ok-end
|
|
30563
|
+
},
|
|
30564
|
+
required: ["message_handle", "reaction"]
|
|
30565
|
+
}
|
|
30566
|
+
}
|
|
30567
|
+
]
|
|
30568
|
+
};
|
|
30329
30569
|
var INTEGRATIONS_REGISTRY = [
|
|
30330
30570
|
SLACK_INTEGRATION,
|
|
30331
30571
|
GOOGLE_INTEGRATION,
|
|
30332
30572
|
LINEAR_INTEGRATION,
|
|
30333
30573
|
GITHUB_INTEGRATION,
|
|
30334
|
-
TELEGRAM_INTEGRATION
|
|
30574
|
+
TELEGRAM_INTEGRATION,
|
|
30575
|
+
IMESSAGE_INTEGRATION
|
|
30335
30576
|
];
|
|
30336
30577
|
function getAllIntegrations() {
|
|
30337
30578
|
return INTEGRATIONS_REGISTRY;
|
|
@@ -32417,6 +32658,38 @@ var SLACK_MANIFEST_BOT_SCOPES = [
|
|
|
32417
32658
|
...SLACK_REQUIRED_BOT_SCOPES,
|
|
32418
32659
|
...SLACK_OPTIONAL_BOT_SCOPES
|
|
32419
32660
|
];
|
|
32661
|
+
var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
|
|
32662
|
+
function extractSecretReferences(template) {
|
|
32663
|
+
const keys = /* @__PURE__ */ new Set();
|
|
32664
|
+
let match;
|
|
32665
|
+
const regex = new RegExp(SECRET_REF_PATTERN.source, "g");
|
|
32666
|
+
while ((match = regex.exec(template)) !== null) {
|
|
32667
|
+
const key = match[1];
|
|
32668
|
+
if (key) keys.add(key);
|
|
32669
|
+
}
|
|
32670
|
+
return Array.from(keys);
|
|
32671
|
+
}
|
|
32672
|
+
function extractSecretReferencesFromAnyValue(value, maxDepth = 10) {
|
|
32673
|
+
const keys = /* @__PURE__ */ new Set();
|
|
32674
|
+
walk(value, 0);
|
|
32675
|
+
return Array.from(keys);
|
|
32676
|
+
function walk(v, depth) {
|
|
32677
|
+
if (depth > maxDepth) return;
|
|
32678
|
+
if (typeof v === "string") {
|
|
32679
|
+
for (const key of extractSecretReferences(v)) keys.add(key);
|
|
32680
|
+
return;
|
|
32681
|
+
}
|
|
32682
|
+
if (Array.isArray(v)) {
|
|
32683
|
+
for (const item of v) walk(item, depth + 1);
|
|
32684
|
+
return;
|
|
32685
|
+
}
|
|
32686
|
+
if (v && typeof v === "object") {
|
|
32687
|
+
for (const inner of Object.values(v)) {
|
|
32688
|
+
walk(inner, depth + 1);
|
|
32689
|
+
}
|
|
32690
|
+
}
|
|
32691
|
+
}
|
|
32692
|
+
}
|
|
32420
32693
|
var FULL_PRODUCT_OBJECT_VERSION_1_0 = "1.0";
|
|
32421
32694
|
var FULL_PRODUCT_OBJECT_VERSION_1_1 = "1.1";
|
|
32422
32695
|
var createPolicySchema = external_exports.enum(["create", "skip", "manual"]).optional();
|
|
@@ -32679,6 +32952,7 @@ var surfaceSchema = external_exports.object({
|
|
|
32679
32952
|
"slack",
|
|
32680
32953
|
"schedule",
|
|
32681
32954
|
"sms",
|
|
32955
|
+
"imessage",
|
|
32682
32956
|
"discord",
|
|
32683
32957
|
"whatsapp",
|
|
32684
32958
|
"messaging",
|
|
@@ -32832,8 +33106,8 @@ var fullProductObjectSchema = external_exports.object({
|
|
|
32832
33106
|
}
|
|
32833
33107
|
}
|
|
32834
33108
|
});
|
|
32835
|
-
function createIssue(severity, code, message,
|
|
32836
|
-
return { code, message, path:
|
|
33109
|
+
function createIssue(severity, code, message, path15, suggestedFix) {
|
|
33110
|
+
return { code, message, path: path15, severity, ...suggestedFix ? { suggestedFix } : {} };
|
|
32837
33111
|
}
|
|
32838
33112
|
function emptyResult() {
|
|
32839
33113
|
return { valid: true, errors: [], warnings: [], recommendations: [] };
|
|
@@ -33003,38 +33277,6 @@ function validateCapability(cap, index, context) {
|
|
|
33003
33277
|
}
|
|
33004
33278
|
return mergeResults(result, subResult);
|
|
33005
33279
|
}
|
|
33006
|
-
var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
|
|
33007
|
-
function extractSecretReferences(template) {
|
|
33008
|
-
const keys = /* @__PURE__ */ new Set();
|
|
33009
|
-
let match;
|
|
33010
|
-
const regex = new RegExp(SECRET_REF_PATTERN.source, "g");
|
|
33011
|
-
while ((match = regex.exec(template)) !== null) {
|
|
33012
|
-
const key = match[1];
|
|
33013
|
-
if (key) keys.add(key);
|
|
33014
|
-
}
|
|
33015
|
-
return Array.from(keys);
|
|
33016
|
-
}
|
|
33017
|
-
function extractSecretReferencesFromAnyValue(value, maxDepth = 10) {
|
|
33018
|
-
const keys = /* @__PURE__ */ new Set();
|
|
33019
|
-
walk(value, 0);
|
|
33020
|
-
return Array.from(keys);
|
|
33021
|
-
function walk(v, depth) {
|
|
33022
|
-
if (depth > maxDepth) return;
|
|
33023
|
-
if (typeof v === "string") {
|
|
33024
|
-
for (const key of extractSecretReferences(v)) keys.add(key);
|
|
33025
|
-
return;
|
|
33026
|
-
}
|
|
33027
|
-
if (Array.isArray(v)) {
|
|
33028
|
-
for (const item of v) walk(item, depth + 1);
|
|
33029
|
-
return;
|
|
33030
|
-
}
|
|
33031
|
-
if (v && typeof v === "object") {
|
|
33032
|
-
for (const inner of Object.values(v)) {
|
|
33033
|
-
walk(inner, depth + 1);
|
|
33034
|
-
}
|
|
33035
|
-
}
|
|
33036
|
-
}
|
|
33037
|
-
}
|
|
33038
33280
|
function validateToolDefinition(tool, index) {
|
|
33039
33281
|
const result = emptyResult();
|
|
33040
33282
|
const base = `tools[${index}]`;
|
|
@@ -33113,6 +33355,7 @@ var VALID_SURFACE_TYPES = /* @__PURE__ */ new Set([
|
|
|
33113
33355
|
"slack",
|
|
33114
33356
|
"schedule",
|
|
33115
33357
|
"sms",
|
|
33358
|
+
"imessage",
|
|
33116
33359
|
"discord",
|
|
33117
33360
|
"whatsapp",
|
|
33118
33361
|
"telegram",
|
|
@@ -33448,16 +33691,16 @@ var fullProductObjectTemplateSchema = external_exports.object({
|
|
|
33448
33691
|
});
|
|
33449
33692
|
var FLOW_PREFIX = "flow:";
|
|
33450
33693
|
var SECRET_PREFIX = "secret:";
|
|
33451
|
-
function collectStringLeafPaths(value,
|
|
33694
|
+
function collectStringLeafPaths(value, path15 = []) {
|
|
33452
33695
|
if (typeof value === "string") {
|
|
33453
|
-
return [{ path:
|
|
33696
|
+
return [{ path: path15, value }];
|
|
33454
33697
|
}
|
|
33455
33698
|
if (Array.isArray(value)) {
|
|
33456
|
-
return value.flatMap((item, index) => collectStringLeafPaths(item, [...
|
|
33699
|
+
return value.flatMap((item, index) => collectStringLeafPaths(item, [...path15, String(index)]));
|
|
33457
33700
|
}
|
|
33458
33701
|
if (value && typeof value === "object") {
|
|
33459
33702
|
return Object.entries(value).flatMap(
|
|
33460
|
-
([key, nestedValue]) => collectStringLeafPaths(nestedValue, [...
|
|
33703
|
+
([key, nestedValue]) => collectStringLeafPaths(nestedValue, [...path15, key])
|
|
33461
33704
|
);
|
|
33462
33705
|
}
|
|
33463
33706
|
return [];
|
|
@@ -33512,8 +33755,8 @@ function getVariableReferences(template) {
|
|
|
33512
33755
|
}
|
|
33513
33756
|
return references;
|
|
33514
33757
|
}
|
|
33515
|
-
function normalizeValidationPath(
|
|
33516
|
-
return
|
|
33758
|
+
function normalizeValidationPath(path15) {
|
|
33759
|
+
return path15.map(String).join(".");
|
|
33517
33760
|
}
|
|
33518
33761
|
function coerceFPOTemplateVariableValue(variable, rawValue) {
|
|
33519
33762
|
if (rawValue === void 0 || rawValue === null || rawValue === "") {
|
|
@@ -33743,6 +33986,7 @@ var ARCHITECTURE_PREVIEW_SURFACE_TYPES = [
|
|
|
33743
33986
|
"email",
|
|
33744
33987
|
"slack",
|
|
33745
33988
|
"sms",
|
|
33989
|
+
"imessage",
|
|
33746
33990
|
"discord",
|
|
33747
33991
|
"whatsapp",
|
|
33748
33992
|
"telegram",
|
|
@@ -34033,6 +34277,7 @@ var PLATFORM_CATALOG = {
|
|
|
34033
34277
|
"slack",
|
|
34034
34278
|
"schedule",
|
|
34035
34279
|
"sms",
|
|
34280
|
+
"imessage",
|
|
34036
34281
|
"discord",
|
|
34037
34282
|
"whatsapp",
|
|
34038
34283
|
"messaging",
|
|
@@ -34274,6 +34519,39 @@ var SURFACE_TYPE_METADATA = {
|
|
|
34274
34519
|
executionHint: "You are responding via SMS. Be extremely brief \u2014 ideally one or two short sentences. Plain text only, no markdown, no lists. Get straight to the point. Do not include reasoning traces or process narration."
|
|
34275
34520
|
}
|
|
34276
34521
|
},
|
|
34522
|
+
imessage: {
|
|
34523
|
+
description: "iMessage messaging via Sendblue for Apple ecosystem interactions",
|
|
34524
|
+
useCases: ["customer support", "appointment reminders", "rich messaging", "two-way texting"],
|
|
34525
|
+
examples: ["iMessage support agent", "Appointment reminder bot", "Rich media messaging bot"],
|
|
34526
|
+
traits: {
|
|
34527
|
+
streaming: "none",
|
|
34528
|
+
messagesMutable: false,
|
|
34529
|
+
deliveryModel: "async",
|
|
34530
|
+
mediaSupport: "images",
|
|
34531
|
+
interactiveUI: "none",
|
|
34532
|
+
inboundMediaSupport: true,
|
|
34533
|
+
consumerType: "human",
|
|
34534
|
+
reasoningVisibility: "always_strip",
|
|
34535
|
+
markdownDialect: "none",
|
|
34536
|
+
threadModel: "flat",
|
|
34537
|
+
senderIdentity: "verified",
|
|
34538
|
+
// ~4 short bubbles' worth of headroom. The adapter splits on paragraph
|
|
34539
|
+
// boundaries before sending; this cap signals to the model that long is
|
|
34540
|
+
// wrong without imposing a hard truncate that would clip mid-thought.
|
|
34541
|
+
maxResponseLength: 1200,
|
|
34542
|
+
executionHint: [
|
|
34543
|
+
"You are responding via iMessage. Hard rules:",
|
|
34544
|
+
"- Plain text only. No markdown \u2014 no **bold**, no # headings, no - bullets, no `code`, no > quotes, no fenced code blocks.",
|
|
34545
|
+
"- 1\u20133 sentences per reply, under 300 characters total when possible.",
|
|
34546
|
+
"- Texting tone: conversational, lowercase is fine, contractions welcome.",
|
|
34547
|
+
'- No greetings ("Hi!", "Hey there!") and no closings ("Let me know!", "Hope this helps!").',
|
|
34548
|
+
`- No AI disclaimers ("As an AI...", "I cannot...", "I'd be happy to help").`,
|
|
34549
|
+
"- One emoji max, only when it fits naturally.",
|
|
34550
|
+
"- For multi-part replies, separate logical chunks with a blank line \u2014 each chunk becomes its own bubble.",
|
|
34551
|
+
"- Do not include reasoning traces or process narration."
|
|
34552
|
+
].join("\n")
|
|
34553
|
+
}
|
|
34554
|
+
},
|
|
34277
34555
|
discord: {
|
|
34278
34556
|
description: "Discord bot for community engagement",
|
|
34279
34557
|
useCases: ["community support", "moderation", "server management"],
|
|
@@ -35085,7 +35363,7 @@ function buildDashboardUrl(opts) {
|
|
|
35085
35363
|
while (base.endsWith("/")) {
|
|
35086
35364
|
base = base.slice(0, -1);
|
|
35087
35365
|
}
|
|
35088
|
-
const
|
|
35366
|
+
const path15 = opts.path.startsWith("/") ? opts.path : `/${opts.path}`;
|
|
35089
35367
|
const params = new URLSearchParams();
|
|
35090
35368
|
if (isValidAccountId(opts.account)) {
|
|
35091
35369
|
params.set(ACCOUNT_QUERY_PARAM, opts.account);
|
|
@@ -35098,7 +35376,7 @@ function buildDashboardUrl(opts) {
|
|
|
35098
35376
|
}
|
|
35099
35377
|
}
|
|
35100
35378
|
const qs = params.toString();
|
|
35101
|
-
return qs ? `${base}${
|
|
35379
|
+
return qs ? `${base}${path15}?${qs}` : `${base}${path15}`;
|
|
35102
35380
|
}
|
|
35103
35381
|
function parseAccountId(value) {
|
|
35104
35382
|
if (!value) return null;
|
|
@@ -36147,14 +36425,14 @@ async function promptConfirm(message, options) {
|
|
|
36147
36425
|
output: process.stdout,
|
|
36148
36426
|
terminal: true
|
|
36149
36427
|
});
|
|
36150
|
-
return new Promise((
|
|
36428
|
+
return new Promise((resolve10) => {
|
|
36151
36429
|
rl.question(chalk2.cyan(`${message} (${hint}): `), (answer) => {
|
|
36152
36430
|
rl.close();
|
|
36153
36431
|
const trimmed = answer.trim().toLowerCase();
|
|
36154
36432
|
if (trimmed === "") {
|
|
36155
|
-
|
|
36433
|
+
resolve10(defaultYes);
|
|
36156
36434
|
} else {
|
|
36157
|
-
|
|
36435
|
+
resolve10(trimmed === "y" || trimmed === "yes");
|
|
36158
36436
|
}
|
|
36159
36437
|
});
|
|
36160
36438
|
});
|
|
@@ -36266,9 +36544,9 @@ var ApiClient = class {
|
|
|
36266
36544
|
this.baseUrl = baseUrl || getApiUrl();
|
|
36267
36545
|
}
|
|
36268
36546
|
/** Prefix path with API version (e.g. /v1) so all requests hit versioned routes. */
|
|
36269
|
-
path(
|
|
36547
|
+
path(path15) {
|
|
36270
36548
|
const version2 = getApiVersion();
|
|
36271
|
-
const p =
|
|
36549
|
+
const p = path15.startsWith("/") ? path15 : `/${path15}`;
|
|
36272
36550
|
return p.startsWith(`/${version2}/`) ? p : `/${version2}${p}`;
|
|
36273
36551
|
}
|
|
36274
36552
|
headers(extra) {
|
|
@@ -36301,8 +36579,8 @@ var ApiClient = class {
|
|
|
36301
36579
|
}
|
|
36302
36580
|
return response.json();
|
|
36303
36581
|
}
|
|
36304
|
-
async get(
|
|
36305
|
-
const url2 = new URL(this.path(
|
|
36582
|
+
async get(path15, params) {
|
|
36583
|
+
const url2 = new URL(this.path(path15), this.baseUrl);
|
|
36306
36584
|
if (params) {
|
|
36307
36585
|
for (const [key, value] of Object.entries(params)) {
|
|
36308
36586
|
if (value !== void 0 && value !== "") {
|
|
@@ -36315,32 +36593,32 @@ var ApiClient = class {
|
|
|
36315
36593
|
});
|
|
36316
36594
|
return this.handleResponse(response);
|
|
36317
36595
|
}
|
|
36318
|
-
async post(
|
|
36319
|
-
const response = await fetch(new URL(this.path(
|
|
36596
|
+
async post(path15, body) {
|
|
36597
|
+
const response = await fetch(new URL(this.path(path15), this.baseUrl).toString(), {
|
|
36320
36598
|
method: "POST",
|
|
36321
36599
|
headers: this.headers(),
|
|
36322
36600
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
36323
36601
|
});
|
|
36324
36602
|
return this.handleResponse(response);
|
|
36325
36603
|
}
|
|
36326
|
-
async put(
|
|
36327
|
-
const response = await fetch(new URL(this.path(
|
|
36604
|
+
async put(path15, body) {
|
|
36605
|
+
const response = await fetch(new URL(this.path(path15), this.baseUrl).toString(), {
|
|
36328
36606
|
method: "PUT",
|
|
36329
36607
|
headers: this.headers(),
|
|
36330
36608
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
36331
36609
|
});
|
|
36332
36610
|
return this.handleResponse(response);
|
|
36333
36611
|
}
|
|
36334
|
-
async patch(
|
|
36335
|
-
const response = await fetch(new URL(this.path(
|
|
36612
|
+
async patch(path15, body) {
|
|
36613
|
+
const response = await fetch(new URL(this.path(path15), this.baseUrl).toString(), {
|
|
36336
36614
|
method: "PATCH",
|
|
36337
36615
|
headers: this.headers(),
|
|
36338
36616
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
36339
36617
|
});
|
|
36340
36618
|
return this.handleResponse(response);
|
|
36341
36619
|
}
|
|
36342
|
-
async delete(
|
|
36343
|
-
const response = await fetch(new URL(this.path(
|
|
36620
|
+
async delete(path15) {
|
|
36621
|
+
const response = await fetch(new URL(this.path(path15), this.baseUrl).toString(), {
|
|
36344
36622
|
method: "DELETE",
|
|
36345
36623
|
headers: this.headers()
|
|
36346
36624
|
});
|
|
@@ -36354,8 +36632,8 @@ var ApiClient = class {
|
|
|
36354
36632
|
throw new ApiError(response.status, message);
|
|
36355
36633
|
}
|
|
36356
36634
|
}
|
|
36357
|
-
async stream(
|
|
36358
|
-
const response = await fetch(new URL(this.path(
|
|
36635
|
+
async stream(path15, body) {
|
|
36636
|
+
const response = await fetch(new URL(this.path(path15), this.baseUrl).toString(), {
|
|
36359
36637
|
method: "POST",
|
|
36360
36638
|
headers: this.headers({ Accept: "text/event-stream" }),
|
|
36361
36639
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
@@ -43846,8 +44124,8 @@ function MarathonApp({
|
|
|
43846
44124
|
setIsTerminalCheckpoint(true);
|
|
43847
44125
|
isTerminalCheckpointRef.current = true;
|
|
43848
44126
|
}
|
|
43849
|
-
return new Promise((
|
|
43850
|
-
checkpointResolveRef.current =
|
|
44127
|
+
return new Promise((resolve10) => {
|
|
44128
|
+
checkpointResolveRef.current = resolve10;
|
|
43851
44129
|
});
|
|
43852
44130
|
},
|
|
43853
44131
|
updateMilestone: (milestone) => {
|
|
@@ -45174,16 +45452,16 @@ function MarathonStartupShell({
|
|
|
45174
45452
|
latestAppPropsRef.current = marathonAppProps;
|
|
45175
45453
|
useEffect20(() => {
|
|
45176
45454
|
if (scene !== "app" || !appReadyResolverRef.current) return;
|
|
45177
|
-
const
|
|
45455
|
+
const resolve10 = appReadyResolverRef.current;
|
|
45178
45456
|
appReadyResolverRef.current = null;
|
|
45179
|
-
|
|
45457
|
+
resolve10();
|
|
45180
45458
|
}, [scene]);
|
|
45181
45459
|
const beginTransition = (target) => {
|
|
45182
45460
|
if (transitionPromiseRef.current) return transitionPromiseRef.current;
|
|
45183
45461
|
if (target === "app" && !latestAppPropsRef.current) {
|
|
45184
45462
|
throw new Error("Cannot complete startup before marathon app props are ready.");
|
|
45185
45463
|
}
|
|
45186
|
-
const promise2 = new Promise((
|
|
45464
|
+
const promise2 = new Promise((resolve10) => {
|
|
45187
45465
|
globalThis.setTimeout(() => {
|
|
45188
45466
|
setPrompt(null);
|
|
45189
45467
|
setModelChoices(null);
|
|
@@ -45204,12 +45482,12 @@ function MarathonStartupShell({
|
|
|
45204
45482
|
if (target === "app") {
|
|
45205
45483
|
appReadyResolverRef.current = () => {
|
|
45206
45484
|
transitionPromiseRef.current = null;
|
|
45207
|
-
|
|
45485
|
+
resolve10();
|
|
45208
45486
|
};
|
|
45209
45487
|
} else {
|
|
45210
45488
|
dismissResolverRef.current = () => {
|
|
45211
45489
|
transitionPromiseRef.current = null;
|
|
45212
|
-
|
|
45490
|
+
resolve10();
|
|
45213
45491
|
};
|
|
45214
45492
|
}
|
|
45215
45493
|
}, Math.max(0, MIN_HOLD_MS - (Date.now() - mountedAtRef.current)));
|
|
@@ -45226,8 +45504,8 @@ function MarathonStartupShell({
|
|
|
45226
45504
|
setModelChoices(null);
|
|
45227
45505
|
setPrompt(nextPrompt);
|
|
45228
45506
|
setSelectedPromptIndex(0);
|
|
45229
|
-
return new Promise((
|
|
45230
|
-
promptResolverRef.current =
|
|
45507
|
+
return new Promise((resolve10) => {
|
|
45508
|
+
promptResolverRef.current = resolve10;
|
|
45231
45509
|
});
|
|
45232
45510
|
},
|
|
45233
45511
|
requestModelChoice: async (nextCurrentModel, models) => {
|
|
@@ -45235,8 +45513,8 @@ function MarathonStartupShell({
|
|
|
45235
45513
|
setPlaybookConfirm(null);
|
|
45236
45514
|
setCurrentModel(nextCurrentModel);
|
|
45237
45515
|
setModelChoices(models);
|
|
45238
|
-
return new Promise((
|
|
45239
|
-
modelResolverRef.current =
|
|
45516
|
+
return new Promise((resolve10) => {
|
|
45517
|
+
modelResolverRef.current = resolve10;
|
|
45240
45518
|
});
|
|
45241
45519
|
},
|
|
45242
45520
|
requestPlaybookModelConfirm: async (playbookName, milestoneModels) => {
|
|
@@ -45251,8 +45529,8 @@ function MarathonStartupShell({
|
|
|
45251
45529
|
// Default selection is the "Confirm" action (first item after milestones)
|
|
45252
45530
|
selectedIndex: names.length
|
|
45253
45531
|
});
|
|
45254
|
-
return new Promise((
|
|
45255
|
-
playbookConfirmResolverRef.current =
|
|
45532
|
+
return new Promise((resolve10) => {
|
|
45533
|
+
playbookConfirmResolverRef.current = resolve10;
|
|
45256
45534
|
});
|
|
45257
45535
|
},
|
|
45258
45536
|
completeStartup: () => beginTransition("app"),
|
|
@@ -45750,7 +46028,7 @@ async function retryOnNetworkError(fn, opts = {}) {
|
|
|
45750
46028
|
}
|
|
45751
46029
|
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
45752
46030
|
opts.onRetry?.(attempt + 1, delay, error51);
|
|
45753
|
-
await new Promise((
|
|
46031
|
+
await new Promise((resolve10) => setTimeout(resolve10, delay));
|
|
45754
46032
|
}
|
|
45755
46033
|
}
|
|
45756
46034
|
throw lastError;
|
|
@@ -46010,14 +46288,14 @@ async function promptNumericSelect(choices, promptLabel) {
|
|
|
46010
46288
|
output: process.stdout,
|
|
46011
46289
|
terminal: true
|
|
46012
46290
|
});
|
|
46013
|
-
return new Promise((
|
|
46291
|
+
return new Promise((resolve10) => {
|
|
46014
46292
|
const ask = () => {
|
|
46015
46293
|
rl.question(chalk14.cyan(`
|
|
46016
46294
|
${promptLabel} (1-${choices.length}): `), (answer) => {
|
|
46017
46295
|
const value = parseInt(answer.trim(), 10);
|
|
46018
46296
|
if (value >= 1 && value <= choices.length) {
|
|
46019
46297
|
rl.close();
|
|
46020
|
-
|
|
46298
|
+
resolve10(choices[value - 1].value);
|
|
46021
46299
|
return;
|
|
46022
46300
|
}
|
|
46023
46301
|
console.log(chalk14.red(`Please enter a number between 1 and ${choices.length}.`));
|
|
@@ -46045,7 +46323,7 @@ ${message}`));
|
|
|
46045
46323
|
const previousRawMode = input.isRaw === true;
|
|
46046
46324
|
let selectedIndex = 0;
|
|
46047
46325
|
let renderedLineCount = 0;
|
|
46048
|
-
return new Promise((
|
|
46326
|
+
return new Promise((resolve10) => {
|
|
46049
46327
|
const renderMenu = () => {
|
|
46050
46328
|
if (renderedLineCount > 0) {
|
|
46051
46329
|
clearRenderedLines(output, renderedLineCount);
|
|
@@ -46067,7 +46345,7 @@ ${message}`));
|
|
|
46067
46345
|
};
|
|
46068
46346
|
const finish = (value) => {
|
|
46069
46347
|
cleanup();
|
|
46070
|
-
|
|
46348
|
+
resolve10(value);
|
|
46071
46349
|
};
|
|
46072
46350
|
const onKeypress = (_, key) => {
|
|
46073
46351
|
if (key.ctrl && key.name === "c") {
|
|
@@ -48277,7 +48555,7 @@ async function taskAction(agent, options) {
|
|
|
48277
48555
|
waitForUiExit = renderedShell.waitUntilExit;
|
|
48278
48556
|
rerenderUi = renderedShell.rerender;
|
|
48279
48557
|
unmountUi = renderedShell.unmount;
|
|
48280
|
-
await new Promise((
|
|
48558
|
+
await new Promise((resolve10) => setTimeout(resolve10, 0));
|
|
48281
48559
|
if (!startupShellRef.current) {
|
|
48282
48560
|
exitAltScreen();
|
|
48283
48561
|
unmountUi?.();
|
|
@@ -48823,7 +49101,7 @@ Saving state... done. Session saved to ${filePath}`);
|
|
|
48823
49101
|
waitForUiExit = renderedApp.waitUntilExit;
|
|
48824
49102
|
unmountUi = renderedApp.unmount;
|
|
48825
49103
|
}
|
|
48826
|
-
await new Promise((
|
|
49104
|
+
await new Promise((resolve10) => setTimeout(resolve10, 0));
|
|
48827
49105
|
const streamActions = streamRef.current;
|
|
48828
49106
|
if (!streamActions) {
|
|
48829
49107
|
exitAltScreen();
|
|
@@ -48948,7 +49226,7 @@ Saving state... done. Session saved to ${filePath}`);
|
|
|
48948
49226
|
};
|
|
48949
49227
|
if (event.phase === "start") {
|
|
48950
49228
|
currentActions.startContextCompaction(absoluteEvent);
|
|
48951
|
-
await new Promise((
|
|
49229
|
+
await new Promise((resolve10) => setTimeout(resolve10, 0));
|
|
48952
49230
|
return;
|
|
48953
49231
|
}
|
|
48954
49232
|
currentActions.finishContextCompaction(absoluteEvent);
|
|
@@ -50927,13 +51205,13 @@ apiKeysCommand.command("delete <id>").description("Delete an API key").option("-
|
|
|
50927
51205
|
await waitUntilExit2();
|
|
50928
51206
|
return;
|
|
50929
51207
|
}
|
|
50930
|
-
const confirmed = await new Promise((
|
|
51208
|
+
const confirmed = await new Promise((resolve10) => {
|
|
50931
51209
|
const { unmount } = render14(
|
|
50932
51210
|
React14.createElement(ConfirmPrompt, {
|
|
50933
51211
|
message: `Delete API key ${id}?`,
|
|
50934
51212
|
defaultValue: false,
|
|
50935
51213
|
onConfirm: (result) => {
|
|
50936
|
-
|
|
51214
|
+
resolve10(result);
|
|
50937
51215
|
unmount();
|
|
50938
51216
|
}
|
|
50939
51217
|
})
|
|
@@ -51038,8 +51316,8 @@ apiKeysCommand.command("analytics").description("Show API key usage analytics").
|
|
|
51038
51316
|
const client = new ApiClient(apiKey);
|
|
51039
51317
|
if (!isTTY(options) || options.json) {
|
|
51040
51318
|
try {
|
|
51041
|
-
const
|
|
51042
|
-
const data = await client.get(
|
|
51319
|
+
const path15 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
|
|
51320
|
+
const data = await client.get(path15);
|
|
51043
51321
|
printJson(data);
|
|
51044
51322
|
} catch (error51) {
|
|
51045
51323
|
const message = error51 instanceof Error ? error51.message : "Unknown error";
|
|
@@ -51056,8 +51334,8 @@ apiKeysCommand.command("analytics").description("Show API key usage analytics").
|
|
|
51056
51334
|
useEffect25(() => {
|
|
51057
51335
|
const run = async () => {
|
|
51058
51336
|
try {
|
|
51059
|
-
const
|
|
51060
|
-
const data = await client.get(
|
|
51337
|
+
const path15 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
|
|
51338
|
+
const data = await client.get(path15);
|
|
51061
51339
|
printJson(data);
|
|
51062
51340
|
setSuccess(true);
|
|
51063
51341
|
setLoading(false);
|
|
@@ -51399,13 +51677,13 @@ clientTokensCommand.command("delete <id>").description("Delete a client token").
|
|
|
51399
51677
|
await waitUntilExit2();
|
|
51400
51678
|
return;
|
|
51401
51679
|
}
|
|
51402
|
-
const confirmed = await new Promise((
|
|
51680
|
+
const confirmed = await new Promise((resolve10) => {
|
|
51403
51681
|
const { unmount } = render15(
|
|
51404
51682
|
React15.createElement(ConfirmPrompt, {
|
|
51405
51683
|
message: `Delete client token ${id}?`,
|
|
51406
51684
|
defaultValue: false,
|
|
51407
51685
|
onConfirm: (result) => {
|
|
51408
|
-
|
|
51686
|
+
resolve10(result);
|
|
51409
51687
|
unmount();
|
|
51410
51688
|
}
|
|
51411
51689
|
})
|
|
@@ -51710,8 +51988,8 @@ function defaultTokenName(agentName) {
|
|
|
51710
51988
|
}
|
|
51711
51989
|
async function promptLine(rl, question, defaultValue) {
|
|
51712
51990
|
const hint = defaultValue ? chalk23.dim(` (${defaultValue})`) : "";
|
|
51713
|
-
const answer = await new Promise((
|
|
51714
|
-
rl.question(`${question}${hint}: `,
|
|
51991
|
+
const answer = await new Promise((resolve10) => {
|
|
51992
|
+
rl.question(`${question}${hint}: `, resolve10);
|
|
51715
51993
|
});
|
|
51716
51994
|
const trimmed = answer.trim();
|
|
51717
51995
|
if (!trimmed && defaultValue !== void 0) {
|
|
@@ -51721,8 +51999,8 @@ async function promptLine(rl, question, defaultValue) {
|
|
|
51721
51999
|
}
|
|
51722
52000
|
async function promptConfirm2(rl, message, defaultYes = false) {
|
|
51723
52001
|
const hint = defaultYes ? chalk23.dim(" (Y/n)") : chalk23.dim(" (y/N)");
|
|
51724
|
-
const answer = await new Promise((
|
|
51725
|
-
rl.question(`${message}${hint}: `,
|
|
52002
|
+
const answer = await new Promise((resolve10) => {
|
|
52003
|
+
rl.question(`${message}${hint}: `, resolve10);
|
|
51726
52004
|
});
|
|
51727
52005
|
const t = answer.trim().toLowerCase();
|
|
51728
52006
|
if (t === "") return defaultYes;
|
|
@@ -51791,18 +52069,18 @@ Dashboard: ${initial.dashboardUrl}`));
|
|
|
51791
52069
|
process.stdin.removeAllListeners("keypress");
|
|
51792
52070
|
process.stdin.pause();
|
|
51793
52071
|
};
|
|
51794
|
-
await new Promise((
|
|
52072
|
+
await new Promise((resolve10) => {
|
|
51795
52073
|
const onKeypress = async (_str, key) => {
|
|
51796
52074
|
if (!key) return;
|
|
51797
52075
|
if (key.ctrl && key.name === "c") {
|
|
51798
52076
|
cleanup();
|
|
51799
|
-
|
|
52077
|
+
resolve10();
|
|
51800
52078
|
process.exit(0);
|
|
51801
52079
|
}
|
|
51802
52080
|
const name = key.name;
|
|
51803
52081
|
if (name === "q" || name === "escape") {
|
|
51804
52082
|
cleanup();
|
|
51805
|
-
|
|
52083
|
+
resolve10();
|
|
51806
52084
|
return;
|
|
51807
52085
|
}
|
|
51808
52086
|
if (name === "c") {
|
|
@@ -52662,9 +52940,283 @@ flowVersionsCommand.command("publish <flowId>").description("Publish a version")
|
|
|
52662
52940
|
await waitUntilExit();
|
|
52663
52941
|
});
|
|
52664
52942
|
|
|
52665
|
-
// src/commands/
|
|
52943
|
+
// src/commands/agent-versions.ts
|
|
52666
52944
|
import { Command as Command21 } from "commander";
|
|
52667
52945
|
import chalk27 from "chalk";
|
|
52946
|
+
import React19 from "react";
|
|
52947
|
+
import { render as render19 } from "ink";
|
|
52948
|
+
import { useState as useState33, useEffect as useEffect30 } from "react";
|
|
52949
|
+
import { Text as Text35 } from "ink";
|
|
52950
|
+
var agentVersionsCommand = new Command21("agent-versions").description(
|
|
52951
|
+
"Manage agent versions"
|
|
52952
|
+
);
|
|
52953
|
+
agentVersionsCommand.command("list <agentId>").description("List all versions for an agent").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (agentId, options) => {
|
|
52954
|
+
const apiKey = await ensureAuth();
|
|
52955
|
+
if (!apiKey) return;
|
|
52956
|
+
const client = new ApiClient(apiKey);
|
|
52957
|
+
if (!isTTY(options) || options.json) {
|
|
52958
|
+
try {
|
|
52959
|
+
const data = await client.get(`/agent-versions/${agentId}`);
|
|
52960
|
+
if (options.json) {
|
|
52961
|
+
printJson(data);
|
|
52962
|
+
} else {
|
|
52963
|
+
const versions = data.versions ?? [];
|
|
52964
|
+
if (versions.length === 0) {
|
|
52965
|
+
console.log(chalk27.gray("No versions found"));
|
|
52966
|
+
return;
|
|
52967
|
+
}
|
|
52968
|
+
console.log(chalk27.cyan(`Versions for agent ${agentId}:`));
|
|
52969
|
+
for (const v of versions) {
|
|
52970
|
+
const isPublished = v.id === data.publishedVersionId;
|
|
52971
|
+
const liveTag = isPublished ? chalk27.green(" [live]") : "";
|
|
52972
|
+
const versionLabel = v.label || (v.versionNumber !== void 0 ? `v${v.versionNumber}` : v.id);
|
|
52973
|
+
const date5 = v.createdAt ? chalk27.gray(` ${v.createdAt}`) : "";
|
|
52974
|
+
console.log(` ${chalk27.green(v.id)} ${versionLabel}${liveTag}${date5}`);
|
|
52975
|
+
}
|
|
52976
|
+
}
|
|
52977
|
+
} catch (error51) {
|
|
52978
|
+
const message = error51 instanceof Error ? error51.message : "Unknown error";
|
|
52979
|
+
console.error(chalk27.red("Failed to fetch versions"));
|
|
52980
|
+
console.error(chalk27.red(message));
|
|
52981
|
+
process.exit(1);
|
|
52982
|
+
}
|
|
52983
|
+
return;
|
|
52984
|
+
}
|
|
52985
|
+
const App = () => {
|
|
52986
|
+
const [loading, setLoading] = useState33(true);
|
|
52987
|
+
const [items, setItems] = useState33(null);
|
|
52988
|
+
const [publishedId, setPublishedId] = useState33(null);
|
|
52989
|
+
const [error51, setError] = useState33(null);
|
|
52990
|
+
useEffect30(() => {
|
|
52991
|
+
const run = async () => {
|
|
52992
|
+
try {
|
|
52993
|
+
const data = await client.get(`/agent-versions/${agentId}`);
|
|
52994
|
+
setItems(data.versions ?? []);
|
|
52995
|
+
setPublishedId(data.publishedVersionId ?? null);
|
|
52996
|
+
setLoading(false);
|
|
52997
|
+
} catch (err) {
|
|
52998
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
52999
|
+
setLoading(false);
|
|
53000
|
+
}
|
|
53001
|
+
};
|
|
53002
|
+
run();
|
|
53003
|
+
}, []);
|
|
53004
|
+
return React19.createElement(DataList, {
|
|
53005
|
+
title: `Versions for agent ${agentId}`,
|
|
53006
|
+
items,
|
|
53007
|
+
error: error51,
|
|
53008
|
+
loading,
|
|
53009
|
+
emptyMessage: "No versions found",
|
|
53010
|
+
renderCard: (item) => {
|
|
53011
|
+
const v = item;
|
|
53012
|
+
const liveTag = v.id === publishedId ? " [live]" : "";
|
|
53013
|
+
const versionLabel = v.label || (v.versionNumber !== void 0 ? `v${v.versionNumber}` : v.id);
|
|
53014
|
+
return React19.createElement(
|
|
53015
|
+
Text35,
|
|
53016
|
+
null,
|
|
53017
|
+
` ${v.id} ${versionLabel}${liveTag}${v.createdAt ? ` ${v.createdAt}` : ""}`
|
|
53018
|
+
);
|
|
53019
|
+
}
|
|
53020
|
+
});
|
|
53021
|
+
};
|
|
53022
|
+
const { waitUntilExit } = render19(React19.createElement(App));
|
|
53023
|
+
await waitUntilExit();
|
|
53024
|
+
});
|
|
53025
|
+
agentVersionsCommand.command("get <agentId> <versionId>").description("Get a specific version").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
|
|
53026
|
+
async (agentId, versionId, options) => {
|
|
53027
|
+
const apiKey = await ensureAuth();
|
|
53028
|
+
if (!apiKey) return;
|
|
53029
|
+
const client = new ApiClient(apiKey);
|
|
53030
|
+
if (!isTTY(options) || options.json) {
|
|
53031
|
+
try {
|
|
53032
|
+
const data = await client.get(`/agent-versions/${agentId}/${versionId}`);
|
|
53033
|
+
if (options.json) {
|
|
53034
|
+
printJson(data);
|
|
53035
|
+
} else {
|
|
53036
|
+
printDetail("Agent Version", [
|
|
53037
|
+
{ label: "ID", value: data.id },
|
|
53038
|
+
{ label: "Agent ID", value: data.agentId },
|
|
53039
|
+
{ label: "Version", value: data.versionNumber },
|
|
53040
|
+
{ label: "Type", value: data.versionType },
|
|
53041
|
+
{ label: "Label", value: data.label ?? void 0 },
|
|
53042
|
+
{ label: "Notes", value: data.notes ?? void 0 },
|
|
53043
|
+
{ label: "Created", value: data.createdAt }
|
|
53044
|
+
]);
|
|
53045
|
+
}
|
|
53046
|
+
} catch (error51) {
|
|
53047
|
+
const message = error51 instanceof Error ? error51.message : "Unknown error";
|
|
53048
|
+
console.error(chalk27.red("Failed to fetch version"));
|
|
53049
|
+
console.error(chalk27.red(message));
|
|
53050
|
+
process.exit(1);
|
|
53051
|
+
}
|
|
53052
|
+
return;
|
|
53053
|
+
}
|
|
53054
|
+
const App = () => {
|
|
53055
|
+
const [loading, setLoading] = useState33(true);
|
|
53056
|
+
const [success2, setSuccess] = useState33(null);
|
|
53057
|
+
const [error51, setError] = useState33(null);
|
|
53058
|
+
const [resultNode, setResultNode] = useState33(void 0);
|
|
53059
|
+
useEffect30(() => {
|
|
53060
|
+
const run = async () => {
|
|
53061
|
+
try {
|
|
53062
|
+
const data = await client.get(`/agent-versions/${agentId}/${versionId}`);
|
|
53063
|
+
setResultNode(
|
|
53064
|
+
React19.createElement(EntityCard, {
|
|
53065
|
+
fields: [
|
|
53066
|
+
{ label: "ID", value: data.id },
|
|
53067
|
+
{ label: "Agent ID", value: data.agentId },
|
|
53068
|
+
{ label: "Version", value: data.versionNumber },
|
|
53069
|
+
{ label: "Type", value: data.versionType },
|
|
53070
|
+
{ label: "Label", value: data.label ?? void 0 },
|
|
53071
|
+
{ label: "Notes", value: data.notes ?? void 0 },
|
|
53072
|
+
{ label: "Created", value: data.createdAt }
|
|
53073
|
+
]
|
|
53074
|
+
})
|
|
53075
|
+
);
|
|
53076
|
+
setSuccess(true);
|
|
53077
|
+
setLoading(false);
|
|
53078
|
+
} catch (err) {
|
|
53079
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
53080
|
+
setSuccess(false);
|
|
53081
|
+
setLoading(false);
|
|
53082
|
+
}
|
|
53083
|
+
};
|
|
53084
|
+
run();
|
|
53085
|
+
}, []);
|
|
53086
|
+
return React19.createElement(MutationResult, {
|
|
53087
|
+
loading,
|
|
53088
|
+
loadingLabel: "Fetching version...",
|
|
53089
|
+
success: success2,
|
|
53090
|
+
successMessage: "Agent Version",
|
|
53091
|
+
error: error51,
|
|
53092
|
+
result: resultNode
|
|
53093
|
+
});
|
|
53094
|
+
};
|
|
53095
|
+
const { waitUntilExit } = render19(React19.createElement(App));
|
|
53096
|
+
await waitUntilExit();
|
|
53097
|
+
}
|
|
53098
|
+
);
|
|
53099
|
+
agentVersionsCommand.command("published <agentId>").description("Get the published version for an agent").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (agentId, options) => {
|
|
53100
|
+
const apiKey = await ensureAuth();
|
|
53101
|
+
if (!apiKey) return;
|
|
53102
|
+
const client = new ApiClient(apiKey);
|
|
53103
|
+
if (!isTTY(options) || options.json) {
|
|
53104
|
+
try {
|
|
53105
|
+
const data = await client.get(`/agent-versions/${agentId}/published`);
|
|
53106
|
+
if (options.json) {
|
|
53107
|
+
printJson(data);
|
|
53108
|
+
} else {
|
|
53109
|
+
printDetail("Published Version", [
|
|
53110
|
+
{ label: "ID", value: data.id },
|
|
53111
|
+
{ label: "Version", value: data.versionNumber },
|
|
53112
|
+
{ label: "Label", value: data.label ?? void 0 },
|
|
53113
|
+
{ label: "Created", value: data.createdAt }
|
|
53114
|
+
]);
|
|
53115
|
+
}
|
|
53116
|
+
} catch (error51) {
|
|
53117
|
+
const message = error51 instanceof Error ? error51.message : "Unknown error";
|
|
53118
|
+
console.error(chalk27.red("Failed to fetch published version"));
|
|
53119
|
+
console.error(chalk27.red(message));
|
|
53120
|
+
process.exit(1);
|
|
53121
|
+
}
|
|
53122
|
+
return;
|
|
53123
|
+
}
|
|
53124
|
+
const App = () => {
|
|
53125
|
+
const [loading, setLoading] = useState33(true);
|
|
53126
|
+
const [success2, setSuccess] = useState33(null);
|
|
53127
|
+
const [error51, setError] = useState33(null);
|
|
53128
|
+
const [resultNode, setResultNode] = useState33(void 0);
|
|
53129
|
+
useEffect30(() => {
|
|
53130
|
+
const run = async () => {
|
|
53131
|
+
try {
|
|
53132
|
+
const data = await client.get(`/agent-versions/${agentId}/published`);
|
|
53133
|
+
setResultNode(
|
|
53134
|
+
React19.createElement(EntityCard, {
|
|
53135
|
+
fields: [
|
|
53136
|
+
{ label: "ID", value: data.id },
|
|
53137
|
+
{ label: "Version", value: data.versionNumber },
|
|
53138
|
+
{ label: "Label", value: data.label ?? void 0 },
|
|
53139
|
+
{ label: "Created", value: data.createdAt }
|
|
53140
|
+
]
|
|
53141
|
+
})
|
|
53142
|
+
);
|
|
53143
|
+
setSuccess(true);
|
|
53144
|
+
setLoading(false);
|
|
53145
|
+
} catch (err) {
|
|
53146
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
53147
|
+
setSuccess(false);
|
|
53148
|
+
setLoading(false);
|
|
53149
|
+
}
|
|
53150
|
+
};
|
|
53151
|
+
run();
|
|
53152
|
+
}, []);
|
|
53153
|
+
return React19.createElement(MutationResult, {
|
|
53154
|
+
loading,
|
|
53155
|
+
loadingLabel: "Fetching published version...",
|
|
53156
|
+
success: success2,
|
|
53157
|
+
successMessage: "Published Version",
|
|
53158
|
+
error: error51,
|
|
53159
|
+
result: resultNode
|
|
53160
|
+
});
|
|
53161
|
+
};
|
|
53162
|
+
const { waitUntilExit } = render19(React19.createElement(App));
|
|
53163
|
+
await waitUntilExit();
|
|
53164
|
+
});
|
|
53165
|
+
agentVersionsCommand.command("publish <agentId>").description("Publish a version").requiredOption("-v, --version <versionId>", "Version ID to publish").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
|
|
53166
|
+
async (agentId, options) => {
|
|
53167
|
+
const apiKey = await ensureAuth();
|
|
53168
|
+
if (!apiKey) return;
|
|
53169
|
+
const client = new ApiClient(apiKey);
|
|
53170
|
+
if (!isTTY(options)) {
|
|
53171
|
+
try {
|
|
53172
|
+
await client.post(`/agent-versions/${agentId}/publish`, {
|
|
53173
|
+
versionId: options.version
|
|
53174
|
+
});
|
|
53175
|
+
console.log(chalk27.green("Version published"));
|
|
53176
|
+
} catch (error51) {
|
|
53177
|
+
const message = error51 instanceof Error ? error51.message : "Unknown error";
|
|
53178
|
+
console.error(chalk27.red("Failed to publish version"));
|
|
53179
|
+
console.error(chalk27.red(message));
|
|
53180
|
+
process.exit(1);
|
|
53181
|
+
}
|
|
53182
|
+
return;
|
|
53183
|
+
}
|
|
53184
|
+
const App = () => {
|
|
53185
|
+
const [loading, setLoading] = useState33(true);
|
|
53186
|
+
const [success2, setSuccess] = useState33(null);
|
|
53187
|
+
const [error51, setError] = useState33(null);
|
|
53188
|
+
useEffect30(() => {
|
|
53189
|
+
const run = async () => {
|
|
53190
|
+
try {
|
|
53191
|
+
await client.post(`/agent-versions/${agentId}/publish`, {
|
|
53192
|
+
versionId: options.version
|
|
53193
|
+
});
|
|
53194
|
+
setSuccess(true);
|
|
53195
|
+
setLoading(false);
|
|
53196
|
+
} catch (err) {
|
|
53197
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
53198
|
+
setSuccess(false);
|
|
53199
|
+
setLoading(false);
|
|
53200
|
+
}
|
|
53201
|
+
};
|
|
53202
|
+
run();
|
|
53203
|
+
}, []);
|
|
53204
|
+
return React19.createElement(MutationResult, {
|
|
53205
|
+
loading,
|
|
53206
|
+
loadingLabel: "Publishing version...",
|
|
53207
|
+
success: success2,
|
|
53208
|
+
successMessage: "Version published",
|
|
53209
|
+
error: error51
|
|
53210
|
+
});
|
|
53211
|
+
};
|
|
53212
|
+
const { waitUntilExit } = render19(React19.createElement(App));
|
|
53213
|
+
await waitUntilExit();
|
|
53214
|
+
}
|
|
53215
|
+
);
|
|
53216
|
+
|
|
53217
|
+
// src/commands/tail.ts
|
|
53218
|
+
import { Command as Command22 } from "commander";
|
|
53219
|
+
import chalk28 from "chalk";
|
|
52668
53220
|
function abbreviateId(id) {
|
|
52669
53221
|
const underscoreIdx = id.lastIndexOf("_");
|
|
52670
53222
|
if (underscoreIdx === -1) {
|
|
@@ -52683,20 +53235,20 @@ function formatTime(ts) {
|
|
|
52683
53235
|
return `${hh}:${mm}:${ss}.${ms}`;
|
|
52684
53236
|
}
|
|
52685
53237
|
var LEVEL_COLORS = {
|
|
52686
|
-
debug:
|
|
52687
|
-
info:
|
|
52688
|
-
warn:
|
|
52689
|
-
error:
|
|
53238
|
+
debug: chalk28.gray,
|
|
53239
|
+
info: chalk28.blue,
|
|
53240
|
+
warn: chalk28.yellow,
|
|
53241
|
+
error: chalk28.red
|
|
52690
53242
|
};
|
|
52691
53243
|
function levelBadge(level, useColor) {
|
|
52692
53244
|
const tag = level.toUpperCase().padEnd(5);
|
|
52693
53245
|
if (!useColor) return `[${tag}]`;
|
|
52694
|
-
const colorFn = LEVEL_COLORS[level] ||
|
|
53246
|
+
const colorFn = LEVEL_COLORS[level] || chalk28.white;
|
|
52695
53247
|
return colorFn(`[${tag}]`);
|
|
52696
53248
|
}
|
|
52697
53249
|
function categoryBadge(category, useColor) {
|
|
52698
53250
|
if (!useColor) return `[${category}]`;
|
|
52699
|
-
return
|
|
53251
|
+
return chalk28.magenta(`[${category}]`);
|
|
52700
53252
|
}
|
|
52701
53253
|
function formatTailData(data) {
|
|
52702
53254
|
return Object.entries(data).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
|
|
@@ -52711,14 +53263,14 @@ function formatContextIds(event, useColor) {
|
|
|
52711
53263
|
if (event.conversationId) ids.push(`conv=${abbreviateId(event.conversationId)}`);
|
|
52712
53264
|
if (ids.length === 0) return "";
|
|
52713
53265
|
const text = ids.join(" ");
|
|
52714
|
-
return useColor ?
|
|
53266
|
+
return useColor ? chalk28.gray(` ${text}`) : ` ${text}`;
|
|
52715
53267
|
}
|
|
52716
53268
|
function formatEvent(event, useColor) {
|
|
52717
|
-
const time3 = useColor ?
|
|
53269
|
+
const time3 = useColor ? chalk28.gray(formatTime(event.timestamp)) : formatTime(event.timestamp);
|
|
52718
53270
|
const level = levelBadge(event.level, useColor);
|
|
52719
53271
|
const cat = categoryBadge(event.category, useColor);
|
|
52720
53272
|
const ctx = formatContextIds(event, useColor);
|
|
52721
|
-
const data = event.tailData && Object.keys(event.tailData).length > 0 ? useColor ?
|
|
53273
|
+
const data = event.tailData && Object.keys(event.tailData).length > 0 ? useColor ? chalk28.gray(` | ${formatTailData(event.tailData)}`) : ` | ${formatTailData(event.tailData)}` : "";
|
|
52722
53274
|
return `${time3} ${level} ${cat} ${event.message}${data}${ctx}`;
|
|
52723
53275
|
}
|
|
52724
53276
|
async function consumeSSEStream(reader, options, signal) {
|
|
@@ -52757,17 +53309,17 @@ async function consumeSSEStream(reader, options, signal) {
|
|
|
52757
53309
|
break;
|
|
52758
53310
|
case "tail_gap":
|
|
52759
53311
|
process.stderr.write(
|
|
52760
|
-
(useColor ?
|
|
53312
|
+
(useColor ? chalk28.yellow(`[warn] Dropped ${msg.droppedCount} event(s) between ${msg.fromTimestamp} and ${msg.toTimestamp}`) : `[warn] Dropped ${msg.droppedCount} event(s) between ${msg.fromTimestamp} and ${msg.toTimestamp}`) + "\n"
|
|
52761
53313
|
);
|
|
52762
53314
|
break;
|
|
52763
53315
|
case "tail_connected":
|
|
52764
53316
|
process.stderr.write(
|
|
52765
|
-
(useColor ?
|
|
53317
|
+
(useColor ? chalk28.green(`Connected to tail session ${msg.sessionId}`) : `Connected to tail session ${msg.sessionId}`) + "\n"
|
|
52766
53318
|
);
|
|
52767
53319
|
break;
|
|
52768
53320
|
case "tail_error":
|
|
52769
53321
|
process.stderr.write(
|
|
52770
|
-
(useColor ?
|
|
53322
|
+
(useColor ? chalk28.red(`[error] ${msg.error}`) : `[error] ${msg.error}`) + "\n"
|
|
52771
53323
|
);
|
|
52772
53324
|
break;
|
|
52773
53325
|
}
|
|
@@ -52847,7 +53399,7 @@ async function runTail(options) {
|
|
|
52847
53399
|
const useColor = options.color;
|
|
52848
53400
|
const activeFilters = Object.entries(filters).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${v}`);
|
|
52849
53401
|
process.stderr.write(
|
|
52850
|
-
(useColor ?
|
|
53402
|
+
(useColor ? chalk28.gray(`Connecting to ${apiUrl}...${activeFilters.length ? ` filters: ${activeFilters.join(", ")}` : ""}`) : `Connecting to ${apiUrl}...${activeFilters.length ? ` filters: ${activeFilters.join(", ")}` : ""}`) + "\n"
|
|
52851
53403
|
);
|
|
52852
53404
|
const controller = new AbortController();
|
|
52853
53405
|
let shuttingDown = false;
|
|
@@ -52855,7 +53407,7 @@ async function runTail(options) {
|
|
|
52855
53407
|
if (shuttingDown) return;
|
|
52856
53408
|
shuttingDown = true;
|
|
52857
53409
|
process.stderr.write(
|
|
52858
|
-
(useColor ?
|
|
53410
|
+
(useColor ? chalk28.gray("\nDisconnecting...") : "\nDisconnecting...") + "\n"
|
|
52859
53411
|
);
|
|
52860
53412
|
controller.abort();
|
|
52861
53413
|
};
|
|
@@ -52869,7 +53421,7 @@ async function runTail(options) {
|
|
|
52869
53421
|
const result = await connectAndStream(session.sseUrl, apiKey, options, controller.signal);
|
|
52870
53422
|
if (result === "aborted" || shuttingDown) break;
|
|
52871
53423
|
process.stderr.write(
|
|
52872
|
-
(useColor ?
|
|
53424
|
+
(useColor ? chalk28.yellow("Stream ended, reconnecting...") : "Stream ended, reconnecting...") + "\n"
|
|
52873
53425
|
);
|
|
52874
53426
|
} catch (err) {
|
|
52875
53427
|
if (shuttingDown || controller.signal.aborted) break;
|
|
@@ -52877,22 +53429,22 @@ async function runTail(options) {
|
|
|
52877
53429
|
const delay = Math.min(BASE_DELAY_MS * Math.pow(2, attempt - 1), MAX_DELAY_MS);
|
|
52878
53430
|
const message = err instanceof Error ? err.message : String(err);
|
|
52879
53431
|
process.stderr.write(
|
|
52880
|
-
(useColor ?
|
|
53432
|
+
(useColor ? chalk28.red(`Connection error: ${message}`) : `Connection error: ${message}`) + "\n"
|
|
52881
53433
|
);
|
|
52882
53434
|
if (attempt >= MAX_ATTEMPTS) {
|
|
52883
53435
|
process.stderr.write(
|
|
52884
|
-
(useColor ?
|
|
53436
|
+
(useColor ? chalk28.red(`Max reconnect attempts (${MAX_ATTEMPTS}) reached. Exiting.`) : `Max reconnect attempts (${MAX_ATTEMPTS}) reached. Exiting.`) + "\n"
|
|
52885
53437
|
);
|
|
52886
53438
|
process.exit(1);
|
|
52887
53439
|
}
|
|
52888
53440
|
process.stderr.write(
|
|
52889
|
-
(useColor ?
|
|
53441
|
+
(useColor ? chalk28.gray(`Retrying in ${delay / 1e3}s (attempt ${attempt}/${MAX_ATTEMPTS})...`) : `Retrying in ${delay / 1e3}s (attempt ${attempt}/${MAX_ATTEMPTS})...`) + "\n"
|
|
52890
53442
|
);
|
|
52891
|
-
await new Promise((
|
|
52892
|
-
const timer = setTimeout(
|
|
53443
|
+
await new Promise((resolve10) => {
|
|
53444
|
+
const timer = setTimeout(resolve10, delay);
|
|
52893
53445
|
const onAbort = () => {
|
|
52894
53446
|
clearTimeout(timer);
|
|
52895
|
-
|
|
53447
|
+
resolve10();
|
|
52896
53448
|
};
|
|
52897
53449
|
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
52898
53450
|
});
|
|
@@ -52901,16 +53453,16 @@ async function runTail(options) {
|
|
|
52901
53453
|
process.removeListener("SIGINT", shutdown);
|
|
52902
53454
|
process.removeListener("SIGTERM", shutdown);
|
|
52903
53455
|
}
|
|
52904
|
-
var tailCommand = new
|
|
53456
|
+
var tailCommand = new Command22("tail").description("Stream live execution logs from the Runtype API").option("--flow <id>", "Filter by flow ID").option("--agent <id>", "Filter by agent ID").option("--surface <id>", "Filter by surface ID").option("--execution <id>", "Filter by execution ID").option("--level <level>", "Filter by level (debug/info/warn/error)").option("--category <category>", "Filter by category (execution/agent/tool/model/system/error)").option("--json", "Output raw JSON (one object per line)").option("--no-color", "Disable color output").action(async (options) => {
|
|
52905
53457
|
await runTail(options);
|
|
52906
53458
|
});
|
|
52907
53459
|
|
|
52908
53460
|
// src/commands/validate-product.ts
|
|
52909
|
-
import { Command as
|
|
52910
|
-
import
|
|
53461
|
+
import { Command as Command23, Option } from "commander";
|
|
53462
|
+
import chalk29 from "chalk";
|
|
52911
53463
|
import { readFileSync as readFileSync15 } from "fs";
|
|
52912
53464
|
function createValidateProductCommand() {
|
|
52913
|
-
return new
|
|
53465
|
+
return new Command23("validate-product").description("Validate a product (FPO) or FPO template locally (no API call)").argument(
|
|
52914
53466
|
"[input]",
|
|
52915
53467
|
'Path to JSON file, raw JSON string (starts with "{"), or "-" for stdin'
|
|
52916
53468
|
).option("--template", "Force FPO template validation").option("--fpo", "Force FPO (non-template) validation").addOption(
|
|
@@ -52934,7 +53486,7 @@ var validateProductCommand = createValidateProductCommand();
|
|
|
52934
53486
|
async function runValidateAction(input, _options) {
|
|
52935
53487
|
const options = this.optsWithGlobals();
|
|
52936
53488
|
if (options.template && options.fpo) {
|
|
52937
|
-
console.error(
|
|
53489
|
+
console.error(chalk29.red("Error: --template and --fpo are mutually exclusive"));
|
|
52938
53490
|
process.exit(1);
|
|
52939
53491
|
}
|
|
52940
53492
|
let raw;
|
|
@@ -52942,7 +53494,7 @@ async function runValidateAction(input, _options) {
|
|
|
52942
53494
|
raw = await readInput(input);
|
|
52943
53495
|
} catch (err) {
|
|
52944
53496
|
const message = err instanceof Error ? err.message : String(err);
|
|
52945
|
-
console.error(
|
|
53497
|
+
console.error(chalk29.red(`Failed to read input: ${message}`));
|
|
52946
53498
|
process.exit(1);
|
|
52947
53499
|
return;
|
|
52948
53500
|
}
|
|
@@ -52951,7 +53503,7 @@ async function runValidateAction(input, _options) {
|
|
|
52951
53503
|
parsed = JSON.parse(raw);
|
|
52952
53504
|
} catch (err) {
|
|
52953
53505
|
const message = err instanceof Error ? err.message : String(err);
|
|
52954
|
-
console.error(
|
|
53506
|
+
console.error(chalk29.red(`Invalid JSON: ${message}`));
|
|
52955
53507
|
process.exit(1);
|
|
52956
53508
|
return;
|
|
52957
53509
|
}
|
|
@@ -53041,16 +53593,16 @@ function runValidation(body, kind) {
|
|
|
53041
53593
|
function printHumanResult(kind, result) {
|
|
53042
53594
|
const label = kind === "template" ? "FPO template" : "FPO";
|
|
53043
53595
|
const overallValid = !hasAnyErrors(result);
|
|
53044
|
-
const headline = overallValid ?
|
|
53596
|
+
const headline = overallValid ? chalk29.green(`\u2713 Valid ${label}`) : chalk29.red(`\u2717 Invalid ${label}`);
|
|
53045
53597
|
console.log(headline);
|
|
53046
53598
|
console.log(
|
|
53047
|
-
|
|
53599
|
+
chalk29.gray(
|
|
53048
53600
|
` ${result.errors.length} error(s), ${result.warnings.length} warning(s), ${result.recommendations.length} recommendation(s)`
|
|
53049
53601
|
)
|
|
53050
53602
|
);
|
|
53051
|
-
printIssues("Errors", result.errors,
|
|
53052
|
-
printIssues("Warnings", result.warnings,
|
|
53053
|
-
printIssues("Recommendations", result.recommendations,
|
|
53603
|
+
printIssues("Errors", result.errors, chalk29.red);
|
|
53604
|
+
printIssues("Warnings", result.warnings, chalk29.yellow);
|
|
53605
|
+
printIssues("Recommendations", result.recommendations, chalk29.blue);
|
|
53054
53606
|
if (result.kind === "template") {
|
|
53055
53607
|
const defaults = result.defaultsValidation;
|
|
53056
53608
|
const structuralErrors = defaults.errors.filter(
|
|
@@ -53062,22 +53614,22 @@ function printHumanResult(kind, result) {
|
|
|
53062
53614
|
if (structuralErrors.length > 0) {
|
|
53063
53615
|
console.log();
|
|
53064
53616
|
console.log(
|
|
53065
|
-
|
|
53617
|
+
chalk29.red(
|
|
53066
53618
|
`Defaults validation: template defaults do not produce a valid FPO`
|
|
53067
53619
|
)
|
|
53068
53620
|
);
|
|
53069
|
-
printIssues("Default-resolution errors", structuralErrors,
|
|
53070
|
-
printIssues("Default-resolution warnings", defaults.warnings,
|
|
53621
|
+
printIssues("Default-resolution errors", structuralErrors, chalk29.red);
|
|
53622
|
+
printIssues("Default-resolution warnings", defaults.warnings, chalk29.yellow);
|
|
53071
53623
|
}
|
|
53072
53624
|
if (missingVars.length > 0) {
|
|
53073
53625
|
console.log();
|
|
53074
53626
|
console.log(
|
|
53075
|
-
|
|
53627
|
+
chalk29.gray(
|
|
53076
53628
|
`Template variables needing deploy-time values (${missingVars.length}):`
|
|
53077
53629
|
)
|
|
53078
53630
|
);
|
|
53079
53631
|
for (const issue2 of missingVars) {
|
|
53080
|
-
console.log(
|
|
53632
|
+
console.log(chalk29.gray(` \u2022 ${issue2.path} \u2014 ${issue2.message}`));
|
|
53081
53633
|
}
|
|
53082
53634
|
}
|
|
53083
53635
|
}
|
|
@@ -53087,19 +53639,515 @@ function printIssues(title, issues, color) {
|
|
|
53087
53639
|
console.log();
|
|
53088
53640
|
console.log(color(`${title}:`));
|
|
53089
53641
|
for (const issue2 of issues) {
|
|
53090
|
-
const pathLabel = issue2.path ?
|
|
53091
|
-
console.log(` ${color("\u2022")} ${
|
|
53642
|
+
const pathLabel = issue2.path ? chalk29.gray(` [${issue2.path}]`) : "";
|
|
53643
|
+
console.log(` ${color("\u2022")} ${chalk29.bold(issue2.code)}${pathLabel} ${issue2.message}`);
|
|
53092
53644
|
if (issue2.suggestedFix) {
|
|
53093
|
-
console.log(` ${
|
|
53645
|
+
console.log(` ${chalk29.gray("fix:")} ${issue2.suggestedFix}`);
|
|
53646
|
+
}
|
|
53647
|
+
}
|
|
53648
|
+
}
|
|
53649
|
+
|
|
53650
|
+
// src/commands/deploy.ts
|
|
53651
|
+
import { Command as Command24 } from "commander";
|
|
53652
|
+
import chalk30 from "chalk";
|
|
53653
|
+
import * as fs14 from "fs";
|
|
53654
|
+
import * as path14 from "path";
|
|
53655
|
+
function bashSingleQuote(s) {
|
|
53656
|
+
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
53657
|
+
}
|
|
53658
|
+
function serverTs() {
|
|
53659
|
+
return `/**
|
|
53660
|
+
* Generated by \`runtype deploy\`.
|
|
53661
|
+
*
|
|
53662
|
+
* Boots a Hono server that loads every agent JSON file under ./agents/ and
|
|
53663
|
+
* registers a streaming POST /agent/:name endpoint for each.
|
|
53664
|
+
*
|
|
53665
|
+
* See README.md for startup and deploy instructions.
|
|
53666
|
+
*/
|
|
53667
|
+
import { readFile, readdir } from 'node:fs/promises'
|
|
53668
|
+
import { resolve } from 'node:path'
|
|
53669
|
+
import { Hono } from 'hono'
|
|
53670
|
+
import { cors } from 'hono/cors'
|
|
53671
|
+
import { serve } from '@hono/node-server'
|
|
53672
|
+
import {
|
|
53673
|
+
CloudRunAdapter,
|
|
53674
|
+
createRuntime,
|
|
53675
|
+
exportedAgentSchema,
|
|
53676
|
+
type ExportedAgent,
|
|
53677
|
+
} from '@runtypelabs/runtime'
|
|
53678
|
+
|
|
53679
|
+
async function loadAgent(filePath: string): Promise<ExportedAgent> {
|
|
53680
|
+
const raw = await readFile(filePath, 'utf-8')
|
|
53681
|
+
return exportedAgentSchema.parse(JSON.parse(raw))
|
|
53682
|
+
}
|
|
53683
|
+
|
|
53684
|
+
async function loadAgentsDir(dir: string): Promise<Record<string, ExportedAgent>> {
|
|
53685
|
+
let entries: string[]
|
|
53686
|
+
try {
|
|
53687
|
+
entries = await readdir(dir)
|
|
53688
|
+
} catch (err) {
|
|
53689
|
+
throw new Error(
|
|
53690
|
+
\`[runtype] could not read agents directory at \${dir}: \${err instanceof Error ? err.message : String(err)}\`
|
|
53691
|
+
)
|
|
53692
|
+
}
|
|
53693
|
+
const jsonFiles = entries.filter((f) => f.endsWith('.json')).sort()
|
|
53694
|
+
if (jsonFiles.length === 0) {
|
|
53695
|
+
throw new Error(\`[runtype] no agents found in \${dir} (expected one or more *.json files)\`)
|
|
53696
|
+
}
|
|
53697
|
+
|
|
53698
|
+
const agents: Record<string, ExportedAgent> = {}
|
|
53699
|
+
for (const file of jsonFiles) {
|
|
53700
|
+
const agent = await loadAgent(resolve(dir, file))
|
|
53701
|
+
if (agents[agent.name]) {
|
|
53702
|
+
throw new Error(
|
|
53703
|
+
\`[runtype] duplicate agent name "\${agent.name}" in \${file} \u2014 already defined by an earlier file\`
|
|
53704
|
+
)
|
|
53094
53705
|
}
|
|
53706
|
+
agents[agent.name] = agent
|
|
53707
|
+
console.log(\`[runtype] loaded agent id=\${agent.id} name=\${agent.name}\`)
|
|
53095
53708
|
}
|
|
53709
|
+
return agents
|
|
53710
|
+
}
|
|
53711
|
+
|
|
53712
|
+
async function main(): Promise<void> {
|
|
53713
|
+
const agentsDir = resolve(process.cwd(), 'agents')
|
|
53714
|
+
const agents = await loadAgentsDir(agentsDir)
|
|
53715
|
+
|
|
53716
|
+
const runtime = createRuntime({
|
|
53717
|
+
agents,
|
|
53718
|
+
keys: { mode: 'own' },
|
|
53719
|
+
adapter: new CloudRunAdapter(),
|
|
53720
|
+
})
|
|
53721
|
+
|
|
53722
|
+
const app = new Hono()
|
|
53723
|
+
|
|
53724
|
+
const allowedOriginsEnv = process.env.ALLOWED_ORIGINS?.trim()
|
|
53725
|
+
const allowedOrigins = allowedOriginsEnv
|
|
53726
|
+
? allowedOriginsEnv.split(',').map((o) => o.trim()).filter(Boolean)
|
|
53727
|
+
: '*'
|
|
53728
|
+
app.use(
|
|
53729
|
+
'*',
|
|
53730
|
+
cors({
|
|
53731
|
+
origin: allowedOrigins,
|
|
53732
|
+
allowMethods: ['GET', 'POST', 'OPTIONS'],
|
|
53733
|
+
allowHeaders: ['Content-Type', 'Authorization'],
|
|
53734
|
+
credentials: false,
|
|
53735
|
+
maxAge: 86400,
|
|
53736
|
+
})
|
|
53737
|
+
)
|
|
53738
|
+
|
|
53739
|
+
app.get('/health', (c) => c.json({ status: 'ok', agents: Object.keys(agents) }))
|
|
53740
|
+
|
|
53741
|
+
app.post('/agent/:name', async (c) => {
|
|
53742
|
+
const name = c.req.param('name')
|
|
53743
|
+
if (!runtime.getAgent(name)) {
|
|
53744
|
+
return c.json({ error: \`unknown agent: \${name}\` }, 404)
|
|
53745
|
+
}
|
|
53746
|
+
|
|
53747
|
+
let body: { messages?: Array<{ role: string; content: string }> } = {}
|
|
53748
|
+
try {
|
|
53749
|
+
body = (await c.req.json()) as typeof body
|
|
53750
|
+
} catch {
|
|
53751
|
+
return c.json({ error: 'request body must be JSON' }, 400)
|
|
53752
|
+
}
|
|
53753
|
+
const messages = Array.isArray(body.messages) ? body.messages : []
|
|
53754
|
+
|
|
53755
|
+
try {
|
|
53756
|
+
const response = await runtime.executeAgent(name, {
|
|
53757
|
+
messages: messages as Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,
|
|
53758
|
+
signal: c.req.raw.signal,
|
|
53759
|
+
})
|
|
53760
|
+
return response
|
|
53761
|
+
} catch (err) {
|
|
53762
|
+
return c.json({ error: err instanceof Error ? err.message : 'unknown error' }, 500)
|
|
53763
|
+
}
|
|
53764
|
+
})
|
|
53765
|
+
|
|
53766
|
+
const port = Number(process.env.PORT ?? 8080)
|
|
53767
|
+
serve({ fetch: app.fetch, port, hostname: '0.0.0.0' })
|
|
53768
|
+
console.log(\`[runtype] listening on 0.0.0.0:\${port} \u2014 agents: \${Object.keys(agents).join(', ')}\`)
|
|
53769
|
+
}
|
|
53770
|
+
|
|
53771
|
+
main().catch((err) => {
|
|
53772
|
+
console.error('[runtype] fatal: failed to start server', err)
|
|
53773
|
+
process.exit(1)
|
|
53774
|
+
})
|
|
53775
|
+
`;
|
|
53096
53776
|
}
|
|
53777
|
+
function dockerfile() {
|
|
53778
|
+
return `FROM node:22-bookworm-slim AS builder
|
|
53779
|
+
|
|
53780
|
+
WORKDIR /app
|
|
53781
|
+
|
|
53782
|
+
COPY package.json ./
|
|
53783
|
+
COPY packages ./packages
|
|
53784
|
+
RUN npm install --omit=dev --no-audit --no-fund
|
|
53785
|
+
|
|
53786
|
+
COPY tsconfig.json server.ts ./
|
|
53787
|
+
COPY agents ./agents
|
|
53788
|
+
RUN npm install --no-save --no-audit --no-fund typescript @types/node \\
|
|
53789
|
+
&& npx tsc -p tsconfig.json
|
|
53790
|
+
|
|
53791
|
+
FROM node:22-bookworm-slim AS runner
|
|
53792
|
+
|
|
53793
|
+
WORKDIR /app
|
|
53794
|
+
ENV NODE_ENV=production
|
|
53795
|
+
ENV PORT=8080
|
|
53796
|
+
EXPOSE 8080
|
|
53797
|
+
|
|
53798
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
53799
|
+
COPY --from=builder /app/dist ./dist
|
|
53800
|
+
COPY --from=builder /app/agents ./agents
|
|
53801
|
+
COPY --from=builder /app/package.json ./package.json
|
|
53802
|
+
|
|
53803
|
+
CMD ["node", "dist/server.js"]
|
|
53804
|
+
`;
|
|
53805
|
+
}
|
|
53806
|
+
function dockerignore() {
|
|
53807
|
+
return `node_modules
|
|
53808
|
+
dist
|
|
53809
|
+
*.log
|
|
53810
|
+
`;
|
|
53811
|
+
}
|
|
53812
|
+
function tsconfigJson() {
|
|
53813
|
+
return JSON.stringify(
|
|
53814
|
+
{
|
|
53815
|
+
compilerOptions: {
|
|
53816
|
+
target: "ES2022",
|
|
53817
|
+
module: "ESNext",
|
|
53818
|
+
moduleResolution: "bundler",
|
|
53819
|
+
lib: ["ES2022", "DOM"],
|
|
53820
|
+
strict: true,
|
|
53821
|
+
esModuleInterop: true,
|
|
53822
|
+
forceConsistentCasingInFileNames: true,
|
|
53823
|
+
resolveJsonModule: true,
|
|
53824
|
+
skipLibCheck: true,
|
|
53825
|
+
outDir: "dist",
|
|
53826
|
+
declaration: false,
|
|
53827
|
+
sourceMap: true,
|
|
53828
|
+
noEmit: false
|
|
53829
|
+
},
|
|
53830
|
+
include: ["*.ts"],
|
|
53831
|
+
exclude: ["node_modules", "dist"]
|
|
53832
|
+
},
|
|
53833
|
+
null,
|
|
53834
|
+
2
|
|
53835
|
+
);
|
|
53836
|
+
}
|
|
53837
|
+
function packageJson(name, runtimeDep) {
|
|
53838
|
+
return JSON.stringify(
|
|
53839
|
+
{
|
|
53840
|
+
name,
|
|
53841
|
+
version: "0.0.0",
|
|
53842
|
+
private: true,
|
|
53843
|
+
type: "module",
|
|
53844
|
+
scripts: {
|
|
53845
|
+
start: "node dist/server.js",
|
|
53846
|
+
dev: "tsx server.ts",
|
|
53847
|
+
build: "tsc -p tsconfig.json",
|
|
53848
|
+
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
53849
|
+
},
|
|
53850
|
+
dependencies: {
|
|
53851
|
+
"@hono/node-server": "^2.0.0",
|
|
53852
|
+
"@runtypelabs/runtime": runtimeDep,
|
|
53853
|
+
hono: "^4.12.16"
|
|
53854
|
+
},
|
|
53855
|
+
devDependencies: {
|
|
53856
|
+
"@types/node": "^22.10.5",
|
|
53857
|
+
tsx: "^4.19.2",
|
|
53858
|
+
typescript: "^5.3.3"
|
|
53859
|
+
},
|
|
53860
|
+
engines: {
|
|
53861
|
+
node: ">=22.0.0"
|
|
53862
|
+
}
|
|
53863
|
+
},
|
|
53864
|
+
null,
|
|
53865
|
+
2
|
|
53866
|
+
);
|
|
53867
|
+
}
|
|
53868
|
+
function setupSh(monorepoRoot) {
|
|
53869
|
+
return `#!/usr/bin/env bash
|
|
53870
|
+
# Generated by \`runtype deploy\`.
|
|
53871
|
+
#
|
|
53872
|
+
# Builds and packs @runtypelabs/runtime from your local monorepo, then
|
|
53873
|
+
# installs all dependencies so you can run \`npm start\` or deploy to
|
|
53874
|
+
# Cloud Run with \`gcloud run deploy --source .\`.
|
|
53875
|
+
#
|
|
53876
|
+
# Usage (from this directory):
|
|
53877
|
+
# ./setup.sh
|
|
53878
|
+
# # then: npm run dev OR gcloud run deploy \u2026
|
|
53879
|
+
|
|
53880
|
+
set -euo pipefail
|
|
53881
|
+
|
|
53882
|
+
DEPLOY_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
|
53883
|
+
MONOREPO_ROOT=${bashSingleQuote(monorepoRoot)}
|
|
53884
|
+
TARBALL_DIR="\${DEPLOY_DIR}/packages"
|
|
53885
|
+
|
|
53886
|
+
echo "[setup] building @runtypelabs/runtime..."
|
|
53887
|
+
pnpm --dir "\${MONOREPO_ROOT}" --filter @runtypelabs/runtime build
|
|
53888
|
+
|
|
53889
|
+
mkdir -p "\${TARBALL_DIR}"
|
|
53890
|
+
|
|
53891
|
+
echo "[setup] packing @runtypelabs/runtime tarball..."
|
|
53892
|
+
pnpm --dir "\${MONOREPO_ROOT}/packages/runtime" pack \\
|
|
53893
|
+
--pack-destination "\${TARBALL_DIR}"
|
|
53894
|
+
|
|
53895
|
+
RUNTIME_TGZ="$(ls "\${TARBALL_DIR}"/runtypelabs-runtime-*.tgz | head -n 1)"
|
|
53896
|
+
if [ -z "\${RUNTIME_TGZ}" ]; then
|
|
53897
|
+
echo "[setup] error: no tarball produced by pnpm pack" >&2
|
|
53898
|
+
exit 1
|
|
53899
|
+
fi
|
|
53900
|
+
RUNTIME_TGZ_NAME="$(basename "\${RUNTIME_TGZ}")"
|
|
53901
|
+
|
|
53902
|
+
echo "[setup] updating package.json with file: dependency..."
|
|
53903
|
+
node -e "
|
|
53904
|
+
const fs = require('fs');
|
|
53905
|
+
const pkg = JSON.parse(fs.readFileSync('\${DEPLOY_DIR}/package.json', 'utf8'));
|
|
53906
|
+
pkg.dependencies['@runtypelabs/runtime'] = 'file:./packages/\${RUNTIME_TGZ_NAME}';
|
|
53907
|
+
fs.writeFileSync('\${DEPLOY_DIR}/package.json', JSON.stringify(pkg, null, 2) + '\\\\n');
|
|
53908
|
+
"
|
|
53909
|
+
|
|
53910
|
+
echo "[setup] installing dependencies..."
|
|
53911
|
+
npm install --no-audit --no-fund
|
|
53912
|
+
|
|
53913
|
+
echo ""
|
|
53914
|
+
echo "[setup] Done! Next steps:"
|
|
53915
|
+
echo " npm run dev \u2014 start locally"
|
|
53916
|
+
echo " npm run build \u2014 compile TypeScript"
|
|
53917
|
+
echo " gcloud run deploy --source . --region us-central1 --allow-unauthenticated --port 8080"
|
|
53918
|
+
`;
|
|
53919
|
+
}
|
|
53920
|
+
function readme(agentNames, secretNames) {
|
|
53921
|
+
const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
|
|
53922
|
+
const secretList = secretNames.length > 0 ? secretNames.map((s) => ` gcloud secrets create ${s} --data-file=-`).join("\n") : " (none detected)";
|
|
53923
|
+
return `# Runtype Deployment
|
|
53924
|
+
|
|
53925
|
+
Generated by \`runtype deploy\`. Contains the following agents:
|
|
53926
|
+
|
|
53927
|
+
${agentList}
|
|
53928
|
+
|
|
53929
|
+
## Setup
|
|
53930
|
+
|
|
53931
|
+
Run \`./setup.sh\` to build the runtime and install dependencies:
|
|
53932
|
+
|
|
53933
|
+
\`\`\`bash
|
|
53934
|
+
chmod +x setup.sh
|
|
53935
|
+
./setup.sh
|
|
53936
|
+
\`\`\`
|
|
53937
|
+
|
|
53938
|
+
## Local development
|
|
53939
|
+
|
|
53940
|
+
\`\`\`bash
|
|
53941
|
+
npm run dev
|
|
53942
|
+
\`\`\`
|
|
53943
|
+
|
|
53944
|
+
Test with:
|
|
53945
|
+
\`\`\`bash
|
|
53946
|
+
curl -X POST http://localhost:8080/agent/${agentNames[0] ?? "my-agent"} \\
|
|
53947
|
+
-H "Content-Type: application/json" \\
|
|
53948
|
+
-d '{"messages":[{"role":"user","content":"Hello!"}]}'
|
|
53949
|
+
\`\`\`
|
|
53950
|
+
|
|
53951
|
+
## Required secrets
|
|
53952
|
+
|
|
53953
|
+
Set these before deploying to Cloud Run:
|
|
53954
|
+
|
|
53955
|
+
${secretList}
|
|
53956
|
+
|
|
53957
|
+
## Deploy to Cloud Run
|
|
53958
|
+
|
|
53959
|
+
\`\`\`bash
|
|
53960
|
+
gcloud run deploy runtype-deploy \\
|
|
53961
|
+
--source . \\
|
|
53962
|
+
--region us-central1 \\
|
|
53963
|
+
--platform managed \\
|
|
53964
|
+
--allow-unauthenticated \\
|
|
53965
|
+
--port 8080
|
|
53966
|
+
\`\`\`
|
|
53967
|
+
|
|
53968
|
+
## Health check
|
|
53969
|
+
|
|
53970
|
+
\`GET /health\` returns \`{"status":"ok","agents":[...]}\`.
|
|
53971
|
+
`;
|
|
53972
|
+
}
|
|
53973
|
+
function collectSecretNames(agentDef) {
|
|
53974
|
+
const names = /* @__PURE__ */ new Set();
|
|
53975
|
+
const model = agentDef.config?.model?.toLowerCase();
|
|
53976
|
+
if (model) {
|
|
53977
|
+
for (const s of resolveModelSecretNames(model)) names.add(s);
|
|
53978
|
+
}
|
|
53979
|
+
const toolsCfg = agentDef.config?.tools;
|
|
53980
|
+
const mcpServers = toolsCfg?.mcpServers;
|
|
53981
|
+
if (mcpServers) {
|
|
53982
|
+
for (const srv of mcpServers) {
|
|
53983
|
+
const auth = srv.auth;
|
|
53984
|
+
if (auth?.tokenSecretName) names.add(String(auth.tokenSecretName));
|
|
53985
|
+
if (auth?.usernameSecretName) names.add(String(auth.usernameSecretName));
|
|
53986
|
+
if (auth?.passwordSecretName) names.add(String(auth.passwordSecretName));
|
|
53987
|
+
}
|
|
53988
|
+
}
|
|
53989
|
+
for (const s of extractSecretReferencesFromAnyValue(agentDef)) names.add(s);
|
|
53990
|
+
return Array.from(names);
|
|
53991
|
+
}
|
|
53992
|
+
function slugify2(s) {
|
|
53993
|
+
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
|
|
53994
|
+
}
|
|
53995
|
+
var deployCommand = new Command24("deploy").description("Export an agent or flow and scaffold a Cloud Run deployment").option("--agent <id>", "Agent ID to export (may be repeated)", (v, acc) => {
|
|
53996
|
+
acc.push(v);
|
|
53997
|
+
return acc;
|
|
53998
|
+
}, []).option("--flow <id>", "Flow ID to export (may be repeated)", (v, acc) => {
|
|
53999
|
+
acc.push(v);
|
|
54000
|
+
return acc;
|
|
54001
|
+
}, []).option("--output <dir>", "Output directory for the scaffold (default: ./runtype-deploy)", "./runtype-deploy").option("--name <name>", "Project name used in package.json (default: derived from output dir)").action(
|
|
54002
|
+
async (options) => {
|
|
54003
|
+
const agentIds = options.agent;
|
|
54004
|
+
const flowIds = options.flow;
|
|
54005
|
+
if (agentIds.length === 0 && flowIds.length === 0) {
|
|
54006
|
+
console.error(chalk30.red("Error: provide at least one --agent <id> or --flow <id>"));
|
|
54007
|
+
process.exit(1);
|
|
54008
|
+
}
|
|
54009
|
+
const apiKey = await ensureAuth();
|
|
54010
|
+
if (!apiKey) return;
|
|
54011
|
+
const client = new ApiClient(apiKey);
|
|
54012
|
+
const outDir = path14.resolve(options.output);
|
|
54013
|
+
const projectName = options.name ?? slugify2(path14.basename(outDir));
|
|
54014
|
+
console.log(chalk30.cyan(`
|
|
54015
|
+
Scaffolding deployment to ${outDir}
|
|
54016
|
+
`));
|
|
54017
|
+
const agentDefs = [];
|
|
54018
|
+
for (const id of agentIds) {
|
|
54019
|
+
process.stdout.write(` Exporting agent ${chalk30.green(id)}... `);
|
|
54020
|
+
try {
|
|
54021
|
+
const def = await client.get(`/agents/${id}/export-runtime`);
|
|
54022
|
+
agentDefs.push({ id, name: String(def.name ?? id), def });
|
|
54023
|
+
process.stdout.write(chalk30.green("\u2713\n"));
|
|
54024
|
+
} catch (err) {
|
|
54025
|
+
const msg = err instanceof ApiError ? err.message : String(err);
|
|
54026
|
+
process.stdout.write(chalk30.red(`\u2717
|
|
54027
|
+
`));
|
|
54028
|
+
console.error(chalk30.red(` Failed to export agent ${id}: ${msg}`));
|
|
54029
|
+
if (err instanceof ApiError && err.statusCode === 404) {
|
|
54030
|
+
console.error(chalk30.yellow(" The export-runtime feature may not be enabled on your account or environment."));
|
|
54031
|
+
console.error(chalk30.gray(" If you have your own environment, try: RUNTYPE_API_URL={API Base URI} runtype deploy ..."));
|
|
54032
|
+
}
|
|
54033
|
+
process.exit(1);
|
|
54034
|
+
}
|
|
54035
|
+
}
|
|
54036
|
+
for (const id of flowIds) {
|
|
54037
|
+
process.stdout.write(` Exporting flow ${chalk30.green(id)}... `);
|
|
54038
|
+
try {
|
|
54039
|
+
const def = await client.get(`/flows/${id}/export-runtime`);
|
|
54040
|
+
const wrappedName = String(def.name ?? id);
|
|
54041
|
+
agentDefs.push({
|
|
54042
|
+
id,
|
|
54043
|
+
name: wrappedName,
|
|
54044
|
+
def: {
|
|
54045
|
+
id: def.id,
|
|
54046
|
+
name: wrappedName,
|
|
54047
|
+
description: def.description ?? null,
|
|
54048
|
+
agentType: "runtype",
|
|
54049
|
+
config: {},
|
|
54050
|
+
primaryFlow: def
|
|
54051
|
+
}
|
|
54052
|
+
});
|
|
54053
|
+
process.stdout.write(chalk30.green("\u2713\n"));
|
|
54054
|
+
} catch (err) {
|
|
54055
|
+
const msg = err instanceof ApiError ? err.message : String(err);
|
|
54056
|
+
process.stdout.write(chalk30.red(`\u2717
|
|
54057
|
+
`));
|
|
54058
|
+
console.error(chalk30.red(` Failed to export flow ${id}: ${msg}`));
|
|
54059
|
+
if (err instanceof ApiError && err.statusCode === 404) {
|
|
54060
|
+
console.error(chalk30.yellow(" The export-runtime feature may not be enabled on your account or environment."));
|
|
54061
|
+
console.error(chalk30.gray(" If you have your own environment, try: RUNTYPE_API_URL={API Base URI} runtype deploy ..."));
|
|
54062
|
+
}
|
|
54063
|
+
process.exit(1);
|
|
54064
|
+
}
|
|
54065
|
+
}
|
|
54066
|
+
fs14.mkdirSync(path14.join(outDir, "agents"), { recursive: true });
|
|
54067
|
+
fs14.mkdirSync(path14.join(outDir, "packages"), { recursive: true });
|
|
54068
|
+
for (const { name, def } of agentDefs) {
|
|
54069
|
+
const filename = `${slugify2(name)}.json`;
|
|
54070
|
+
fs14.writeFileSync(
|
|
54071
|
+
path14.join(outDir, "agents", filename),
|
|
54072
|
+
JSON.stringify(def, null, 2)
|
|
54073
|
+
);
|
|
54074
|
+
console.log(` Wrote agents/${filename}`);
|
|
54075
|
+
}
|
|
54076
|
+
fs14.writeFileSync(
|
|
54077
|
+
path14.join(outDir, "server.ts"),
|
|
54078
|
+
serverTs()
|
|
54079
|
+
);
|
|
54080
|
+
fs14.writeFileSync(
|
|
54081
|
+
path14.join(outDir, "Dockerfile"),
|
|
54082
|
+
dockerfile()
|
|
54083
|
+
);
|
|
54084
|
+
fs14.writeFileSync(
|
|
54085
|
+
path14.join(outDir, ".dockerignore"),
|
|
54086
|
+
dockerignore()
|
|
54087
|
+
);
|
|
54088
|
+
fs14.writeFileSync(
|
|
54089
|
+
path14.join(outDir, "tsconfig.json"),
|
|
54090
|
+
tsconfigJson()
|
|
54091
|
+
);
|
|
54092
|
+
fs14.writeFileSync(
|
|
54093
|
+
path14.join(outDir, "package.json"),
|
|
54094
|
+
packageJson(projectName, "workspace:*")
|
|
54095
|
+
);
|
|
54096
|
+
let monorepoRoot = process.cwd();
|
|
54097
|
+
for (let i = 0; i < 8; i++) {
|
|
54098
|
+
if (fs14.existsSync(path14.join(monorepoRoot, "pnpm-workspace.yaml"))) break;
|
|
54099
|
+
const parent = path14.dirname(monorepoRoot);
|
|
54100
|
+
if (parent === monorepoRoot) break;
|
|
54101
|
+
monorepoRoot = parent;
|
|
54102
|
+
}
|
|
54103
|
+
const setupScript = setupSh(monorepoRoot);
|
|
54104
|
+
const setupPath = path14.join(outDir, "setup.sh");
|
|
54105
|
+
fs14.writeFileSync(setupPath, setupScript);
|
|
54106
|
+
fs14.chmodSync(setupPath, 493);
|
|
54107
|
+
const allSecrets = /* @__PURE__ */ new Set();
|
|
54108
|
+
for (const { def } of agentDefs) {
|
|
54109
|
+
for (const s of collectSecretNames(def)) allSecrets.add(s);
|
|
54110
|
+
}
|
|
54111
|
+
const secretNames = Array.from(allSecrets);
|
|
54112
|
+
fs14.writeFileSync(
|
|
54113
|
+
path14.join(outDir, "README.md"),
|
|
54114
|
+
readme(
|
|
54115
|
+
agentDefs.map((a) => a.name),
|
|
54116
|
+
secretNames
|
|
54117
|
+
)
|
|
54118
|
+
);
|
|
54119
|
+
console.log("");
|
|
54120
|
+
console.log(chalk30.green(`\u2713 Scaffold written to ${outDir}`));
|
|
54121
|
+
console.log("");
|
|
54122
|
+
console.log(chalk30.bold("Next steps:"));
|
|
54123
|
+
console.log(` cd ${options.output}`);
|
|
54124
|
+
console.log(" chmod +x setup.sh && ./setup.sh # pack runtime + install deps");
|
|
54125
|
+
console.log(" npm run dev # test locally");
|
|
54126
|
+
console.log("");
|
|
54127
|
+
if (secretNames.length > 0) {
|
|
54128
|
+
console.log(chalk30.yellow("Required secrets (set before deploying):"));
|
|
54129
|
+
for (const s of secretNames) {
|
|
54130
|
+
console.log(` ${chalk30.cyan(s)}`);
|
|
54131
|
+
}
|
|
54132
|
+
console.log("");
|
|
54133
|
+
console.log(" Set via Cloud Run: gcloud run deploy \u2026 --set-secrets KEY=NAME:latest");
|
|
54134
|
+
console.log(" Or export locally: export KEY=<value>");
|
|
54135
|
+
console.log("");
|
|
54136
|
+
}
|
|
54137
|
+
console.log("Deploy to Cloud Run:");
|
|
54138
|
+
console.log(
|
|
54139
|
+
` gcloud run deploy ${projectName} --source ${options.output} \\`
|
|
54140
|
+
);
|
|
54141
|
+
console.log(" --region us-central1 --platform managed \\");
|
|
54142
|
+
console.log(" --allow-unauthenticated --port 8080");
|
|
54143
|
+
}
|
|
54144
|
+
);
|
|
53097
54145
|
|
|
53098
54146
|
// src/index.ts
|
|
53099
54147
|
init_credential_store();
|
|
53100
54148
|
|
|
53101
54149
|
// src/lib/update-check.ts
|
|
53102
|
-
import
|
|
54150
|
+
import chalk31 from "chalk";
|
|
53103
54151
|
import Conf3 from "conf";
|
|
53104
54152
|
var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
|
|
53105
54153
|
var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -53193,7 +54241,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
|
|
|
53193
54241
|
console.error(message);
|
|
53194
54242
|
});
|
|
53195
54243
|
notify(
|
|
53196
|
-
`${
|
|
54244
|
+
`${chalk31.yellow("Update available:")} ${chalk31.red(currentVersion)} ${chalk31.gray("->")} ${chalk31.green(latestVersion)} ${chalk31.gray(`(${getUpgradeCommand()})`)}`
|
|
53197
54245
|
);
|
|
53198
54246
|
store.set("lastNotifiedAt", now.toISOString());
|
|
53199
54247
|
store.set("lastNotifiedVersion", latestVersion);
|
|
@@ -53235,7 +54283,7 @@ function maybeNotifyAboutCliUpdate(args, options = {}) {
|
|
|
53235
54283
|
// src/index.ts
|
|
53236
54284
|
loadEnv();
|
|
53237
54285
|
setCliTitle();
|
|
53238
|
-
var program = new
|
|
54286
|
+
var program = new Command25();
|
|
53239
54287
|
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");
|
|
53240
54288
|
program.addCommand(initCommand);
|
|
53241
54289
|
program.addCommand(loginCommand);
|
|
@@ -53257,9 +54305,11 @@ program.addCommand(personaCommand);
|
|
|
53257
54305
|
program.addCommand(analyticsCommand);
|
|
53258
54306
|
program.addCommand(billingCommand);
|
|
53259
54307
|
program.addCommand(flowVersionsCommand);
|
|
54308
|
+
program.addCommand(agentVersionsCommand);
|
|
53260
54309
|
program.addCommand(createMarathonCommand());
|
|
53261
54310
|
program.addCommand(tailCommand);
|
|
53262
54311
|
program.addCommand(validateProductCommand);
|
|
54312
|
+
program.addCommand(deployCommand);
|
|
53263
54313
|
program.exitOverride();
|
|
53264
54314
|
try {
|
|
53265
54315
|
const userArgs = process.argv.slice(2);
|
|
@@ -53273,15 +54323,15 @@ try {
|
|
|
53273
54323
|
} catch (error51) {
|
|
53274
54324
|
const commanderError = error51;
|
|
53275
54325
|
if (commanderError.code === "commander.missingArgument") {
|
|
53276
|
-
console.error(
|
|
54326
|
+
console.error(chalk32.red(`Error: ${commanderError.message}`));
|
|
53277
54327
|
process.exit(1);
|
|
53278
54328
|
} else if (commanderError.code === "commander.unknownOption") {
|
|
53279
|
-
console.error(
|
|
54329
|
+
console.error(chalk32.red(`Error: ${commanderError.message}`));
|
|
53280
54330
|
process.exit(1);
|
|
53281
54331
|
} else if (commanderError.code === "commander.help" || commanderError.code === "commander.version") {
|
|
53282
54332
|
process.exit(0);
|
|
53283
54333
|
} else {
|
|
53284
|
-
console.error(
|
|
54334
|
+
console.error(chalk32.red("An unexpected error occurred:"));
|
|
53285
54335
|
console.error(error51);
|
|
53286
54336
|
process.exit(1);
|
|
53287
54337
|
}
|
|
@@ -53290,12 +54340,12 @@ async function handleNoCommand() {
|
|
|
53290
54340
|
const store = new CredentialStore();
|
|
53291
54341
|
const hasCredentials = await store.hasCredentials();
|
|
53292
54342
|
if (!hasCredentials) {
|
|
53293
|
-
console.log(
|
|
54343
|
+
console.log(chalk32.cyan("\nWelcome to Runtype CLI!\n"));
|
|
53294
54344
|
console.log("It looks like this is your first time. Run the setup wizard:");
|
|
53295
|
-
console.log(` ${
|
|
54345
|
+
console.log(` ${chalk32.green("runtype init")}
|
|
53296
54346
|
`);
|
|
53297
54347
|
console.log("Or see all available commands:");
|
|
53298
|
-
console.log(` ${
|
|
54348
|
+
console.log(` ${chalk32.green("runtype --help")}
|
|
53299
54349
|
`);
|
|
53300
54350
|
} else {
|
|
53301
54351
|
try {
|