@runtypelabs/cli 2.29.0 → 2.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +523 -157
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -136,8 +136,8 @@ var init_credential_store = __esm({
|
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
// src/index.ts
|
|
139
|
-
import { Command as
|
|
140
|
-
import
|
|
139
|
+
import { Command as Command39 } from "commander";
|
|
140
|
+
import chalk48 from "chalk";
|
|
141
141
|
|
|
142
142
|
// src/lib/load-env.ts
|
|
143
143
|
import { readFileSync } from "fs";
|
|
@@ -38852,6 +38852,9 @@ var coverageInventoryOutputSchema = external_exports.object({
|
|
|
38852
38852
|
instructions: external_exports.array(coverageInstructionSchema)
|
|
38853
38853
|
});
|
|
38854
38854
|
var userProfileFeaturesSchema = external_exports.object({
|
|
38855
|
+
// Agent Skills is permanently enabled — the API always returns `true`. Kept
|
|
38856
|
+
// on the wire (rather than dropped) for compatibility with deployed SPA
|
|
38857
|
+
// bundles and the published SDK that still read this field.
|
|
38855
38858
|
enableAgentSkills: external_exports.boolean(),
|
|
38856
38859
|
// Gates the WebMCP-powered dashboard assistant (copilot panel + chat
|
|
38857
38860
|
// proxy). Driven by the `enable-dashboard-assistant` boolean flag.
|
|
@@ -38938,10 +38941,16 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38938
38941
|
"anthropic": "claude-opus-4-7",
|
|
38939
38942
|
"vercel": "anthropic/claude-opus-4.7"
|
|
38940
38943
|
},
|
|
38944
|
+
"claude-opus-4-7-fast": {
|
|
38945
|
+
"vercel": "anthropic/claude-opus-4.7-fast"
|
|
38946
|
+
},
|
|
38941
38947
|
"claude-opus-4-8": {
|
|
38942
38948
|
"anthropic": "claude-opus-4-8",
|
|
38943
38949
|
"vercel": "anthropic/claude-opus-4.8"
|
|
38944
38950
|
},
|
|
38951
|
+
"claude-opus-4-8-fast": {
|
|
38952
|
+
"vercel": "anthropic/claude-opus-4.8-fast"
|
|
38953
|
+
},
|
|
38945
38954
|
"claude-opus-4.1": {
|
|
38946
38955
|
"vercel": "anthropic/claude-opus-4.1"
|
|
38947
38956
|
},
|
|
@@ -38954,9 +38963,15 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38954
38963
|
"claude-opus-4.7": {
|
|
38955
38964
|
"vercel": "anthropic/claude-opus-4.7"
|
|
38956
38965
|
},
|
|
38966
|
+
"claude-opus-4.7-fast": {
|
|
38967
|
+
"vercel": "anthropic/claude-opus-4.7-fast"
|
|
38968
|
+
},
|
|
38957
38969
|
"claude-opus-4.8": {
|
|
38958
38970
|
"vercel": "anthropic/claude-opus-4.8"
|
|
38959
38971
|
},
|
|
38972
|
+
"claude-opus-4.8-fast": {
|
|
38973
|
+
"vercel": "anthropic/claude-opus-4.8-fast"
|
|
38974
|
+
},
|
|
38960
38975
|
"claude-sonnet-4": {
|
|
38961
38976
|
"vercel": "anthropic/claude-sonnet-4"
|
|
38962
38977
|
},
|
|
@@ -39006,9 +39021,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39006
39021
|
"devstral-2": {
|
|
39007
39022
|
"vercel": "mistral/devstral-2"
|
|
39008
39023
|
},
|
|
39009
|
-
"devstral-small": {
|
|
39010
|
-
"vercel": "mistral/devstral-small"
|
|
39011
|
-
},
|
|
39012
39024
|
"devstral-small-2": {
|
|
39013
39025
|
"vercel": "mistral/devstral-small-2"
|
|
39014
39026
|
},
|
|
@@ -39366,6 +39378,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39366
39378
|
"gpt-oss-20b": {
|
|
39367
39379
|
"togetherai": "togetherai/openai/gpt-oss-20b"
|
|
39368
39380
|
},
|
|
39381
|
+
"gpt-realtime-whisper": {
|
|
39382
|
+
"vercel": "openai/gpt-realtime-whisper"
|
|
39383
|
+
},
|
|
39369
39384
|
"grok-4-20-0309-non-reasoning": {
|
|
39370
39385
|
"xai": "grok-4.20-0309-non-reasoning"
|
|
39371
39386
|
},
|
|
@@ -39438,6 +39453,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39438
39453
|
"grok-voice-think-fast-1.0": {
|
|
39439
39454
|
"vercel": "xai/grok-voice-think-fast-1.0"
|
|
39440
39455
|
},
|
|
39456
|
+
"inkling": {
|
|
39457
|
+
"vercel": "thinkingmachines/inkling"
|
|
39458
|
+
},
|
|
39441
39459
|
"interfaze-beta": {
|
|
39442
39460
|
"vercel": "interfaze/interfaze-beta"
|
|
39443
39461
|
},
|
|
@@ -39495,6 +39513,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39495
39513
|
"kimi-k2.7-code-highspeed": {
|
|
39496
39514
|
"vercel": "moonshotai/kimi-k2.7-code-highspeed"
|
|
39497
39515
|
},
|
|
39516
|
+
"kimi-k3": {
|
|
39517
|
+
"vercel": "moonshotai/kimi-k3"
|
|
39518
|
+
},
|
|
39498
39519
|
"lfm2-24b-a2b": {
|
|
39499
39520
|
"togetherai": "togetherai/LiquidAI/LFM2-24B-A2B"
|
|
39500
39521
|
},
|
|
@@ -39546,12 +39567,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39546
39567
|
"llama3-3-70b": {
|
|
39547
39568
|
"vercel": "meta/llama-3.3-70b"
|
|
39548
39569
|
},
|
|
39549
|
-
"longcat-flash-chat": {
|
|
39550
|
-
"vercel": "meituan/longcat-flash-chat"
|
|
39551
|
-
},
|
|
39552
|
-
"longcat-flash-thinking-2601": {
|
|
39553
|
-
"vercel": "meituan/longcat-flash-thinking-2601"
|
|
39554
|
-
},
|
|
39555
39570
|
"magistral-medium": {
|
|
39556
39571
|
"vercel": "mistral/magistral-medium"
|
|
39557
39572
|
},
|
|
@@ -39573,9 +39588,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39573
39588
|
"mimo-v2-5-pro": {
|
|
39574
39589
|
"vercel": "xiaomi/mimo-v2.5-pro"
|
|
39575
39590
|
},
|
|
39576
|
-
"mimo-v2-pro": {
|
|
39577
|
-
"vercel": "xiaomi/mimo-v2-pro"
|
|
39578
|
-
},
|
|
39579
39591
|
"mimo-v2.5": {
|
|
39580
39592
|
"vercel": "xiaomi/mimo-v2.5"
|
|
39581
39593
|
},
|
|
@@ -39714,9 +39726,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39714
39726
|
"pixtral-12b": {
|
|
39715
39727
|
"vercel": "mistral/pixtral-12b"
|
|
39716
39728
|
},
|
|
39717
|
-
"pixtral-large": {
|
|
39718
|
-
"vercel": "mistral/pixtral-large"
|
|
39719
|
-
},
|
|
39720
39729
|
"qwen-3-14b": {
|
|
39721
39730
|
"vercel": "alibaba/qwen-3-14b"
|
|
39722
39731
|
},
|
|
@@ -39894,18 +39903,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39894
39903
|
"qwen3.7-plus": {
|
|
39895
39904
|
"vercel": "alibaba/qwen3.7-plus"
|
|
39896
39905
|
},
|
|
39897
|
-
"rerank-2-5": {
|
|
39898
|
-
"vercel": "voyage/rerank-2.5"
|
|
39899
|
-
},
|
|
39900
|
-
"rerank-2-5-lite": {
|
|
39901
|
-
"vercel": "voyage/rerank-2.5-lite"
|
|
39902
|
-
},
|
|
39903
|
-
"rerank-2.5": {
|
|
39904
|
-
"vercel": "voyage/rerank-2.5"
|
|
39905
|
-
},
|
|
39906
|
-
"rerank-2.5-lite": {
|
|
39907
|
-
"vercel": "voyage/rerank-2.5-lite"
|
|
39908
|
-
},
|
|
39909
39906
|
"rerank-v3-5": {
|
|
39910
39907
|
"vercel": "cohere/rerank-v3.5"
|
|
39911
39908
|
},
|
|
@@ -39966,9 +39963,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39966
39963
|
"trinity-large": {
|
|
39967
39964
|
"vercel": "arcee-ai/trinity-large-thinking"
|
|
39968
39965
|
},
|
|
39969
|
-
"trinity-large-preview": {
|
|
39970
|
-
"vercel": "arcee-ai/trinity-large-preview"
|
|
39971
|
-
},
|
|
39972
39966
|
"trinity-large-thinking": {
|
|
39973
39967
|
"vercel": "arcee-ai/trinity-large-thinking"
|
|
39974
39968
|
},
|
|
@@ -41975,6 +41969,14 @@ var mcpToolFulfillmentSchema = external_exports.object({
|
|
|
41975
41969
|
rung: external_exports.literal("mcp_tool"),
|
|
41976
41970
|
tool: external_exports.string(),
|
|
41977
41971
|
args: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
41972
|
+
/**
|
|
41973
|
+
* Operator-supplied arguments that MUST be merged into `args` before the
|
|
41974
|
+
* call does anything — executing `args` alone is accepted by the tool but
|
|
41975
|
+
* writes nothing, so a consumer that sees this field non-empty must obtain
|
|
41976
|
+
* these values (from the operator or a secret store) first. Keyed by arg
|
|
41977
|
+
* name; the value describes what to supply.
|
|
41978
|
+
*/
|
|
41979
|
+
pendingArgs: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
41978
41980
|
summary: external_exports.string()
|
|
41979
41981
|
});
|
|
41980
41982
|
var restFulfillmentSchema = external_exports.object({
|
|
@@ -43425,12 +43427,10 @@ var platformCatalogSchema = external_exports.object({
|
|
|
43425
43427
|
/**
|
|
43426
43428
|
* Agent Skills — loadable SKILL.md context bundles a deployed agent pulls into
|
|
43427
43429
|
* its working context on demand. Distinct from A2A AgentSkill (agent-card
|
|
43428
|
-
* roles).
|
|
43429
|
-
*
|
|
43430
|
+
* roles). Described here rather than listed as a fixed catalog (skills are
|
|
43431
|
+
* user-authored, not a built-in set).
|
|
43430
43432
|
*/
|
|
43431
43433
|
agentSkills: external_exports.object({
|
|
43432
|
-
/** Rollout flag controlling availability; off in production until ramped. */
|
|
43433
|
-
rolloutFlag: external_exports.string(),
|
|
43434
43434
|
description: external_exports.string(),
|
|
43435
43435
|
/** How an agent acquires a bound skill at runtime. */
|
|
43436
43436
|
loadModel: external_exports.string(),
|
|
@@ -43552,7 +43552,6 @@ var PLATFORM_CATALOG = {
|
|
|
43552
43552
|
}
|
|
43553
43553
|
],
|
|
43554
43554
|
agentSkills: {
|
|
43555
|
-
rolloutFlag: "enable-agent-skills",
|
|
43556
43555
|
description: "Loadable SKILL.md context bundles (Anthropic frontmatter + a runtype: capability block) that a deployed agent pulls into its working context on demand.",
|
|
43557
43556
|
loadModel: "A bound skill is surfaced as a `skill:<slug>` virtual tool \u2014 the model loads it on demand (L1 description in the tool list \u2192 L2 markdown body returned on call); bound capabilities activate for later turns.",
|
|
43558
43557
|
governance: "Two-plane: admin/control plane (REST /v1/skills, scoped by SKILLS:READ/WRITE, no review queue) vs deployed-agent/data plane (propose_skill, review-by-default via /v1/skill-proposals).",
|
|
@@ -44008,7 +44007,7 @@ ${renderDefaultModelStrengthsGuide()}`;
|
|
|
44008
44007
|
- **Built-in tools**: GPT Image 2 image generation, provider-native web search (OpenAI web search, Anthropic web search/fetch, xAI Live Search for Grok-3 series, xAI X Search / Web Search agentic tools for Grok-4 series), Exa (AI search), Firecrawl (simple web scraping), Browser Run tools (rendered markdown, HTML, screenshots, snapshots, selector scraping, JSON extraction, link harvesting \u2014 stateless), Browser Session tools (persistent interactive browsing: open, navigate, click, type, scroll, screenshot, evaluate, close), Browser Agent (autonomous higher-level alternative \u2014 give a natural-language goal plus a startUrl or sessionId and the agent navigates/clicks/extracts on its own), Store Asset (host any file from a URL or base64 inline content \u2014 returns a permanent public or signed private URL, downloads as attachment), Publish Page (host HTML that renders inline in the browser at a shareable 7-day /preview/ URL under a locked-down CSP), vector search, UCP commerce tools (discovery, catalog, cart, checkout, orders for any UCP-enabled merchant)
|
|
44009
44008
|
- **Integrations**: ${integrations}
|
|
44010
44009
|
- **Flow step types**: prompt, ${stepTypes}
|
|
44011
|
-
- **Agent Skills**: loadable SKILL.md context bundles an agent pulls in on demand via a \`skill:<slug>\` tool (L1 description \u2192 L2 body), optionally binding flows/subagents/tools.
|
|
44010
|
+
- **Agent Skills**: loadable SKILL.md context bundles an agent pulls in on demand via a \`skill:<slug>\` tool (L1 description \u2192 L2 body), optionally binding flows/subagents/tools. See the Agent Skills guide.
|
|
44012
44011
|
- **Available models**: ${models}
|
|
44013
44012
|
- **Surface types**: ${PLATFORM_CATALOG.availableSurfaceTypes.join(", ")}`;
|
|
44014
44013
|
})();
|
|
@@ -71871,6 +71870,7 @@ function isCI() {
|
|
|
71871
71870
|
var SKILLS_OFFER_SKIP_COMMANDS = /* @__PURE__ */ new Set([
|
|
71872
71871
|
"skills",
|
|
71873
71872
|
"install-mcp",
|
|
71873
|
+
"onboard",
|
|
71874
71874
|
"init",
|
|
71875
71875
|
"login",
|
|
71876
71876
|
"auth"
|
|
@@ -72611,8 +72611,6 @@ function getMcpRestartInstruction(agent) {
|
|
|
72611
72611
|
function getMcpSkillsAgentId(agent) {
|
|
72612
72612
|
return MCP_AGENT_DEFINITIONS[agent].skillsAgentId;
|
|
72613
72613
|
}
|
|
72614
|
-
|
|
72615
|
-
// src/commands/install-mcp.ts
|
|
72616
72614
|
async function selectAgent(options, tty) {
|
|
72617
72615
|
if (options.agent) {
|
|
72618
72616
|
const explicit = normalizeMcpAgent(options.agent);
|
|
@@ -72648,6 +72646,8 @@ async function selectAgent(options, tty) {
|
|
|
72648
72646
|
{ promptLabel: "Agent" }
|
|
72649
72647
|
);
|
|
72650
72648
|
}
|
|
72649
|
+
|
|
72650
|
+
// src/commands/install-mcp.ts
|
|
72651
72651
|
async function installSkillsForAgent(agent, jsonMode) {
|
|
72652
72652
|
const rosieId = getMcpSkillsAgentId(agent);
|
|
72653
72653
|
try {
|
|
@@ -72814,13 +72814,378 @@ Setting up Runtype for ${definition.displayName}\u2026`));
|
|
|
72814
72814
|
if (partial2) process.exitCode = 1;
|
|
72815
72815
|
});
|
|
72816
72816
|
|
|
72817
|
-
// src/commands/
|
|
72818
|
-
import {
|
|
72819
|
-
import { join as join14
|
|
72817
|
+
// src/commands/onboard.ts
|
|
72818
|
+
import { existsSync as existsSync16, readFileSync as readFileSync20 } from "fs";
|
|
72819
|
+
import { join as join14 } from "path";
|
|
72820
72820
|
import { Command as Command34 } from "commander";
|
|
72821
72821
|
import chalk42 from "chalk";
|
|
72822
|
+
|
|
72823
|
+
// ../shared/dist/agent-onboarding-content.mjs
|
|
72824
|
+
var AGENT_ONBOARDING_MARKDOWN = `# Runtype for Coding Agents
|
|
72825
|
+
|
|
72826
|
+
You are reading the setup script served by \`https://runtype.ai\`. Your durable goal is to leave this coding harness connected to Runtype's hosted MCP server with browser OAuth. Use the Runtype CLI as a bridge during this first session; do not treat it as the final integration.
|
|
72827
|
+
|
|
72828
|
+
## Golden path \u2014 do exactly this
|
|
72829
|
+
|
|
72830
|
+
If the live Runtype MCP tools are already available in this session, skip setup and go to "After MCP is active" below. Otherwise follow every step in order:
|
|
72831
|
+
|
|
72832
|
+
### 1. Install and authenticate the CLI
|
|
72833
|
+
|
|
72834
|
+
\`\`\`bash
|
|
72835
|
+
npm install -g @runtypelabs/cli
|
|
72836
|
+
runtype auth login
|
|
72837
|
+
\`\`\`
|
|
72838
|
+
|
|
72839
|
+
Complete the browser sign-in when it opens. The CLI makes this first session productive even though a running coding harness often cannot discover a newly installed MCP connection until it restarts.
|
|
72840
|
+
|
|
72841
|
+
### 2. Install skills and the OAuth MCP connection
|
|
72842
|
+
|
|
72843
|
+
\`\`\`bash
|
|
72844
|
+
runtype install-mcp
|
|
72845
|
+
\`\`\`
|
|
72846
|
+
|
|
72847
|
+
This command detects the current coding harness, installs the Runtype agent skills for it, writes the user-level hosted MCP configuration, and starts the harness's own OAuth flow when possible. If it asks which harness to configure, select the harness running this session. If a browser opens, have the user complete OAuth.
|
|
72848
|
+
|
|
72849
|
+
Do not manually create an API key, export the CLI key into MCP, or choose a different setup path merely to avoid a restart. CLI authentication and MCP OAuth are separate on purpose: the CLI is the first-session bridge; client-owned OAuth MCP is the durable connection.
|
|
72850
|
+
|
|
72851
|
+
### 3. Keep working in this session with the CLI
|
|
72852
|
+
|
|
72853
|
+
Do not stop just because the new MCP connection is not visible yet. Use CLI commands for useful first-session work:
|
|
72854
|
+
|
|
72855
|
+
\`\`\`bash
|
|
72856
|
+
runtype auth whoami
|
|
72857
|
+
runtype agents list
|
|
72858
|
+
runtype flows list
|
|
72859
|
+
runtype products list
|
|
72860
|
+
runtype --help
|
|
72861
|
+
\`\`\`
|
|
72862
|
+
|
|
72863
|
+
The CLI also supports dispatch, records, validation, product setup, and other account operations. Read command help before mutating resources, and report concrete IDs and URLs to the user.
|
|
72864
|
+
|
|
72865
|
+
### 4. Tell the user to restart or reload the harness
|
|
72866
|
+
|
|
72867
|
+
Before finishing this session, read the final status and next steps from \`runtype install-mcp\`. Complete any OAuth action it requests and retry any failed skill installation. Do not call setup complete while the command reports \`action-required\`, \`partial\`, or an error.
|
|
72868
|
+
|
|
72869
|
+
Only after skills and OAuth both succeed, tell the user exactly what changed and ask them to restart or reload the coding harness. Use direct language such as:
|
|
72870
|
+
|
|
72871
|
+
> Runtype skills and the OAuth MCP connection are installed. Please restart or reload this coding agent (or start a new session) so it can activate the new MCP tools. I used the CLI to keep this first session productive; after restart I will use MCP by default.
|
|
72872
|
+
|
|
72873
|
+
If an action remains, report that exact action instead of using the success wording above. Do not claim the running agent can use MCP until its Runtype tools actually appear.
|
|
72874
|
+
|
|
72875
|
+
### 5. Switch to MCP after restart
|
|
72876
|
+
|
|
72877
|
+
In the next session, use Runtype MCP first. Do not fall back to the CLI just because it worked previously. Start by calling:
|
|
72878
|
+
|
|
72879
|
+
\`\`\`json
|
|
72880
|
+
{
|
|
72881
|
+
"task": "build-product",
|
|
72882
|
+
"description": "Describe the user's product goal here"
|
|
72883
|
+
}
|
|
72884
|
+
\`\`\`
|
|
72885
|
+
|
|
72886
|
+
with \`get_build_instructions\`. Then use \`get_platform_documentation\` for exact schemas and catalogs, create or update resources with MCP tools, validate them, and test the result with a real run.
|
|
72887
|
+
|
|
72888
|
+
## If the install needs recovery
|
|
72889
|
+
|
|
72890
|
+
\`runtype install-mcp\` intentionally changes one confidently selected harness, not every agent config it can find. If detection is ambiguous, re-run it with one explicit id:
|
|
72891
|
+
|
|
72892
|
+
\`\`\`bash
|
|
72893
|
+
runtype install-mcp --agent claude
|
|
72894
|
+
runtype install-mcp --agent codex
|
|
72895
|
+
runtype install-mcp --agent cursor
|
|
72896
|
+
runtype install-mcp --agent gemini
|
|
72897
|
+
runtype install-mcp --agent opencode
|
|
72898
|
+
runtype install-mcp --agent vscode
|
|
72899
|
+
\`\`\`
|
|
72900
|
+
|
|
72901
|
+
Use only the line for the current harness. Follow the command's OAuth and restart instructions. Use \`--force\` only when the command reports that an existing MCP server named \`runtype\` points to a different URL and the user agrees to replace it.
|
|
72902
|
+
|
|
72903
|
+
## Headless exception \u2014 not the normal path
|
|
72904
|
+
|
|
72905
|
+
Only use an API key when browser OAuth is genuinely impossible in the user's environment, not merely inconvenient. Ask the user before switching authentication modes, then follow the canonical headless registration and claim protocol at \`https://runtype.com/auth.md\`. Never print a secret into the transcript or write a bearer token directly into a committed config file.
|
|
72906
|
+
|
|
72907
|
+
The hosted MCP endpoint is \`https://api.runtype.com/v1/mcp/protocol\`. A user-supplied \`RUNTYPE_API_KEY\` can authenticate CLI commands in a headless environment, but return to client-owned OAuth MCP when the harness can support it.
|
|
72908
|
+
|
|
72909
|
+
## After MCP is active
|
|
72910
|
+
|
|
72911
|
+
- Call \`get_build_instructions\` before building.
|
|
72912
|
+
- Use \`get_platform_documentation\` instead of inventing payload shapes.
|
|
72913
|
+
- Let the installed Runtype skills route task-specific work: product builds, live account operations, Persona embeds, templates, and SDK/CLI workflows.
|
|
72914
|
+
- If the user gives you a \`use.runtype.com/now?...\`, example, or template/FPO link, use the Runtype template skill and MCP tools rather than opening the login-gated dashboard page.
|
|
72915
|
+
- Validate before shipping and test with a real execution.
|
|
72916
|
+
|
|
72917
|
+
Runtype MCP can create and operate agents, flows, products, records, secrets, evals, and surfaces; attach built-in, HTTP, MCP, flow, and subagent tools; and ship chat, API, webhook, messaging, schedule, MCP, and hosted-page experiences.
|
|
72918
|
+
|
|
72919
|
+
Docs: [runtype.com](https://runtype.com)
|
|
72920
|
+
Dashboard: [use.runtype.com](https://use.runtype.com)
|
|
72921
|
+
API: [api.runtype.com](https://api.runtype.com)
|
|
72922
|
+
`;
|
|
72923
|
+
|
|
72924
|
+
// src/commands/onboard.ts
|
|
72925
|
+
init_credential_store();
|
|
72926
|
+
var AUTH_LOGIN_INSTRUCTION = "Sign in to Runtype: run `runtype auth login` (or set RUNTYPE_API_KEY), then re-run `runtype onboard`.";
|
|
72927
|
+
var AFTER_RESTART_STEPS = [
|
|
72928
|
+
"Use the Runtype MCP server first for all Runtype work.",
|
|
72929
|
+
"Start with the get_build_instructions tool before creating or changing resources.",
|
|
72930
|
+
"Do not fall back to the Runtype CLI once the MCP connection is active."
|
|
72931
|
+
];
|
|
72932
|
+
var EXISTING_PROJECT_ADVICE = "Building AI features into an existing codebase? After restart, decide with the user whether flow/agent config should be hosted (dashboard-editable, called via the dispatch API) or code-first in this repo via the TypeScript SDK. They run on the same platform and can be mixed.";
|
|
72933
|
+
function detectExistingProject(cwd = process.cwd()) {
|
|
72934
|
+
const packageJsonPath = join14(cwd, "package.json");
|
|
72935
|
+
const hasPackageJson = existsSync16(packageJsonPath);
|
|
72936
|
+
if (!hasPackageJson && !existsSync16(join14(cwd, ".git"))) return false;
|
|
72937
|
+
if (hasPackageJson) {
|
|
72938
|
+
try {
|
|
72939
|
+
const parsed = JSON.parse(readFileSync20(packageJsonPath, "utf8"));
|
|
72940
|
+
if (parsed.name === "@runtypelabs/cli") return false;
|
|
72941
|
+
} catch {
|
|
72942
|
+
}
|
|
72943
|
+
}
|
|
72944
|
+
return true;
|
|
72945
|
+
}
|
|
72946
|
+
var defaultDependencies = {
|
|
72947
|
+
getEnvApiKey: () => getRuntimeApiKey(),
|
|
72948
|
+
getStoredCredentials: async () => {
|
|
72949
|
+
const credentials = await new CredentialStore().getCredentials();
|
|
72950
|
+
if (!credentials) return null;
|
|
72951
|
+
return { userId: credentials.userId, orgId: credentials.orgId };
|
|
72952
|
+
},
|
|
72953
|
+
ensureAuth,
|
|
72954
|
+
selectAgent,
|
|
72955
|
+
configureMcp: (agent, options) => configureMcpAgent(agent, options),
|
|
72956
|
+
authenticateMcp: (agent, options) => authenticateMcpAgent(agent, options),
|
|
72957
|
+
installSkills: installSkillsForAgent,
|
|
72958
|
+
isExistingProject: detectExistingProject,
|
|
72959
|
+
setExitCode: (code) => {
|
|
72960
|
+
process.exitCode = code;
|
|
72961
|
+
}
|
|
72962
|
+
};
|
|
72963
|
+
async function resolveAuth(dependencies, options) {
|
|
72964
|
+
if (dependencies.getEnvApiKey()) {
|
|
72965
|
+
return { authenticated: true, method: "env" };
|
|
72966
|
+
}
|
|
72967
|
+
const stored = await dependencies.getStoredCredentials();
|
|
72968
|
+
if (stored) {
|
|
72969
|
+
return { authenticated: true, method: "stored", userId: stored.userId, orgId: stored.orgId };
|
|
72970
|
+
}
|
|
72971
|
+
if (!options.interactiveLogin) {
|
|
72972
|
+
return { authenticated: false, instruction: AUTH_LOGIN_INSTRUCTION };
|
|
72973
|
+
}
|
|
72974
|
+
const apiKey = await dependencies.ensureAuth({ exitOnFailure: false });
|
|
72975
|
+
if (!apiKey) {
|
|
72976
|
+
return { authenticated: false, instruction: AUTH_LOGIN_INSTRUCTION };
|
|
72977
|
+
}
|
|
72978
|
+
const after = await dependencies.getStoredCredentials();
|
|
72979
|
+
return {
|
|
72980
|
+
authenticated: true,
|
|
72981
|
+
method: "browser-login",
|
|
72982
|
+
userId: after?.userId,
|
|
72983
|
+
orgId: after?.orgId
|
|
72984
|
+
};
|
|
72985
|
+
}
|
|
72986
|
+
function printAuthLine(auth) {
|
|
72987
|
+
if (!auth.authenticated) {
|
|
72988
|
+
console.log(chalk42.yellow(`! Not signed in. ${auth.instruction}`));
|
|
72989
|
+
return;
|
|
72990
|
+
}
|
|
72991
|
+
if (auth.method === "env") {
|
|
72992
|
+
console.log(chalk42.green("\u2713 Signed in with RUNTYPE_API_KEY from the environment."));
|
|
72993
|
+
return;
|
|
72994
|
+
}
|
|
72995
|
+
const identity = auth.userId ? ` (user ${auth.userId}${auth.orgId ? `, org ${auth.orgId}` : ""})` : "";
|
|
72996
|
+
if (auth.method === "stored") {
|
|
72997
|
+
console.log(chalk42.green(`\u2713 Already signed in${identity}.`));
|
|
72998
|
+
} else {
|
|
72999
|
+
console.log(chalk42.green(`\u2713 Signed in${identity}.`));
|
|
73000
|
+
}
|
|
73001
|
+
}
|
|
73002
|
+
function createOnboardCommand(overrides = {}) {
|
|
73003
|
+
const dependencies = { ...defaultDependencies, ...overrides };
|
|
73004
|
+
return new Command34("onboard").description("Set up Runtype for this coding agent: sign in, install skills and OAuth MCP").option("--agent <id>", "Coding agent to configure (auto-detected by default)").option("--force", 'Replace a conflicting MCP server named "runtype"').option("--dry-run", "Show the selected agent and planned changes without writing them").option("--no-login", "Skip browser sign-in and MCP OAuth").option("--no-skills", "Skip installing Runtype agent skills").option("--json", "Structured JSON output; implies --no-login").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").option("--print-instructions", "Print the canonical agent onboarding markdown and exit").action(async (options, cmd) => {
|
|
73005
|
+
if (options.printInstructions) {
|
|
73006
|
+
console.log(AGENT_ONBOARDING_MARKDOWN);
|
|
73007
|
+
return;
|
|
73008
|
+
}
|
|
73009
|
+
const globals = cmd.optsWithGlobals();
|
|
73010
|
+
const jsonMode = !!(options.json ?? globals.json);
|
|
73011
|
+
const tty = isTTY(options);
|
|
73012
|
+
const loginAllowed = !jsonMode && tty && options.login !== false;
|
|
73013
|
+
if (!jsonMode) {
|
|
73014
|
+
console.log(chalk42.cyan("\nRuntype onboarding"));
|
|
73015
|
+
console.log(
|
|
73016
|
+
"Runtype is a platform for building AI products: agents, flows, evals, and surfaces your team ships to its own users."
|
|
73017
|
+
);
|
|
73018
|
+
console.log(
|
|
73019
|
+
chalk42.dim(
|
|
73020
|
+
"This command signs you in, installs Runtype skills and the hosted OAuth MCP server, then prints next steps.\n"
|
|
73021
|
+
)
|
|
73022
|
+
);
|
|
73023
|
+
}
|
|
73024
|
+
let auth;
|
|
73025
|
+
try {
|
|
73026
|
+
auth = await resolveAuth(dependencies, {
|
|
73027
|
+
interactiveLogin: loginAllowed && !options.dryRun
|
|
73028
|
+
});
|
|
73029
|
+
} catch (error51) {
|
|
73030
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
73031
|
+
if (jsonMode) {
|
|
73032
|
+
printJson({ status: "error", code: "AUTH_RESOLUTION_FAILED", error: message });
|
|
73033
|
+
} else {
|
|
73034
|
+
console.error(chalk42.red(`Could not read Runtype credentials: ${message}`));
|
|
73035
|
+
}
|
|
73036
|
+
dependencies.setExitCode(1);
|
|
73037
|
+
return;
|
|
73038
|
+
}
|
|
73039
|
+
if (!jsonMode) printAuthLine(auth);
|
|
73040
|
+
let agent;
|
|
73041
|
+
try {
|
|
73042
|
+
agent = await dependencies.selectAgent({ agent: options.agent, json: jsonMode }, tty);
|
|
73043
|
+
} catch (error51) {
|
|
73044
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
73045
|
+
if (jsonMode) {
|
|
73046
|
+
printJson({ status: "error", code: "AGENT_DETECTION_FAILED", auth, error: message });
|
|
73047
|
+
} else {
|
|
73048
|
+
console.error(chalk42.red(message));
|
|
73049
|
+
}
|
|
73050
|
+
dependencies.setExitCode(1);
|
|
73051
|
+
return;
|
|
73052
|
+
}
|
|
73053
|
+
const definition = MCP_AGENT_DEFINITIONS[agent];
|
|
73054
|
+
if (!jsonMode) {
|
|
73055
|
+
console.log(chalk42.cyan(`
|
|
73056
|
+
Setting up Runtype for ${definition.displayName}\u2026`));
|
|
73057
|
+
}
|
|
73058
|
+
const configuration = await dependencies.configureMcp(agent, {
|
|
73059
|
+
force: options.force,
|
|
73060
|
+
dryRun: options.dryRun
|
|
73061
|
+
});
|
|
73062
|
+
if (!configuration.configured) {
|
|
73063
|
+
if (jsonMode) {
|
|
73064
|
+
printJson({ status: "error", code: "MCP_CONFIG_FAILED", agent, auth, configuration });
|
|
73065
|
+
} else {
|
|
73066
|
+
console.error(chalk42.red(configuration.error ?? "Could not configure Runtype MCP."));
|
|
73067
|
+
}
|
|
73068
|
+
dependencies.setExitCode(1);
|
|
73069
|
+
return;
|
|
73070
|
+
}
|
|
73071
|
+
if (!jsonMode) {
|
|
73072
|
+
if (options.dryRun) {
|
|
73073
|
+
console.log(chalk42.green("\u2713 Would install the user-level Runtype MCP connection."));
|
|
73074
|
+
} else if (configuration.changed) {
|
|
73075
|
+
console.log(chalk42.green("\u2713 Installed the user-level Runtype MCP connection."));
|
|
73076
|
+
} else {
|
|
73077
|
+
console.log(chalk42.green("\u2713 Runtype MCP is already configured at the correct URL."));
|
|
73078
|
+
}
|
|
73079
|
+
if (configuration.configPath) {
|
|
73080
|
+
console.log(chalk42.dim(` ${configuration.configPath}`));
|
|
73081
|
+
}
|
|
73082
|
+
if (configuration.backupPath) {
|
|
73083
|
+
console.log(chalk42.dim(` Backup: ${configuration.backupPath}`));
|
|
73084
|
+
}
|
|
73085
|
+
}
|
|
73086
|
+
const authentication = await dependencies.authenticateMcp(agent, {
|
|
73087
|
+
login: loginAllowed,
|
|
73088
|
+
dryRun: options.dryRun
|
|
73089
|
+
});
|
|
73090
|
+
if (!jsonMode && !options.dryRun) {
|
|
73091
|
+
if (authentication.authenticated) {
|
|
73092
|
+
console.log(chalk42.green("\u2713 MCP OAuth completed."));
|
|
73093
|
+
} else if (authentication.error) {
|
|
73094
|
+
console.log(chalk42.yellow(`! ${authentication.error}`));
|
|
73095
|
+
} else if (authentication.instruction) {
|
|
73096
|
+
console.log(chalk42.yellow(`! OAuth action required: ${authentication.instruction}`));
|
|
73097
|
+
}
|
|
73098
|
+
}
|
|
73099
|
+
const skills = options.skills === false || options.dryRun ? {
|
|
73100
|
+
status: options.dryRun ? "planned" : "skipped",
|
|
73101
|
+
installedAgents: [],
|
|
73102
|
+
failedAgents: []
|
|
73103
|
+
} : await dependencies.installSkills(agent, jsonMode);
|
|
73104
|
+
if (!jsonMode && !options.dryRun && skills.status === "error") {
|
|
73105
|
+
console.log(
|
|
73106
|
+
chalk42.yellow(
|
|
73107
|
+
`! Runtype MCP is configured, but skill installation failed: ${skills.error ?? "unknown error"}`
|
|
73108
|
+
)
|
|
73109
|
+
);
|
|
73110
|
+
}
|
|
73111
|
+
const restartInstruction = getMcpRestartInstruction(agent);
|
|
73112
|
+
const existingProject = dependencies.isExistingProject();
|
|
73113
|
+
const nextSteps = [];
|
|
73114
|
+
if (options.dryRun) {
|
|
73115
|
+
nextSteps.push(
|
|
73116
|
+
`Re-run \`runtype onboard --agent ${agent}\` without --dry-run to sign in, install skills, and configure MCP.`
|
|
73117
|
+
);
|
|
73118
|
+
} else {
|
|
73119
|
+
if (!auth.authenticated && auth.instruction) nextSteps.push(auth.instruction);
|
|
73120
|
+
if (authentication.instruction) nextSteps.push(authentication.instruction);
|
|
73121
|
+
if (authentication.error && !authentication.instruction) {
|
|
73122
|
+
nextSteps.push("Resolve the OAuth blocker reported above, then re-run `runtype onboard`.");
|
|
73123
|
+
}
|
|
73124
|
+
if (skills.status === "error") {
|
|
73125
|
+
nextSteps.push(
|
|
73126
|
+
`Retry skill installation with \`runtype skills install --agent ${getMcpSkillsAgentId(agent)}\`.`
|
|
73127
|
+
);
|
|
73128
|
+
} else if (skills.status === "skipped") {
|
|
73129
|
+
nextSteps.push(
|
|
73130
|
+
`Install the Runtype skills with \`runtype skills install --agent ${getMcpSkillsAgentId(agent)}\`.`
|
|
73131
|
+
);
|
|
73132
|
+
}
|
|
73133
|
+
nextSteps.push(
|
|
73134
|
+
"Continue this first session with the Runtype CLI; this running agent may not see the new MCP connection yet."
|
|
73135
|
+
);
|
|
73136
|
+
if (auth.authenticated && authentication.authenticated && skills.status !== "error") {
|
|
73137
|
+
nextSteps.push(
|
|
73138
|
+
`Tell the user that Runtype is set up, then ask them to restart or reload ${definition.displayName}.`
|
|
73139
|
+
);
|
|
73140
|
+
} else {
|
|
73141
|
+
nextSteps.push(
|
|
73142
|
+
"Tell the user that setup still has the action(s) above; do not call onboarding complete yet."
|
|
73143
|
+
);
|
|
73144
|
+
}
|
|
73145
|
+
nextSteps.push(`After completing any action above, ${restartInstruction}`);
|
|
73146
|
+
}
|
|
73147
|
+
const partial2 = !options.dryRun && (Boolean(authentication.error) || skills.status === "error");
|
|
73148
|
+
const status = options.dryRun ? "planned" : partial2 ? "partial" : auth.authenticated && authentication.authenticated ? "ok" : "action-required";
|
|
73149
|
+
if (jsonMode) {
|
|
73150
|
+
printJson({
|
|
73151
|
+
status,
|
|
73152
|
+
agent,
|
|
73153
|
+
auth,
|
|
73154
|
+
configuration,
|
|
73155
|
+
authentication,
|
|
73156
|
+
skills,
|
|
73157
|
+
activation: options.dryRun ? "not-configured" : "restart-required",
|
|
73158
|
+
restartInstruction,
|
|
73159
|
+
afterRestart: AFTER_RESTART_STEPS,
|
|
73160
|
+
...existingProject ? { existingProjectAdvice: EXISTING_PROJECT_ADVICE } : {},
|
|
73161
|
+
nextSteps
|
|
73162
|
+
});
|
|
73163
|
+
} else {
|
|
73164
|
+
console.log(chalk42.bold(`
|
|
73165
|
+
Onboarding status: ${status}`));
|
|
73166
|
+
console.log(chalk42.bold("\nDo exactly this next:"));
|
|
73167
|
+
nextSteps.forEach((step, index) => console.log(` ${index + 1}. ${step}`));
|
|
73168
|
+
console.log(chalk42.bold(`
|
|
73169
|
+
After restarting ${definition.displayName}:`));
|
|
73170
|
+
AFTER_RESTART_STEPS.forEach((step) => console.log(` - ${step}`));
|
|
73171
|
+
if (existingProject) {
|
|
73172
|
+
console.log(`
|
|
73173
|
+
${EXISTING_PROJECT_ADVICE}`);
|
|
73174
|
+
}
|
|
73175
|
+
console.log("");
|
|
73176
|
+
}
|
|
73177
|
+
if (partial2) dependencies.setExitCode(1);
|
|
73178
|
+
});
|
|
73179
|
+
}
|
|
73180
|
+
var onboardCommand = createOnboardCommand();
|
|
73181
|
+
|
|
73182
|
+
// src/commands/apps.ts
|
|
73183
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync21, lstatSync, statSync as statSync7, existsSync as existsSync17 } from "fs";
|
|
73184
|
+
import { join as join15, relative as relative7 } from "path";
|
|
73185
|
+
import { Command as Command35 } from "commander";
|
|
73186
|
+
import chalk43 from "chalk";
|
|
72822
73187
|
import { zipSync } from "fflate";
|
|
72823
|
-
var appsCommand = new
|
|
73188
|
+
var appsCommand = new Command35("apps").description(
|
|
72824
73189
|
"Manage Runtype Apps (hosted AI apps on *.runtype.run)"
|
|
72825
73190
|
);
|
|
72826
73191
|
var MANIFEST_FILENAME = "runtype.app.json";
|
|
@@ -72829,14 +73194,14 @@ function collectBundleFiles(dir) {
|
|
|
72829
73194
|
const walk = (current) => {
|
|
72830
73195
|
for (const entry of readdirSync7(current)) {
|
|
72831
73196
|
if (entry.startsWith(".")) continue;
|
|
72832
|
-
const full =
|
|
73197
|
+
const full = join15(current, entry);
|
|
72833
73198
|
const stat2 = lstatSync(full);
|
|
72834
73199
|
if (stat2.isSymbolicLink()) continue;
|
|
72835
73200
|
if (stat2.isDirectory()) {
|
|
72836
73201
|
if (entry === "node_modules") continue;
|
|
72837
73202
|
walk(full);
|
|
72838
73203
|
} else {
|
|
72839
|
-
zippable[relative7(dir, full).split("\\").join("/")] =
|
|
73204
|
+
zippable[relative7(dir, full).split("\\").join("/")] = readFileSync21(full);
|
|
72840
73205
|
}
|
|
72841
73206
|
}
|
|
72842
73207
|
};
|
|
@@ -72847,7 +73212,7 @@ function fail(message, jsonMode, code) {
|
|
|
72847
73212
|
if (jsonMode) {
|
|
72848
73213
|
printJson({ status: "error", error: message, code });
|
|
72849
73214
|
} else {
|
|
72850
|
-
console.error(
|
|
73215
|
+
console.error(chalk43.red(message));
|
|
72851
73216
|
}
|
|
72852
73217
|
process.exit(1);
|
|
72853
73218
|
}
|
|
@@ -72872,13 +73237,13 @@ appsCommand.command("list").description("List your apps").option("--json", "Stru
|
|
|
72872
73237
|
return;
|
|
72873
73238
|
}
|
|
72874
73239
|
if (data.length === 0) {
|
|
72875
|
-
console.log(
|
|
73240
|
+
console.log(chalk43.yellow("No apps yet. Create one with `runtype apps create`."));
|
|
72876
73241
|
return;
|
|
72877
73242
|
}
|
|
72878
73243
|
for (const app of data) {
|
|
72879
|
-
const status = app.status === "suspended" ?
|
|
72880
|
-
const serving = app.activeVersionId ? "" :
|
|
72881
|
-
console.log(`${
|
|
73244
|
+
const status = app.status === "suspended" ? chalk43.red("suspended") : chalk43.green("active");
|
|
73245
|
+
const serving = app.activeVersionId ? "" : chalk43.dim(" (no active version)");
|
|
73246
|
+
console.log(`${chalk43.bold(app.name)} ${chalk43.dim(app.id)}`);
|
|
72882
73247
|
console.log(` ${app.url} ${status} ${app.visibility}${serving}`);
|
|
72883
73248
|
}
|
|
72884
73249
|
} catch (error51) {
|
|
@@ -72907,9 +73272,9 @@ appsCommand.command("create").description("Create an app (the hostname is {slug}
|
|
|
72907
73272
|
printJson(app);
|
|
72908
73273
|
return;
|
|
72909
73274
|
}
|
|
72910
|
-
console.log(
|
|
73275
|
+
console.log(chalk43.green(`Created ${app.name} (${app.id})`));
|
|
72911
73276
|
console.log(` ${app.url}`);
|
|
72912
|
-
console.log(
|
|
73277
|
+
console.log(chalk43.dim(" Deploy a bundle with `runtype apps deploy <dir> --app " + app.id + "`"));
|
|
72913
73278
|
} catch (error51) {
|
|
72914
73279
|
fail(
|
|
72915
73280
|
`Failed to create app: ${error51 instanceof Error ? error51.message : String(error51)}`,
|
|
@@ -72925,7 +73290,7 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
|
|
|
72925
73290
|
const jsonMode = !!(options.json ?? globals.json);
|
|
72926
73291
|
const apiKey = await ensureAuth();
|
|
72927
73292
|
if (!apiKey) return;
|
|
72928
|
-
if (!
|
|
73293
|
+
if (!existsSync17(dir) || !statSync7(dir).isDirectory()) {
|
|
72929
73294
|
fail(`Not a directory: ${dir}`, jsonMode, "INVALID_DIR");
|
|
72930
73295
|
}
|
|
72931
73296
|
let bundleFiles = {};
|
|
@@ -72955,7 +73320,7 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
|
|
|
72955
73320
|
const client = createCliClient(apiKey);
|
|
72956
73321
|
try {
|
|
72957
73322
|
const zipBytes = zipSync(bundleFiles);
|
|
72958
|
-
if (!jsonMode) console.log(
|
|
73323
|
+
if (!jsonMode) console.log(chalk43.dim(`Uploading ${(zipBytes.byteLength / 1024).toFixed(1)} KB bundle...`));
|
|
72959
73324
|
const version2 = await appsApi.uploadVersion(client, options.app, zipBytes);
|
|
72960
73325
|
let app;
|
|
72961
73326
|
if (options.activate) {
|
|
@@ -72973,8 +73338,8 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
|
|
|
72973
73338
|
activated: false
|
|
72974
73339
|
});
|
|
72975
73340
|
} else {
|
|
72976
|
-
console.error(
|
|
72977
|
-
console.error(
|
|
73341
|
+
console.error(chalk43.red(`Uploaded version ${version2.versionNumber}, but activation failed: ${message}`));
|
|
73342
|
+
console.error(chalk43.dim(` Retry with \`runtype apps activate ${options.app} ${version2.id}\` (no re-upload needed).`));
|
|
72978
73343
|
}
|
|
72979
73344
|
process.exit(1);
|
|
72980
73345
|
}
|
|
@@ -72984,14 +73349,14 @@ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload
|
|
|
72984
73349
|
return;
|
|
72985
73350
|
}
|
|
72986
73351
|
console.log(
|
|
72987
|
-
|
|
73352
|
+
chalk43.green(
|
|
72988
73353
|
`Deployed version ${version2.versionNumber} (${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB)`
|
|
72989
73354
|
)
|
|
72990
73355
|
);
|
|
72991
73356
|
if (app) {
|
|
72992
|
-
console.log(` Live at ${
|
|
73357
|
+
console.log(` Live at ${chalk43.bold(app.url)}`);
|
|
72993
73358
|
} else {
|
|
72994
|
-
console.log(
|
|
73359
|
+
console.log(chalk43.dim(` Uploaded but not activated. Activate with \`runtype apps activate ${options.app} ${version2.id}\``));
|
|
72995
73360
|
}
|
|
72996
73361
|
} catch (error51) {
|
|
72997
73362
|
fail(
|
|
@@ -73015,13 +73380,13 @@ appsCommand.command("versions <appId>").description("List an app's versions, new
|
|
|
73015
73380
|
return;
|
|
73016
73381
|
}
|
|
73017
73382
|
if (data.length === 0) {
|
|
73018
|
-
console.log(
|
|
73383
|
+
console.log(chalk43.yellow("No versions uploaded yet."));
|
|
73019
73384
|
return;
|
|
73020
73385
|
}
|
|
73021
73386
|
for (const version2 of data) {
|
|
73022
|
-
const marker = version2.status === "active" ?
|
|
73387
|
+
const marker = version2.status === "active" ? chalk43.green(" (active)") : "";
|
|
73023
73388
|
console.log(
|
|
73024
|
-
`v${version2.versionNumber} ${
|
|
73389
|
+
`v${version2.versionNumber} ${chalk43.dim(version2.id)} ${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB${marker}`
|
|
73025
73390
|
);
|
|
73026
73391
|
}
|
|
73027
73392
|
} catch (error51) {
|
|
@@ -73044,8 +73409,8 @@ appsCommand.command("activate <appId> <versionId>").description("Activate an upl
|
|
|
73044
73409
|
printJson({ app, version: version2 });
|
|
73045
73410
|
return;
|
|
73046
73411
|
}
|
|
73047
|
-
console.log(
|
|
73048
|
-
console.log(` Live at ${
|
|
73412
|
+
console.log(chalk43.green(`Activated version ${version2.versionNumber}`));
|
|
73413
|
+
console.log(` Live at ${chalk43.bold(app.url)}`);
|
|
73049
73414
|
} catch (error51) {
|
|
73050
73415
|
fail(
|
|
73051
73416
|
`Activation failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
|
|
@@ -73066,7 +73431,7 @@ appsCommand.command("delete <appId>").description("Permanently delete an app, it
|
|
|
73066
73431
|
printJson({ status: "deleted", appId });
|
|
73067
73432
|
return;
|
|
73068
73433
|
}
|
|
73069
|
-
console.log(
|
|
73434
|
+
console.log(chalk43.green(`Deleted ${appId}`));
|
|
73070
73435
|
} catch (error51) {
|
|
73071
73436
|
fail(
|
|
73072
73437
|
`Delete failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
|
|
@@ -73077,17 +73442,17 @@ appsCommand.command("delete <appId>").description("Permanently delete an app, it
|
|
|
73077
73442
|
});
|
|
73078
73443
|
|
|
73079
73444
|
// src/commands/update.ts
|
|
73080
|
-
import
|
|
73081
|
-
import { Command as
|
|
73445
|
+
import chalk45 from "chalk";
|
|
73446
|
+
import { Command as Command36 } from "commander";
|
|
73082
73447
|
|
|
73083
73448
|
// src/lib/auto-update.ts
|
|
73084
73449
|
import { spawn as spawn2 } from "child_process";
|
|
73085
73450
|
import {
|
|
73086
73451
|
closeSync,
|
|
73087
|
-
existsSync as
|
|
73452
|
+
existsSync as existsSync18,
|
|
73088
73453
|
mkdirSync as mkdirSync12,
|
|
73089
73454
|
openSync,
|
|
73090
|
-
readFileSync as
|
|
73455
|
+
readFileSync as readFileSync22,
|
|
73091
73456
|
readdirSync as readdirSync8,
|
|
73092
73457
|
realpathSync as realpathSync3,
|
|
73093
73458
|
renameSync,
|
|
@@ -73096,10 +73461,10 @@ import {
|
|
|
73096
73461
|
writeFileSync as writeFileSync10
|
|
73097
73462
|
} from "fs";
|
|
73098
73463
|
import { constants as osConstants } from "os";
|
|
73099
|
-
import { dirname as dirname10, isAbsolute as isAbsolute4, join as
|
|
73464
|
+
import { dirname as dirname10, isAbsolute as isAbsolute4, join as join16, relative as relative8, resolve as resolve12, sep as sep6 } from "path";
|
|
73100
73465
|
|
|
73101
73466
|
// src/lib/update-check.ts
|
|
73102
|
-
import
|
|
73467
|
+
import chalk44 from "chalk";
|
|
73103
73468
|
import Conf3 from "conf";
|
|
73104
73469
|
var UPDATE_CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
73105
73470
|
var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -73193,7 +73558,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
|
|
|
73193
73558
|
console.error(message);
|
|
73194
73559
|
});
|
|
73195
73560
|
notify(
|
|
73196
|
-
`${
|
|
73561
|
+
`${chalk44.yellow("Update available:")} ${chalk44.red(currentVersion)} ${chalk44.gray("->")} ${chalk44.green(latestVersion)} ${chalk44.gray(`(${getUpgradeCommand()})`)}`
|
|
73197
73562
|
);
|
|
73198
73563
|
store.set("lastNotifiedAt", now.toISOString());
|
|
73199
73564
|
store.set("lastNotifiedVersion", latestVersion);
|
|
@@ -73252,32 +73617,32 @@ function isStableCliVersion(version2) {
|
|
|
73252
73617
|
return Boolean(version2 && /^\d+\.\d+\.\d+$/.test(version2));
|
|
73253
73618
|
}
|
|
73254
73619
|
function getManagedCliPaths(homeDir = getRuntypeHomeDir()) {
|
|
73255
|
-
const root =
|
|
73620
|
+
const root = join16(homeDir, "cli");
|
|
73256
73621
|
return {
|
|
73257
73622
|
home: homeDir,
|
|
73258
73623
|
root,
|
|
73259
|
-
versions:
|
|
73260
|
-
state:
|
|
73261
|
-
lock:
|
|
73262
|
-
log:
|
|
73624
|
+
versions: join16(root, "versions"),
|
|
73625
|
+
state: join16(root, "current.json"),
|
|
73626
|
+
lock: join16(root, "update.lock"),
|
|
73627
|
+
log: join16(root, "update.log")
|
|
73263
73628
|
};
|
|
73264
73629
|
}
|
|
73265
73630
|
function getVersionRoot(paths, version2) {
|
|
73266
73631
|
if (!isStableCliVersion(version2)) {
|
|
73267
73632
|
throw new Error(`Invalid CLI version: ${version2}`);
|
|
73268
73633
|
}
|
|
73269
|
-
return
|
|
73634
|
+
return join16(paths.versions, version2);
|
|
73270
73635
|
}
|
|
73271
73636
|
function getVersionPackageRoot(paths, version2) {
|
|
73272
|
-
return
|
|
73637
|
+
return join16(getVersionRoot(paths, version2), "node_modules", "@runtypelabs", "cli");
|
|
73273
73638
|
}
|
|
73274
73639
|
function getVersionEntrypoint(paths, version2) {
|
|
73275
|
-
return
|
|
73640
|
+
return join16(getVersionPackageRoot(paths, version2), "dist", "index.js");
|
|
73276
73641
|
}
|
|
73277
73642
|
function getManagedCliState(homeDir = getRuntypeHomeDir()) {
|
|
73278
73643
|
const { state } = getManagedCliPaths(homeDir);
|
|
73279
73644
|
try {
|
|
73280
|
-
const parsed = JSON.parse(
|
|
73645
|
+
const parsed = JSON.parse(readFileSync22(state, "utf8"));
|
|
73281
73646
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
73282
73647
|
} catch {
|
|
73283
73648
|
return {};
|
|
@@ -73296,7 +73661,7 @@ function writeManagedCliState(paths, state) {
|
|
|
73296
73661
|
}
|
|
73297
73662
|
function readInstalledPackageVersion(packageRoot) {
|
|
73298
73663
|
try {
|
|
73299
|
-
const pkg = JSON.parse(
|
|
73664
|
+
const pkg = JSON.parse(readFileSync22(join16(packageRoot, "package.json"), "utf8"));
|
|
73300
73665
|
if (pkg.name === CLI_PACKAGE_NAME && isStableCliVersion(pkg.version)) {
|
|
73301
73666
|
return pkg.version;
|
|
73302
73667
|
}
|
|
@@ -73307,7 +73672,7 @@ function readInstalledPackageVersion(packageRoot) {
|
|
|
73307
73672
|
function isHealthyManagedVersion(paths, version2) {
|
|
73308
73673
|
if (!isStableCliVersion(version2)) return false;
|
|
73309
73674
|
const packageRoot = getVersionPackageRoot(paths, version2);
|
|
73310
|
-
return readInstalledPackageVersion(packageRoot) === version2 &&
|
|
73675
|
+
return readInstalledPackageVersion(packageRoot) === version2 && existsSync18(getVersionEntrypoint(paths, version2));
|
|
73311
73676
|
}
|
|
73312
73677
|
function isPathInside(parent, child) {
|
|
73313
73678
|
const canonicalize = (path20) => {
|
|
@@ -73323,7 +73688,7 @@ function isPathInside(parent, child) {
|
|
|
73323
73688
|
function isSourceCheckout(entrypoint) {
|
|
73324
73689
|
let current = dirname10(entrypoint);
|
|
73325
73690
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
73326
|
-
if (
|
|
73691
|
+
if (existsSync18(join16(current, ".git")) || existsSync18(join16(current, "pnpm-workspace.yaml"))) {
|
|
73327
73692
|
return true;
|
|
73328
73693
|
}
|
|
73329
73694
|
const parent = dirname10(current);
|
|
@@ -73335,7 +73700,7 @@ function isSourceCheckout(entrypoint) {
|
|
|
73335
73700
|
function findProjectRoot(cwd) {
|
|
73336
73701
|
let current = resolve12(cwd);
|
|
73337
73702
|
while (true) {
|
|
73338
|
-
if (
|
|
73703
|
+
if (existsSync18(join16(current, "package.json")) || existsSync18(join16(current, "pnpm-workspace.yaml"))) {
|
|
73339
73704
|
return current;
|
|
73340
73705
|
}
|
|
73341
73706
|
const parent = dirname10(current);
|
|
@@ -73353,7 +73718,7 @@ function shouldManageInstalledCli(context = {}) {
|
|
|
73353
73718
|
const env = context.env ?? process.env;
|
|
73354
73719
|
const entrypoint = context.entrypoint ?? process.argv[1];
|
|
73355
73720
|
const cwd = context.cwd ?? process.cwd();
|
|
73356
|
-
if (!entrypoint || !
|
|
73721
|
+
if (!entrypoint || !existsSync18(entrypoint)) return false;
|
|
73357
73722
|
if (env.NODE_ENV === "test" || Boolean(env.CI)) return false;
|
|
73358
73723
|
if (env.RUNTYPE_DISABLE_AUTO_UPDATE === "true") return false;
|
|
73359
73724
|
if (isEphemeralPackageRun(entrypoint, env)) return false;
|
|
@@ -73553,7 +73918,7 @@ async function installAndActivateCliVersion(version2, options = {}) {
|
|
|
73553
73918
|
if (!releaseLock) return "busy";
|
|
73554
73919
|
const commandRunner = options.commandRunner ?? defaultCommandRunner;
|
|
73555
73920
|
const finalRoot = getVersionRoot(paths, version2);
|
|
73556
|
-
const temporaryRoot =
|
|
73921
|
+
const temporaryRoot = join16(paths.versions, `.${version2}-${process.pid}-${now.getTime()}`);
|
|
73557
73922
|
let installed = false;
|
|
73558
73923
|
try {
|
|
73559
73924
|
mkdirSync12(paths.versions, { recursive: true });
|
|
@@ -73583,9 +73948,9 @@ async function installAndActivateCliVersion(version2, options = {}) {
|
|
|
73583
73948
|
if (installResult.status !== 0) {
|
|
73584
73949
|
throw installResult.error ?? new Error(`npm install exited with ${installResult.status}`);
|
|
73585
73950
|
}
|
|
73586
|
-
const temporaryPackageRoot =
|
|
73587
|
-
const temporaryEntrypoint =
|
|
73588
|
-
if (readInstalledPackageVersion(temporaryPackageRoot) !== version2 || !
|
|
73951
|
+
const temporaryPackageRoot = join16(temporaryRoot, "node_modules", "@runtypelabs", "cli");
|
|
73952
|
+
const temporaryEntrypoint = join16(temporaryPackageRoot, "dist", "index.js");
|
|
73953
|
+
if (readInstalledPackageVersion(temporaryPackageRoot) !== version2 || !existsSync18(temporaryEntrypoint)) {
|
|
73589
73954
|
throw new Error(
|
|
73590
73955
|
`Installed package did not contain a healthy ${CLI_PACKAGE_NAME}@${version2}`
|
|
73591
73956
|
);
|
|
@@ -73610,7 +73975,7 @@ async function installAndActivateCliVersion(version2, options = {}) {
|
|
|
73610
73975
|
`Installed CLI verification failed (expected ${version2}, got ${verifyResult.stdout.trim() || "no version"})`
|
|
73611
73976
|
);
|
|
73612
73977
|
}
|
|
73613
|
-
if (
|
|
73978
|
+
if (existsSync18(finalRoot)) {
|
|
73614
73979
|
const corruptRoot = `${finalRoot}.replaced-${now.getTime()}`;
|
|
73615
73980
|
renameSync(finalRoot, corruptRoot);
|
|
73616
73981
|
try {
|
|
@@ -73657,7 +74022,7 @@ function isAutoUpdateWorkerInvocation(args, env = process.env) {
|
|
|
73657
74022
|
function spawnAutoUpdateWorker(version2, context = {}) {
|
|
73658
74023
|
if (!isStableCliVersion(version2)) return false;
|
|
73659
74024
|
const entrypoint = context.entrypoint ?? process.argv[1];
|
|
73660
|
-
if (!entrypoint || !
|
|
74025
|
+
if (!entrypoint || !existsSync18(entrypoint)) return false;
|
|
73661
74026
|
const paths = getManagedCliPaths();
|
|
73662
74027
|
mkdirSync12(paths.root, { recursive: true });
|
|
73663
74028
|
const logDescriptor = openSync(paths.log, "a", 384);
|
|
@@ -73749,9 +74114,9 @@ function rollbackManagedCli(homeDir = getRuntypeHomeDir()) {
|
|
|
73749
74114
|
}
|
|
73750
74115
|
|
|
73751
74116
|
// src/commands/update.ts
|
|
73752
|
-
var updateCommand = new
|
|
74117
|
+
var updateCommand = new Command36("update").description("Check for, install, or roll back CLI updates").option("--check", "Check for an update without installing it").option("--rollback", "Roll back the most recent managed update").action(async (options) => {
|
|
73753
74118
|
if (options.check && options.rollback) {
|
|
73754
|
-
console.error(
|
|
74119
|
+
console.error(chalk45.red("Use either --check or --rollback, not both"));
|
|
73755
74120
|
process.exitCode = 1;
|
|
73756
74121
|
return;
|
|
73757
74122
|
}
|
|
@@ -73759,10 +74124,10 @@ var updateCommand = new Command35("update").description("Check for, install, or
|
|
|
73759
74124
|
try {
|
|
73760
74125
|
const result = rollbackManagedCli();
|
|
73761
74126
|
const target = result.to ?? "the package-manager-installed version";
|
|
73762
|
-
console.log(
|
|
73763
|
-
console.log(
|
|
74127
|
+
console.log(chalk45.green(`Rolled back ${result.from} -> ${target}`));
|
|
74128
|
+
console.log(chalk45.gray("The rollback will be used on the next invocation."));
|
|
73764
74129
|
} catch (error51) {
|
|
73765
|
-
console.error(
|
|
74130
|
+
console.error(chalk45.red(error51 instanceof Error ? error51.message : String(error51)));
|
|
73766
74131
|
process.exitCode = 1;
|
|
73767
74132
|
}
|
|
73768
74133
|
return;
|
|
@@ -73770,19 +74135,19 @@ var updateCommand = new Command35("update").description("Check for, install, or
|
|
|
73770
74135
|
const currentVersion = getCliVersion();
|
|
73771
74136
|
const latestVersion = await refreshCliUpdateMetadata({ force: true });
|
|
73772
74137
|
if (!latestVersion) {
|
|
73773
|
-
console.error(
|
|
74138
|
+
console.error(chalk45.red("Unable to determine the latest CLI version from npm"));
|
|
73774
74139
|
process.exitCode = 1;
|
|
73775
74140
|
return;
|
|
73776
74141
|
}
|
|
73777
74142
|
const comparison = compareVersions(latestVersion, currentVersion);
|
|
73778
74143
|
if (comparison <= 0) {
|
|
73779
74144
|
const status = comparison === 0 ? "up to date" : "newer than the latest published version";
|
|
73780
|
-
console.log(
|
|
74145
|
+
console.log(chalk45.green(`Runtype CLI ${currentVersion} is ${status}.`));
|
|
73781
74146
|
return;
|
|
73782
74147
|
}
|
|
73783
74148
|
if (options.check) {
|
|
73784
74149
|
console.log(
|
|
73785
|
-
`${
|
|
74150
|
+
`${chalk45.yellow("Update available:")} ${chalk45.red(currentVersion)} ${chalk45.gray("->")} ${chalk45.green(latestVersion)}`
|
|
73786
74151
|
);
|
|
73787
74152
|
return;
|
|
73788
74153
|
}
|
|
@@ -73790,22 +74155,22 @@ var updateCommand = new Command35("update").description("Check for, install, or
|
|
|
73790
74155
|
try {
|
|
73791
74156
|
const result = await installAndActivateCliVersion(latestVersion);
|
|
73792
74157
|
if (result === "busy") {
|
|
73793
|
-
console.log(
|
|
74158
|
+
console.log(chalk45.yellow("Another CLI update is already in progress."));
|
|
73794
74159
|
return;
|
|
73795
74160
|
}
|
|
73796
|
-
console.log(
|
|
73797
|
-
console.log(
|
|
74161
|
+
console.log(chalk45.green(`Runtype CLI ${latestVersion} is ready.`));
|
|
74162
|
+
console.log(chalk45.gray("It will be used on the next invocation."));
|
|
73798
74163
|
} catch (error51) {
|
|
73799
74164
|
console.error(
|
|
73800
|
-
|
|
74165
|
+
chalk45.red(`CLI update failed: ${error51 instanceof Error ? error51.message : error51}`)
|
|
73801
74166
|
);
|
|
73802
74167
|
process.exitCode = 1;
|
|
73803
74168
|
}
|
|
73804
74169
|
});
|
|
73805
74170
|
|
|
73806
74171
|
// src/commands/mcp.ts
|
|
73807
|
-
import { Command as
|
|
73808
|
-
import
|
|
74172
|
+
import { Command as Command37, InvalidArgumentError } from "commander";
|
|
74173
|
+
import chalk46 from "chalk";
|
|
73809
74174
|
|
|
73810
74175
|
// src/lib/mcp-client.ts
|
|
73811
74176
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -74024,7 +74389,7 @@ async function resolveMcpArguments(options, dependencies = {}) {
|
|
|
74024
74389
|
}
|
|
74025
74390
|
|
|
74026
74391
|
// src/commands/mcp.ts
|
|
74027
|
-
var
|
|
74392
|
+
var defaultDependencies2 = {
|
|
74028
74393
|
ensureAuth,
|
|
74029
74394
|
connect: connectMcpClient,
|
|
74030
74395
|
resolveArguments: resolveMcpArguments,
|
|
@@ -74073,16 +74438,16 @@ async function withMcpClient(options, dependencies, operation, authOptions) {
|
|
|
74073
74438
|
}
|
|
74074
74439
|
function printTools(tools, target) {
|
|
74075
74440
|
if (tools.length === 0) {
|
|
74076
|
-
console.log(
|
|
74441
|
+
console.log(chalk46.gray("No MCP tools found"));
|
|
74077
74442
|
return;
|
|
74078
74443
|
}
|
|
74079
74444
|
const label = target === "code" ? "Code Mode MCP Tools" : "MCP Tools";
|
|
74080
|
-
console.log(
|
|
74445
|
+
console.log(chalk46.cyan(`${label}:`));
|
|
74081
74446
|
for (const tool of tools) {
|
|
74082
74447
|
const description = tool.description?.split("\n", 1)[0];
|
|
74083
|
-
console.log(` ${
|
|
74448
|
+
console.log(` ${chalk46.green(tool.name)}${description ? chalk46.gray(` \u2014 ${description}`) : ""}`);
|
|
74084
74449
|
}
|
|
74085
|
-
console.log(
|
|
74450
|
+
console.log(chalk46.dim(`
|
|
74086
74451
|
Total: ${tools.length} tools`));
|
|
74087
74452
|
}
|
|
74088
74453
|
function printTool(tool) {
|
|
@@ -74112,8 +74477,8 @@ function printCallResult(result, json2) {
|
|
|
74112
74477
|
printJson(result);
|
|
74113
74478
|
}
|
|
74114
74479
|
function createMcpCommand(overrides = {}) {
|
|
74115
|
-
const dependencies = { ...
|
|
74116
|
-
const command = new
|
|
74480
|
+
const dependencies = { ...defaultDependencies2, ...overrides };
|
|
74481
|
+
const command = new Command37("mcp").description(
|
|
74117
74482
|
"Discover and call tools on the Runtype MCP servers"
|
|
74118
74483
|
);
|
|
74119
74484
|
addCommonOptions(
|
|
@@ -74126,7 +74491,7 @@ function createMcpCommand(overrides = {}) {
|
|
|
74126
74491
|
else printTools(tools, options.server);
|
|
74127
74492
|
});
|
|
74128
74493
|
} catch (error51) {
|
|
74129
|
-
console.error(
|
|
74494
|
+
console.error(chalk46.red(`Failed to list MCP tools: ${errorMessage(error51)}`));
|
|
74130
74495
|
dependencies.setExitCode(1);
|
|
74131
74496
|
}
|
|
74132
74497
|
});
|
|
@@ -74144,7 +74509,7 @@ function createMcpCommand(overrides = {}) {
|
|
|
74144
74509
|
else printTool(tool);
|
|
74145
74510
|
});
|
|
74146
74511
|
} catch (error51) {
|
|
74147
|
-
console.error(
|
|
74512
|
+
console.error(chalk46.red(`Failed to inspect MCP tool: ${errorMessage(error51)}`));
|
|
74148
74513
|
dependencies.setExitCode(1);
|
|
74149
74514
|
}
|
|
74150
74515
|
});
|
|
@@ -74182,7 +74547,7 @@ function createMcpCommand(overrides = {}) {
|
|
|
74182
74547
|
usesMcpStdin(options) ? { interactive: false, exitOnFailure: false } : void 0
|
|
74183
74548
|
);
|
|
74184
74549
|
} catch (error51) {
|
|
74185
|
-
console.error(
|
|
74550
|
+
console.error(chalk46.red(`MCP tool call failed: ${errorMessage(error51)}`));
|
|
74186
74551
|
dependencies.setExitCode(1);
|
|
74187
74552
|
}
|
|
74188
74553
|
});
|
|
@@ -74193,8 +74558,8 @@ var mcpCommand = createMcpCommand();
|
|
|
74193
74558
|
// src/commands/devices.ts
|
|
74194
74559
|
import { spawn as spawn4 } from "child_process";
|
|
74195
74560
|
import { readFile as readFile2 } from "fs/promises";
|
|
74196
|
-
import { Command as
|
|
74197
|
-
import
|
|
74561
|
+
import { Command as Command38 } from "commander";
|
|
74562
|
+
import chalk47 from "chalk";
|
|
74198
74563
|
|
|
74199
74564
|
// src/lib/device-provider.ts
|
|
74200
74565
|
var DEVICE_SIDECAR_PROTOCOL_VERSION = 1;
|
|
@@ -74582,7 +74947,7 @@ var MacOSDeviceProvider = class {
|
|
|
74582
74947
|
};
|
|
74583
74948
|
|
|
74584
74949
|
// src/commands/devices.ts
|
|
74585
|
-
var
|
|
74950
|
+
var defaultDependencies3 = {
|
|
74586
74951
|
ensureAuth,
|
|
74587
74952
|
createClient: (apiKey) => createCliClient(apiKey),
|
|
74588
74953
|
createProvider: () => new MacOSDeviceProvider(),
|
|
@@ -74614,8 +74979,8 @@ function isRecordedRevocationError(error51) {
|
|
|
74614
74979
|
return detail.toLowerCase().includes("revocation was recorded");
|
|
74615
74980
|
}
|
|
74616
74981
|
function printCommandError(label, error51) {
|
|
74617
|
-
console.error(
|
|
74618
|
-
console.error(
|
|
74982
|
+
console.error(chalk47.red(label));
|
|
74983
|
+
console.error(chalk47.red(errorMessage2(error51)));
|
|
74619
74984
|
}
|
|
74620
74985
|
function printDevice(device) {
|
|
74621
74986
|
printDetail("Runtype Device", [
|
|
@@ -74665,8 +75030,8 @@ async function runTail2(logPath, lines) {
|
|
|
74665
75030
|
});
|
|
74666
75031
|
}
|
|
74667
75032
|
function createDevicesCommand(overrides = {}) {
|
|
74668
|
-
const dependencies = { ...
|
|
74669
|
-
const command = new
|
|
75033
|
+
const dependencies = { ...defaultDependencies3, ...overrides };
|
|
75034
|
+
const command = new Command38("devices").description(
|
|
74670
75035
|
"Manage local computers connected to Runtype agents"
|
|
74671
75036
|
);
|
|
74672
75037
|
command.command("setup").description("Install, pair, and start Runtype Device on this Mac").option("--name <name>", "Device name shown in Runtype").option("--helper-path <path>", "Install a locally built native helper (internal alpha)").option("--json", "Output as JSON").action(async (options) => {
|
|
@@ -74710,26 +75075,26 @@ function createDevicesCommand(overrides = {}) {
|
|
|
74710
75075
|
printJson(result);
|
|
74711
75076
|
return;
|
|
74712
75077
|
}
|
|
74713
|
-
console.log(
|
|
74714
|
-
console.log(` Device ID: ${
|
|
75078
|
+
console.log(chalk47.green(`Paired and started ${paired.name}`));
|
|
75079
|
+
console.log(` Device ID: ${chalk47.green(paired.deviceId)}`);
|
|
74715
75080
|
console.log(
|
|
74716
|
-
` Relay: ${device?.status?.online ?
|
|
75081
|
+
` Relay: ${device?.status?.online ? chalk47.green("online") : chalk47.yellow("connecting")}`
|
|
74717
75082
|
);
|
|
74718
75083
|
if (device?.mcpUrl) console.log(` MCP URL: ${device.mcpUrl}`);
|
|
74719
75084
|
if (local.messagesDatabaseReadable !== true) {
|
|
74720
75085
|
console.log(
|
|
74721
|
-
|
|
75086
|
+
chalk47.yellow(
|
|
74722
75087
|
`
|
|
74723
75088
|
Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage reads.`
|
|
74724
75089
|
)
|
|
74725
75090
|
);
|
|
74726
75091
|
}
|
|
74727
|
-
console.log(
|
|
75092
|
+
console.log(chalk47.gray("iMessage sending remains disabled by local policy."));
|
|
74728
75093
|
} catch (error51) {
|
|
74729
75094
|
printCommandError("Failed to set up Runtype Device", error51);
|
|
74730
75095
|
if (pairedDeviceId) {
|
|
74731
75096
|
console.error(
|
|
74732
|
-
|
|
75097
|
+
chalk47.yellow(
|
|
74733
75098
|
`Pairing completed as ${pairedDeviceId}, but startup did not finish. Run \`runtype devices install\` after correcting the error.`
|
|
74734
75099
|
)
|
|
74735
75100
|
);
|
|
@@ -74745,7 +75110,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74745
75110
|
if (options.json) {
|
|
74746
75111
|
printJson({ installation, service });
|
|
74747
75112
|
} else {
|
|
74748
|
-
console.log(
|
|
75113
|
+
console.log(chalk47.green("Runtype Device is installed and running"));
|
|
74749
75114
|
console.log(` Helper: ${installation.binaryPath}`);
|
|
74750
75115
|
if (typeof service.logPath === "string") console.log(` Logs: ${service.logPath}`);
|
|
74751
75116
|
}
|
|
@@ -74764,13 +75129,13 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74764
75129
|
return;
|
|
74765
75130
|
}
|
|
74766
75131
|
if (devices.length === 0) {
|
|
74767
|
-
console.log(
|
|
75132
|
+
console.log(chalk47.gray("No paired devices"));
|
|
74768
75133
|
return;
|
|
74769
75134
|
}
|
|
74770
|
-
console.log(
|
|
75135
|
+
console.log(chalk47.cyan("Runtype Devices:"));
|
|
74771
75136
|
for (const device of devices) {
|
|
74772
75137
|
const state = device.revokedAt ? "revoked" : device.status?.online ? "online" : "offline";
|
|
74773
|
-
console.log(` ${
|
|
75138
|
+
console.log(` ${chalk47.green(device.id)} ${device.name} ${state}`);
|
|
74774
75139
|
}
|
|
74775
75140
|
} catch (error51) {
|
|
74776
75141
|
printCommandError("Failed to list Runtype devices", error51);
|
|
@@ -74821,7 +75186,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74821
75186
|
printJson(result);
|
|
74822
75187
|
} else {
|
|
74823
75188
|
console.log(
|
|
74824
|
-
healthy ?
|
|
75189
|
+
healthy ? chalk47.green("Runtype Device is healthy") : chalk47.yellow("Runtype Device needs attention")
|
|
74825
75190
|
);
|
|
74826
75191
|
console.log(` Platform supported: ${probe.supported ? "yes" : "no"}`);
|
|
74827
75192
|
console.log(` Helper installed: ${probe.installed ? "yes" : "no"}`);
|
|
@@ -74833,7 +75198,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74833
75198
|
);
|
|
74834
75199
|
if (local.messagesDatabaseReadable !== true) {
|
|
74835
75200
|
console.log(
|
|
74836
|
-
|
|
75201
|
+
chalk47.yellow(` Grant Full Disk Access to ${String(local.executablePath)}`)
|
|
74837
75202
|
);
|
|
74838
75203
|
}
|
|
74839
75204
|
}
|
|
@@ -74846,7 +75211,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74846
75211
|
});
|
|
74847
75212
|
command.command("policy <mode>").description("Set local iMessage send policy (allow-send or deny-send)").option("--json", "Output as JSON").action(async (mode, options) => {
|
|
74848
75213
|
if (mode !== "allow-send" && mode !== "deny-send") {
|
|
74849
|
-
console.error(
|
|
75214
|
+
console.error(chalk47.red("Policy must be allow-send or deny-send"));
|
|
74850
75215
|
dependencies.setExitCode(1);
|
|
74851
75216
|
return;
|
|
74852
75217
|
}
|
|
@@ -74867,15 +75232,15 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74867
75232
|
if (options.json) printJson(result);
|
|
74868
75233
|
else {
|
|
74869
75234
|
console.log(
|
|
74870
|
-
|
|
75235
|
+
chalk47.green(
|
|
74871
75236
|
`Local iMessage sending is ${mode === "allow-send" ? "enabled" : "disabled"}`
|
|
74872
75237
|
)
|
|
74873
75238
|
);
|
|
74874
75239
|
if (service)
|
|
74875
|
-
console.log(
|
|
75240
|
+
console.log(chalk47.gray("Restarted the device service to publish capabilities."));
|
|
74876
75241
|
else {
|
|
74877
75242
|
console.log(
|
|
74878
|
-
|
|
75243
|
+
chalk47.yellow(
|
|
74879
75244
|
"The device service is not installed; run `runtype devices install` to publish this policy."
|
|
74880
75245
|
)
|
|
74881
75246
|
);
|
|
@@ -74906,7 +75271,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74906
75271
|
});
|
|
74907
75272
|
command.command("revoke <id>").description("Revoke a paired device in Runtype").option("--yes", "Confirm irreversible device revocation").option("--json", "Output as JSON").action(async (id, options) => {
|
|
74908
75273
|
if (!options.yes) {
|
|
74909
|
-
console.error(
|
|
75274
|
+
console.error(chalk47.red("Pass --yes to confirm irreversible device revocation"));
|
|
74910
75275
|
dependencies.setExitCode(1);
|
|
74911
75276
|
return;
|
|
74912
75277
|
}
|
|
@@ -74918,8 +75283,8 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74918
75283
|
);
|
|
74919
75284
|
if (options.json) printJson(device);
|
|
74920
75285
|
else {
|
|
74921
|
-
console.log(
|
|
74922
|
-
console.log(
|
|
75286
|
+
console.log(chalk47.green(`Revoked ${device.name} (${device.id})`));
|
|
75287
|
+
console.log(chalk47.gray("If this is the local Mac, run `runtype devices reset --yes`."));
|
|
74923
75288
|
}
|
|
74924
75289
|
} catch (error51) {
|
|
74925
75290
|
if (isRecordedRevocationError(error51)) {
|
|
@@ -74932,12 +75297,12 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74932
75297
|
if (options.json) printJson(result);
|
|
74933
75298
|
else {
|
|
74934
75299
|
console.error(
|
|
74935
|
-
|
|
75300
|
+
chalk47.yellow(
|
|
74936
75301
|
`Revocation was recorded for ${id}, but relay disconnection was not confirmed.`
|
|
74937
75302
|
)
|
|
74938
75303
|
);
|
|
74939
75304
|
console.error(
|
|
74940
|
-
|
|
75305
|
+
chalk47.yellow("Retry this command, and reset the local Mac if applicable.")
|
|
74941
75306
|
);
|
|
74942
75307
|
}
|
|
74943
75308
|
dependencies.setExitCode(1);
|
|
@@ -74970,7 +75335,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74970
75335
|
if (entries.at(-1) === "") entries.pop();
|
|
74971
75336
|
const selected = entries.slice(-lines).join("\n");
|
|
74972
75337
|
if (selected) console.log(selected);
|
|
74973
|
-
else console.log(
|
|
75338
|
+
else console.log(chalk47.gray("No local device logs yet"));
|
|
74974
75339
|
} catch (error51) {
|
|
74975
75340
|
printCommandError("Failed to read Runtype Device logs", error51);
|
|
74976
75341
|
dependencies.setExitCode(1);
|
|
@@ -74982,7 +75347,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74982
75347
|
const service = await provider.invoke("uninstall");
|
|
74983
75348
|
const removedBinary = options.removeBinary ? await provider.removeInstalledBinary() : false;
|
|
74984
75349
|
if (options.json) printJson({ service, removedBinary });
|
|
74985
|
-
else console.log(
|
|
75350
|
+
else console.log(chalk47.green("Stopped and uninstalled the local Runtype Device service"));
|
|
74986
75351
|
} catch (error51) {
|
|
74987
75352
|
printCommandError("Failed to uninstall Runtype Device", error51);
|
|
74988
75353
|
dependencies.setExitCode(1);
|
|
@@ -74990,7 +75355,7 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74990
75355
|
});
|
|
74991
75356
|
command.command("reset").description("Clear local pairing state and rotate the native signing identity").option("--yes", "Confirm destructive local reset").option("--json", "Output as JSON").action(async (options) => {
|
|
74992
75357
|
if (!options.yes) {
|
|
74993
|
-
console.error(
|
|
75358
|
+
console.error(chalk47.red("Pass --yes to confirm destructive local reset"));
|
|
74994
75359
|
dependencies.setExitCode(1);
|
|
74995
75360
|
return;
|
|
74996
75361
|
}
|
|
@@ -74998,9 +75363,9 @@ Grant Full Disk Access to ${String(local.executablePath)} to enable iMessage rea
|
|
|
74998
75363
|
const result = await dependencies.createProvider().invoke("reset", { rotateIdentity: true });
|
|
74999
75364
|
if (options.json) printJson(result);
|
|
75000
75365
|
else {
|
|
75001
|
-
console.log(
|
|
75366
|
+
console.log(chalk47.green("Cleared local device state and rotated the signing identity"));
|
|
75002
75367
|
console.log(
|
|
75003
|
-
|
|
75368
|
+
chalk47.gray("Revoke the old device in Runtype if it has not already been revoked.")
|
|
75004
75369
|
);
|
|
75005
75370
|
}
|
|
75006
75371
|
} catch (error51) {
|
|
@@ -75031,7 +75396,7 @@ function registerGlobalOptionForwarding(program2) {
|
|
|
75031
75396
|
// src/index.ts
|
|
75032
75397
|
loadEnv();
|
|
75033
75398
|
setCliTitle();
|
|
75034
|
-
var program = new
|
|
75399
|
+
var program = new Command39();
|
|
75035
75400
|
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 as JSON");
|
|
75036
75401
|
program.addCommand(initCommand);
|
|
75037
75402
|
program.addCommand(loginCommand);
|
|
@@ -75068,6 +75433,7 @@ program.addCommand(deployCommand);
|
|
|
75068
75433
|
program.addCommand(skillsCommand);
|
|
75069
75434
|
program.addCommand(updateCommand);
|
|
75070
75435
|
program.addCommand(installMcpCommand);
|
|
75436
|
+
program.addCommand(onboardCommand);
|
|
75071
75437
|
program.addCommand(mcpCommand);
|
|
75072
75438
|
program.addCommand(devicesCommand);
|
|
75073
75439
|
program.addCommand(appsCommand, { hidden: process.env.RUNTYPE_APPS_CLI !== "1" });
|
|
@@ -75102,17 +75468,17 @@ async function run() {
|
|
|
75102
75468
|
run().catch((error51) => {
|
|
75103
75469
|
const commanderError = error51;
|
|
75104
75470
|
if (commanderError.code === "commander.missingArgument") {
|
|
75105
|
-
console.error(
|
|
75471
|
+
console.error(chalk48.red(`Error: ${commanderError.message}`));
|
|
75106
75472
|
process.exit(1);
|
|
75107
75473
|
} else if (commanderError.code === "commander.unknownOption") {
|
|
75108
|
-
console.error(
|
|
75474
|
+
console.error(chalk48.red(`Error: ${commanderError.message}`));
|
|
75109
75475
|
process.exit(1);
|
|
75110
75476
|
} else if (commanderError.code === "commander.unknownCommand") {
|
|
75111
75477
|
process.exit(1);
|
|
75112
75478
|
} else if (commanderError.code === "commander.help" || commanderError.code === "commander.helpDisplayed" || commanderError.code === "commander.version") {
|
|
75113
75479
|
process.exit(0);
|
|
75114
75480
|
} else {
|
|
75115
|
-
console.error(
|
|
75481
|
+
console.error(chalk48.red("An unexpected error occurred:"));
|
|
75116
75482
|
console.error(error51);
|
|
75117
75483
|
process.exit(1);
|
|
75118
75484
|
}
|
|
@@ -75121,12 +75487,12 @@ async function handleNoCommand() {
|
|
|
75121
75487
|
const store = new CredentialStore();
|
|
75122
75488
|
const hasCredentials = await store.hasCredentials();
|
|
75123
75489
|
if (!hasCredentials) {
|
|
75124
|
-
console.log(
|
|
75490
|
+
console.log(chalk48.cyan("\nWelcome to Runtype CLI!\n"));
|
|
75125
75491
|
console.log("It looks like this is your first time. Run the setup wizard:");
|
|
75126
|
-
console.log(` ${
|
|
75492
|
+
console.log(` ${chalk48.green("runtype init")}
|
|
75127
75493
|
`);
|
|
75128
75494
|
console.log("Or see all available commands:");
|
|
75129
|
-
console.log(` ${
|
|
75495
|
+
console.log(` ${chalk48.green("runtype --help")}
|
|
75130
75496
|
`);
|
|
75131
75497
|
} else {
|
|
75132
75498
|
try {
|