@thyme-sh/cli 0.2.0 → 0.3.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 +56 -62
- package/dist/index.js.map +1 -1
- package/package.json +11 -2
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ function step(message) {
|
|
|
30
30
|
clack.log.step(message);
|
|
31
31
|
}
|
|
32
32
|
function log2(message) {
|
|
33
|
-
|
|
33
|
+
clack.log.message(message);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// src/commands/init.ts
|
|
@@ -215,7 +215,7 @@ async function listCommand() {
|
|
|
215
215
|
}
|
|
216
216
|
step(`Found ${tasks.length} task(s):`);
|
|
217
217
|
for (const task of tasks) {
|
|
218
|
-
|
|
218
|
+
clack.log.message(` ${pc.cyan("\u25CF")} ${task}`);
|
|
219
219
|
}
|
|
220
220
|
outro2("");
|
|
221
221
|
}
|
|
@@ -446,7 +446,7 @@ Next steps:
|
|
|
446
446
|
// src/commands/run.ts
|
|
447
447
|
import { existsSync as existsSync6 } from "fs";
|
|
448
448
|
import { readFile as readFile2 } from "fs/promises";
|
|
449
|
-
import {
|
|
449
|
+
import { createPublicClient, formatEther, http, isAddress } from "viem";
|
|
450
450
|
|
|
451
451
|
// src/deno/runner.ts
|
|
452
452
|
import { spawn } from "child_process";
|
|
@@ -685,7 +685,7 @@ async function runCommand(taskName, options = {}) {
|
|
|
685
685
|
step("Calls to execute:");
|
|
686
686
|
for (const call of result.result.calls) {
|
|
687
687
|
log2(` ${pc.cyan("\u2192")} to: ${call.to}`);
|
|
688
|
-
log2(` data: ${call.data
|
|
688
|
+
log2(` data: ${call.data}`);
|
|
689
689
|
}
|
|
690
690
|
if (options.simulate) {
|
|
691
691
|
log2("");
|
|
@@ -739,30 +739,53 @@ async function simulateCalls(calls) {
|
|
|
739
739
|
info(`Chain ID: ${chainId}`);
|
|
740
740
|
info(`Block: ${blockNumber}`);
|
|
741
741
|
info(`Account: ${account}`);
|
|
742
|
+
if (!isAddress(account)) {
|
|
743
|
+
spinner.stop("Invalid account address");
|
|
744
|
+
log2("");
|
|
745
|
+
error(`SIMULATE_ACCOUNT is not a valid Ethereum address: ${account}`);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
742
748
|
const simulationSpinner = clack.spinner();
|
|
743
749
|
simulationSpinner.start("Running simulation...");
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
+
const { results } = await client.simulateCalls({
|
|
751
|
+
account,
|
|
752
|
+
calls: calls.map((call) => ({
|
|
753
|
+
to: call.to,
|
|
754
|
+
data: call.data
|
|
755
|
+
}))
|
|
756
|
+
});
|
|
757
|
+
simulationSpinner.stop("Simulation complete");
|
|
758
|
+
const failedCalls = [];
|
|
759
|
+
for (let i = 0; i < results.length; i++) {
|
|
760
|
+
const result = results[i];
|
|
761
|
+
const call = calls[i];
|
|
762
|
+
if (!result || !call) continue;
|
|
763
|
+
if (result.status === "failure") {
|
|
764
|
+
failedCalls.push({
|
|
765
|
+
index: i,
|
|
766
|
+
call,
|
|
767
|
+
error: result.error?.message || "Unknown error"
|
|
750
768
|
});
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (failedCalls.length > 0) {
|
|
772
|
+
log2("");
|
|
773
|
+
error("Some calls would revert:");
|
|
774
|
+
for (const failed of failedCalls) {
|
|
754
775
|
error(
|
|
755
|
-
`Call to ${call.to}
|
|
776
|
+
` Call ${failed.index + 1} to ${failed.call.to}: ${failed.error}`
|
|
756
777
|
);
|
|
757
|
-
return;
|
|
758
778
|
}
|
|
779
|
+
return;
|
|
759
780
|
}
|
|
760
781
|
const gasPrice = await client.getGasPrice();
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
782
|
+
clack.log.step("Simulation results:");
|
|
783
|
+
clack.log.success("All calls would succeed");
|
|
784
|
+
const totalGas = results.reduce((sum, r) => sum + (r.gasUsed || 0n), 0n);
|
|
785
|
+
if (totalGas > 0n) {
|
|
786
|
+
clack.log.message(` Total gas: ${totalGas.toString()}`);
|
|
787
|
+
}
|
|
788
|
+
clack.log.message(` Gas price: ${formatEther(gasPrice)} ETH`);
|
|
766
789
|
} catch (err) {
|
|
767
790
|
spinner.stop("Simulation failed");
|
|
768
791
|
log2("");
|
|
@@ -857,7 +880,11 @@ async function bundleTask(taskPath) {
|
|
|
857
880
|
if (result.outputFiles.length === 0) {
|
|
858
881
|
throw new Error("No output from bundler");
|
|
859
882
|
}
|
|
860
|
-
const
|
|
883
|
+
const outputFile = result.outputFiles[0];
|
|
884
|
+
if (!outputFile) {
|
|
885
|
+
throw new Error("No output from bundler");
|
|
886
|
+
}
|
|
887
|
+
const bundle = outputFile.text;
|
|
861
888
|
return {
|
|
862
889
|
source,
|
|
863
890
|
bundle
|
|
@@ -877,50 +904,13 @@ function compressTask(source, bundle) {
|
|
|
877
904
|
// src/utils/schema-extractor.ts
|
|
878
905
|
function extractSchemaFromTask(taskCode) {
|
|
879
906
|
try {
|
|
880
|
-
const schemaExtractor = `
|
|
881
|
-
const { z } = require('zod');
|
|
882
|
-
const { zodToJsonSchema } = require('zod-to-json-schema');
|
|
883
|
-
|
|
884
|
-
// Extended z with address validator
|
|
885
|
-
const zodExtended = {
|
|
886
|
-
...z,
|
|
887
|
-
address: () => z.string().refine((val) => /^0x[a-fA-F0-9]{40}$/.test(val), {
|
|
888
|
-
message: 'Invalid Ethereum address',
|
|
889
|
-
}),
|
|
890
|
-
};
|
|
891
|
-
|
|
892
|
-
// Mock defineTask to capture schema
|
|
893
|
-
let capturedSchema = null;
|
|
894
|
-
const defineTask = (definition) => {
|
|
895
|
-
if (definition.schema) {
|
|
896
|
-
capturedSchema = definition.schema;
|
|
897
|
-
}
|
|
898
|
-
return definition;
|
|
899
|
-
};
|
|
900
|
-
|
|
901
|
-
// Mock viem exports
|
|
902
|
-
const encodeFunctionData = () => '0x';
|
|
903
|
-
|
|
904
|
-
// Evaluate task code
|
|
905
|
-
${taskCode}
|
|
906
|
-
|
|
907
|
-
// Convert schema to JSON Schema
|
|
908
|
-
if (capturedSchema) {
|
|
909
|
-
const jsonSchema = zodToJsonSchema(capturedSchema, { target: 'openApi3' });
|
|
910
|
-
console.log(JSON.stringify(jsonSchema));
|
|
911
|
-
} else {
|
|
912
|
-
console.log('null');
|
|
913
|
-
}
|
|
914
|
-
`;
|
|
915
907
|
const schemaMatch = taskCode.match(/schema:\s*z\.object\(\{([^}]+)\}\)/);
|
|
916
|
-
if (!schemaMatch) {
|
|
908
|
+
if (!schemaMatch || !schemaMatch[1]) {
|
|
917
909
|
return null;
|
|
918
910
|
}
|
|
919
911
|
const schemaContent = schemaMatch[1];
|
|
920
912
|
const fields = {};
|
|
921
|
-
const fieldMatches = schemaContent.matchAll(
|
|
922
|
-
/(\w+):\s*z\.(\w+)\(\)/g
|
|
923
|
-
);
|
|
913
|
+
const fieldMatches = schemaContent.matchAll(/(\w+):\s*z\.(\w+)\(\)/g);
|
|
924
914
|
for (const match of fieldMatches) {
|
|
925
915
|
const [, fieldName, fieldType] = match;
|
|
926
916
|
if (fieldName && fieldType) {
|
|
@@ -1027,14 +1017,18 @@ async function uploadCommand(taskName, organizationId) {
|
|
|
1027
1017
|
process.exit(1);
|
|
1028
1018
|
}
|
|
1029
1019
|
if (organizations.length === 0) {
|
|
1030
|
-
error(
|
|
1020
|
+
error(
|
|
1021
|
+
"You are not a member of any organizations. Please create or join an organization first."
|
|
1022
|
+
);
|
|
1031
1023
|
process.exit(1);
|
|
1032
1024
|
}
|
|
1033
1025
|
let selectedOrgId = organizationId;
|
|
1034
1026
|
if (selectedOrgId) {
|
|
1035
1027
|
const orgExists = organizations.find((org) => org.id === selectedOrgId);
|
|
1036
1028
|
if (!orgExists) {
|
|
1037
|
-
error(
|
|
1029
|
+
error(
|
|
1030
|
+
`Organization with ID "${selectedOrgId}" not found or you don't have access to it.`
|
|
1031
|
+
);
|
|
1038
1032
|
process.exit(1);
|
|
1039
1033
|
}
|
|
1040
1034
|
} else {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/ui.ts","../src/utils/tasks.ts","../src/commands/list.ts","../src/commands/login.ts","../src/utils/env.ts","../src/commands/new.ts","../src/commands/run.ts","../src/deno/runner.ts","../src/commands/upload.ts","../src/utils/bundler.ts","../src/utils/compress.ts","../src/utils/schema-extractor.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { initCommand } from './commands/init'\nimport { listCommand } from './commands/list'\nimport { loginCommand } from './commands/login'\nimport { newCommand } from './commands/new'\nimport { runCommand } from './commands/run'\nimport { uploadCommand } from './commands/upload'\n\nconst program = new Command()\n\nprogram\n\t.name('thyme')\n\t.description('CLI for developing and deploying Thyme tasks')\n\t.version('0.1.0')\n\nprogram\n\t.command('init')\n\t.description('Initialize a new Thyme project')\n\t.argument('[name]', 'Project name')\n\t.action(initCommand)\n\nprogram\n\t.command('new')\n\t.description('Create a new task')\n\t.argument('[name]', 'Task name')\n\t.action(newCommand)\n\nprogram\n\t.command('run')\n\t.description('Run a task locally')\n\t.argument('[task]', 'Task name')\n\t.option('--simulate', 'Simulate on-chain execution')\n\t.action((task, options) => runCommand(task, options))\n\nprogram.command('list').description('List all tasks').action(listCommand)\n\nprogram\n\t.command('login')\n\t.description('Authenticate with Thyme Cloud')\n\t.action(loginCommand)\n\nprogram\n\t.command('upload')\n\t.description('Upload a task to Thyme Cloud')\n\t.argument('[task]', 'Task name')\n\t.option('-o, --organization <id>', 'Organization ID to upload to')\n\t.action((task, options) => uploadCommand(task, options.organization))\n\nprogram.parse()\n","import { existsSync } from 'node:fs'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\nexport async function initCommand(projectName?: string) {\n\tintro('Thyme CLI - Initialize Project')\n\n\t// Prompt for project name if not provided\n\tlet finalProjectName = projectName\n\tif (!finalProjectName) {\n\t\tconst name = await clack.text({\n\t\t\tmessage: 'What is your project name?',\n\t\t\tplaceholder: 'my-thyme-project',\n\t\t\tvalidate: (value) => {\n\t\t\t\tif (!value) return 'Project name is required'\n\t\t\t\tif (!/^[a-z0-9-]+$/.test(value))\n\t\t\t\t\treturn 'Project name must be lowercase alphanumeric with hyphens'\n\t\t\t},\n\t\t})\n\n\t\tif (clack.isCancel(name)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalProjectName = name as string\n\t}\n\n\tconst projectPath = join(process.cwd(), finalProjectName)\n\n\t// Check if directory exists\n\tif (existsSync(projectPath)) {\n\t\terror(`Directory \"${finalProjectName}\" already exists`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Creating project structure...')\n\n\ttry {\n\t\t// Create directories\n\t\tawait mkdir(projectPath, { recursive: true })\n\t\tawait mkdir(join(projectPath, 'functions'), { recursive: true })\n\n\t\t// Create package.json\n\t\tconst packageJson = {\n\t\t\tname: finalProjectName,\n\t\t\tversion: '0.1.0',\n\t\t\ttype: 'module',\n\t\t\tprivate: true,\n\t\t\tscripts: {\n\t\t\t\tdev: 'thyme run',\n\t\t\t},\n\t\t\tdependencies: {\n\t\t\t\t'@thyme-sh/sdk': '^0.1.0',\n\t\t\t\tviem: '^2.21.54',\n\t\t\t\tzod: '^3.24.1',\n\t\t\t},\n\t\t\tdevDependencies: {\n\t\t\t\t'@thyme-sh/cli': '^0.1.0',\n\t\t\t\ttypescript: '^5.7.2',\n\t\t\t},\n\t\t}\n\n\t\tawait writeFile(\n\t\t\tjoin(projectPath, 'package.json'),\n\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t)\n\n\t\t// Create tsconfig.json\n\t\tconst tsconfig = {\n\t\t\tcompilerOptions: {\n\t\t\t\ttarget: 'ES2022',\n\t\t\t\tmodule: 'ESNext',\n\t\t\t\tmoduleResolution: 'bundler',\n\t\t\t\tlib: ['ES2022', 'DOM'],\n\t\t\t\tstrict: true,\n\t\t\t\tesModuleInterop: true,\n\t\t\t\tskipLibCheck: true,\n\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\tresolveJsonModule: true,\n\t\t\t},\n\t\t\tinclude: ['functions/**/*'],\n\t\t}\n\n\t\tawait writeFile(\n\t\t\tjoin(projectPath, 'tsconfig.json'),\n\t\t\tJSON.stringify(tsconfig, null, 2),\n\t\t)\n\n\t\t// Create .env.example\n\t\tconst envExample = `# Simulation settings (for --simulate flag)\nRPC_URL=https://eth-sepolia.g.alchemy.com/v2/your-key\nSIMULATE_ACCOUNT=0x742d35Cc6634C0532925a3b844Bc454e4438f44e\n\n# Cloud authentication (set by \\`thyme login\\`)\nTHYME_AUTH_TOKEN=\n\n# Cloud API URL (required - your Convex deployment URL)\n# Example: https://your-deployment.convex.cloud\nTHYME_API_URL=\n`\n\n\t\tawait writeFile(join(projectPath, '.env.example'), envExample)\n\n\t\t// Create .gitignore\n\t\tconst gitignore = `node_modules/\ndist/\n.env\n.env.local\n*.log\n`\n\n\t\tawait writeFile(join(projectPath, '.gitignore'), gitignore)\n\n\t\t// Create README\n\t\tconst readme = `# ${finalProjectName}\n\nA Thyme project for Web3 automation tasks.\n\n## Getting Started\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Create a new task\nthyme new my-task\n\n# Run a task locally\nthyme run my-task\n\n# Simulate on-chain\nthyme run my-task --simulate\n\n# Deploy to cloud\nthyme login\nthyme upload my-task\n\\`\\`\\`\n\n## Project Structure\n\n\\`\\`\\`\nfunctions/\n my-task/\n index.ts # Task definition\n args.json # Test arguments\n\\`\\`\\`\n`\n\n\t\tawait writeFile(join(projectPath, 'README.md'), readme)\n\n\t\tspinner.stop('Project created successfully!')\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Project initialized!\\n\\nNext steps:\\n ${pc.cyan('cd')} ${finalProjectName}\\n ${pc.cyan('npm install')}\\n ${pc.cyan('thyme new')} my-task\\n ${pc.cyan('thyme run')} my-task`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Failed to create project')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import * as clack from '@clack/prompts'\nimport pc from 'picocolors'\n\nexport { clack, pc }\n\nexport function intro(title: string) {\n\tclack.intro(pc.bgCyan(pc.black(` ${title} `)))\n}\n\nexport function outro(message: string) {\n\tclack.outro(message)\n}\n\nexport function success(message: string) {\n\tclack.log.success(pc.green(message))\n}\n\nexport function error(message: string) {\n\tclack.log.error(pc.red(message))\n}\n\nexport function info(message: string) {\n\tclack.log.info(pc.cyan(message))\n}\n\nexport function warn(message: string) {\n\tclack.log.warn(pc.yellow(message))\n}\n\nexport function step(message: string) {\n\tclack.log.step(message)\n}\n\nexport function log(message: string) {\n\tconsole.log(message)\n}\n","import { existsSync } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { join } from 'node:path'\n\n/**\n * Discover all tasks in the functions directory\n */\nexport async function discoverTasks(projectRoot: string): Promise<string[]> {\n\tconst functionsDir = join(projectRoot, 'functions')\n\n\tif (!existsSync(functionsDir)) {\n\t\treturn []\n\t}\n\n\ttry {\n\t\tconst entries = await readdir(functionsDir, { withFileTypes: true })\n\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.filter((e) => existsSync(join(functionsDir, e.name, 'index.ts')))\n\t\t\t.map((e) => e.name)\n\t} catch {\n\t\treturn []\n\t}\n}\n\n/**\n * Get the path to a task's index file\n */\nexport function getTaskPath(projectRoot: string, taskName: string): string {\n\treturn join(projectRoot, 'functions', taskName, 'index.ts')\n}\n\n/**\n * Get the path to a task's args file\n */\nexport function getTaskArgsPath(projectRoot: string, taskName: string): string {\n\treturn join(projectRoot, 'functions', taskName, 'args.json')\n}\n\n/**\n * Check if we're in a Thyme project\n */\nexport function isThymeProject(projectRoot: string): boolean {\n\tconst functionsDir = join(projectRoot, 'functions')\n\treturn existsSync(functionsDir)\n}\n","import { discoverTasks, isThymeProject } from '../utils/tasks'\nimport { intro, outro, pc, step } from '../utils/ui'\n\nexport async function listCommand() {\n\tintro('Thyme CLI - List Tasks')\n\n\tconst projectRoot = process.cwd()\n\n\tif (!isThymeProject(projectRoot)) {\n\t\toutro(pc.red('Not in a Thyme project'))\n\t\tprocess.exit(1)\n\t}\n\n\tconst tasks = await discoverTasks(projectRoot)\n\n\tif (tasks.length === 0) {\n\t\toutro(pc.yellow('No tasks found. Create one with `thyme new`'))\n\t\treturn\n\t}\n\n\tstep(`Found ${tasks.length} task(s):`)\n\tfor (const task of tasks) {\n\t\tconsole.log(` ${pc.cyan('●')} ${task}`)\n\t}\n\n\toutro('')\n}\n","import { existsSync } from 'node:fs'\nimport { appendFile, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { clack, error, info, intro, outro, pc } from '../utils/ui'\n\nexport async function loginCommand() {\n\tintro('Thyme CLI - Login')\n\n\tconst projectRoot = process.cwd()\n\tconst envPath = join(projectRoot, '.env')\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Show instructions\n\tinfo('To authenticate with Thyme Cloud:')\n\tclack.log.message(\n\t\t` 1. Visit ${pc.cyan('https://thyme.sh/settings/api-keys')}`,\n\t)\n\tclack.log.message(' 2. Generate a new API token')\n\tclack.log.message(' 3. Copy the token and paste it below')\n\tclack.log.message('')\n\n\t// Prompt for token\n\tconst token = await clack.password({\n\t\tmessage: 'Paste your API token:',\n\t\tvalidate: (value) => {\n\t\t\tif (!value) return 'Token is required'\n\t\t\tif (value.length < 10) return 'Token seems too short'\n\t\t},\n\t})\n\n\tif (clack.isCancel(token)) {\n\t\tclack.cancel('Operation cancelled')\n\t\tprocess.exit(0)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Verifying token...')\n\n\ttry {\n\t\t// Get API URL (Convex deployment URL)\n\t\tconst apiUrl = getEnv('THYME_API_URL')\n\n\t\tif (!apiUrl) {\n\t\t\tspinner.stop('Configuration error')\n\t\t\terror(\n\t\t\t\t'THYME_API_URL is not set. Please set it to your Convex deployment URL (e.g., https://your-deployment.convex.cloud)',\n\t\t\t)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\t// Verify token with API\n\t\tconst verifyResponse = await fetch(`${apiUrl}/api/auth/verify`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t},\n\t\t})\n\n\t\tif (!verifyResponse.ok) {\n\t\t\tspinner.stop('Token verification failed')\n\t\t\tconst errorText = await verifyResponse.text()\n\t\t\terror(`Invalid token: ${errorText}`)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst verifyData = (await verifyResponse.json()) as {\n\t\t\tuser: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\temail: string\n\t\t\t}\n\t\t\torganizations: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\trole: string\n\t\t\t}[]\n\t\t}\n\n\t\tspinner.stop('Token verified!')\n\n\t\t// Save token\n\t\tconst saveSpinner = clack.spinner()\n\t\tsaveSpinner.start('Saving token...')\n\n\t\t// Read existing .env or create new\n\t\tlet envContent = ''\n\t\tif (existsSync(envPath)) {\n\t\t\tenvContent = await readFile(envPath, 'utf-8')\n\t\t}\n\n\t\t// Check if THYME_AUTH_TOKEN already exists\n\t\tconst tokenRegex = /^THYME_AUTH_TOKEN=.*$/m\n\t\tif (tokenRegex.test(envContent)) {\n\t\t\t// Replace existing token\n\t\t\tenvContent = envContent.replace(tokenRegex, `THYME_AUTH_TOKEN=${token}`)\n\t\t\tawait writeFile(envPath, envContent)\n\t\t} else {\n\t\t\t// Append new token\n\t\t\tconst newLine = envContent && !envContent.endsWith('\\n') ? '\\n' : ''\n\t\t\tawait appendFile(envPath, `${newLine}THYME_AUTH_TOKEN=${token}\\n`)\n\t\t}\n\n\t\tsaveSpinner.stop('Token saved successfully!')\n\n\t\t// Display user info\n\t\tclack.log.message('')\n\t\tclack.log.success('Authenticated as:')\n\t\tclack.log.message(\n\t\t\t` ${pc.cyan('User:')} ${verifyData.user.name || verifyData.user.email}`,\n\t\t)\n\t\tclack.log.message(` ${pc.cyan('Email:')} ${verifyData.user.email}`)\n\n\t\tif (verifyData.organizations && verifyData.organizations.length > 0) {\n\t\t\tclack.log.message('')\n\t\t\tclack.log.message(`${pc.cyan('Organizations:')}`)\n\t\t\tfor (const org of verifyData.organizations) {\n\t\t\t\tclack.log.message(` • ${org.name} ${pc.dim(`(${org.role})`)}`)\n\t\t\t}\n\t\t}\n\n\t\toutro(`\\nYou can now upload tasks with ${pc.cyan('thyme upload')}`)\n\t} catch (err) {\n\t\tspinner.stop('Failed to verify token')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { config } from 'dotenv'\n\n/**\n * Load environment variables from .env file\n */\nexport function loadEnv(projectRoot: string): void {\n\tconst envPath = join(projectRoot, '.env')\n\tif (existsSync(envPath)) {\n\t\tconfig({ path: envPath })\n\t}\n}\n\n/**\n * Get environment variable with fallback\n */\nexport function getEnv(key: string, fallback?: string): string | undefined {\n\treturn process.env[key] ?? fallback\n}\n\n/**\n * Get required environment variable\n */\nexport function getRequiredEnv(key: string): string {\n\tconst value = process.env[key]\n\tif (!value) {\n\t\tthrow new Error(`Missing required environment variable: ${key}`)\n\t}\n\treturn value\n}\n","import { existsSync } from 'node:fs'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isThymeProject } from '../utils/tasks'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\nexport async function newCommand(taskName?: string) {\n\tintro('Thyme CLI - Create New Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project. Run `thyme init` first.')\n\t\tprocess.exit(1)\n\t}\n\n\t// Prompt for task name if not provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst name = await clack.text({\n\t\t\tmessage: 'What is your task name?',\n\t\t\tplaceholder: 'my-task',\n\t\t\tvalidate: (value) => {\n\t\t\t\tif (!value) return 'Task name is required'\n\t\t\t\tif (!/^[a-z0-9-]+$/.test(value))\n\t\t\t\t\treturn 'Task name must be lowercase alphanumeric with hyphens'\n\t\t\t},\n\t\t})\n\n\t\tif (clack.isCancel(name)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = name as string\n\t}\n\n\tconst taskPath = join(projectRoot, 'functions', finalTaskName)\n\n\t// Check if task already exists\n\tif (existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" already exists`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Creating task...')\n\n\ttry {\n\t\t// Create task directory\n\t\tawait mkdir(taskPath, { recursive: true })\n\n\t\t// Create index.ts\n\t\tconst indexTs = `import { defineTask, z } from '@thyme-sh/sdk'\nimport { encodeFunctionData } from 'viem'\n\nexport default defineTask({\n\tschema: z.object({\n\t\ttargetAddress: z.address(),\n\t}),\n\n\tasync run(ctx) {\n\t\tconst { targetAddress } = ctx.args\n\n\t\t// Your task logic here\n\t\tconsole.log('Running task with address:', targetAddress)\n\n\t\t// Example: Read from blockchain using the public client\n\t\t// const balance = await ctx.client.getBalance({ address: targetAddress })\n\t\t// const blockNumber = await ctx.client.getBlockNumber()\n\t\t// const value = await ctx.client.readContract({\n\t\t// address: targetAddress,\n\t\t// abi: [...],\n\t\t// functionName: 'balanceOf',\n\t\t// args: [someAddress],\n\t\t// })\n\n\t\t// Example: Return calls to execute\n\t\treturn {\n\t\t\tcanExec: true,\n\t\t\tcalls: [\n\t\t\t\t{\n\t\t\t\t\tto: targetAddress,\n\t\t\t\t\tdata: '0x' as const,\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\n\t\t// Example with encodeFunctionData:\n\t\t// const abi = [...] as const\n\t\t// return {\n\t\t// canExec: true,\n\t\t// calls: [\n\t\t// {\n\t\t// to: targetAddress,\n\t\t// data: encodeFunctionData({\n\t\t// abi,\n\t\t// functionName: 'transfer',\n\t\t// args: [recipientAddress, 1000n],\n\t\t// }),\n\t\t// },\n\t\t// ],\n\t\t// }\n\n\t\t// Or return false if conditions not met\n\t\t// return {\n\t\t// canExec: false,\n\t\t// message: 'Conditions not met'\n\t\t// }\n\t},\n})\n`\n\n\t\tawait writeFile(join(taskPath, 'index.ts'), indexTs)\n\n\t\t// Create args.json\n\t\tconst args = {\n\t\t\ttargetAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',\n\t\t}\n\n\t\tawait writeFile(join(taskPath, 'args.json'), JSON.stringify(args, null, 2))\n\n\t\tspinner.stop('Task created successfully!')\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Task \"${finalTaskName}\" created!\\n\\nNext steps:\\n ${pc.cyan('Edit')} functions/${finalTaskName}/index.ts\\n ${pc.cyan('Update')} functions/${finalTaskName}/args.json\\n ${pc.cyan('thyme run')} ${finalTaskName}`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Failed to create task')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport type { Address } from 'viem'\nimport { http, createPublicClient, formatEther } from 'viem'\nimport { type TaskConfig, checkDeno, runInDeno } from '../deno/runner'\nimport { getEnv, loadEnv } from '../utils/env'\nimport {\n\tdiscoverTasks,\n\tgetTaskArgsPath,\n\tgetTaskPath,\n\tisThymeProject,\n} from '../utils/tasks'\nimport {\n\tclack,\n\terror,\n\tinfo,\n\tintro,\n\tlog,\n\toutro,\n\tpc,\n\tstep,\n\twarn,\n} from '../utils/ui'\n\ninterface RunOptions {\n\tsimulate?: boolean\n}\n\nexport async function runCommand(taskName?: string, options: RunOptions = {}) {\n\tintro('Thyme CLI - Run Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project')\n\t\tprocess.exit(1)\n\t}\n\n\t// Check if Deno is installed\n\tconst hasDeno = await checkDeno()\n\tif (!hasDeno) {\n\t\terror('Deno is not installed. Please install Deno: https://deno.land/')\n\t\tprocess.exit(1)\n\t}\n\n\t// Discover tasks if no task name provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst tasks = await discoverTasks(projectRoot)\n\n\t\tif (tasks.length === 0) {\n\t\t\terror('No tasks found. Create one with `thyme new`')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select a task to run:',\n\t\t\toptions: tasks.map((task) => ({ value: task, label: task })),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = selected as string\n\t}\n\n\tconst taskPath = getTaskPath(projectRoot, finalTaskName)\n\tconst argsPath = getTaskArgsPath(projectRoot, finalTaskName)\n\n\t// Check if task exists\n\tif (!existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" not found`)\n\t\tprocess.exit(1)\n\t}\n\n\t// Use default config\n\tconst config: TaskConfig = {\n\t\tmemory: 128,\n\t\ttimeout: 30,\n\t\tnetwork: true,\n\t\trpcUrl: getEnv('RPC_URL'),\n\t}\n\n\t// Load args\n\tlet args: unknown = {}\n\tif (existsSync(argsPath)) {\n\t\ttry {\n\t\t\tconst argsData = await readFile(argsPath, 'utf-8')\n\t\t\targs = JSON.parse(argsData)\n\t\t} catch (err) {\n\t\t\twarn(\n\t\t\t\t`Failed to load args.json: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t)\n\t\t}\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Executing task in Deno sandbox...')\n\n\t// Run task\n\tconst result = await runInDeno(taskPath, args, config)\n\n\tif (!result.success) {\n\t\tspinner.stop('Task execution failed')\n\t\terror(result.error ?? 'Unknown error')\n\t\tif (result.logs.length > 0) {\n\t\t\tstep('Task output:')\n\t\t\tfor (const taskLog of result.logs) {\n\t\t\t\tlog(` ${taskLog}`)\n\t\t\t}\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop('Task executed successfully')\n\n\t// Show logs\n\tif (result.logs.length > 0) {\n\t\tlog('')\n\t\tstep('Task output:')\n\t\tfor (const taskLog of result.logs) {\n\t\t\tlog(` ${taskLog}`)\n\t\t}\n\t}\n\n\t// Show result\n\tif (!result.result) {\n\t\terror('No result returned from task')\n\t\tprocess.exit(1)\n\t}\n\n\tlog('')\n\tif (result.result.canExec) {\n\t\tinfo(\n\t\t\t`${pc.green('✓')} Result: canExec = true (${result.result.calls.length} call(s))`,\n\t\t)\n\n\t\t// Show calls\n\t\tlog('')\n\t\tstep('Calls to execute:')\n\t\tfor (const call of result.result.calls) {\n\t\t\tlog(` ${pc.cyan('→')} to: ${call.to}`)\n\t\t\tlog(` data: ${call.data.slice(0, 20)}...`)\n\t\t}\n\n\t\t// Simulate if requested\n\t\tif (options.simulate) {\n\t\t\tlog('')\n\t\t\tawait simulateCalls(result.result.calls)\n\t\t}\n\t} else {\n\t\twarn('Result: canExec = false')\n\t\tinfo(`Message: ${result.result.message}`)\n\t}\n\n\t// Show execution stats\n\tlog('')\n\tif (\n\t\tresult.executionTime !== undefined ||\n\t\tresult.memoryUsed !== undefined ||\n\t\tresult.rpcRequestCount !== undefined\n\t) {\n\t\tstep('Execution stats:')\n\t\tif (result.executionTime !== undefined) {\n\t\t\tlog(` Duration: ${result.executionTime.toFixed(2)}ms`)\n\t\t}\n\t\tif (result.memoryUsed !== undefined) {\n\t\t\tconst memoryMB = (result.memoryUsed / 1024 / 1024).toFixed(2)\n\t\t\tlog(` Memory: ${memoryMB}MB`)\n\t\t}\n\t\tif (result.rpcRequestCount !== undefined) {\n\t\t\tlog(` RPC Requests: ${result.rpcRequestCount}`)\n\t\t}\n\t}\n\n\t// Show simulation tip if task can execute and simulation wasn't run\n\tif (result.result?.canExec && !options.simulate) {\n\t\tlog('')\n\t\tinfo(\n\t\t\t`${pc.dim('💡 Tip: Test calls on-chain with:')} ${pc.cyan(`thyme run ${finalTaskName} --simulate`)}`,\n\t\t)\n\t\toutro('')\n\t} else {\n\t\toutro('')\n\t}\n}\n\nasync function simulateCalls(\n\tcalls: Array<{ to: Address; data: `0x${string}` }>,\n) {\n\tconst rpcUrl = getEnv('RPC_URL')\n\tconst account = getEnv('SIMULATE_ACCOUNT')\n\n\tif (!rpcUrl || !account) {\n\t\twarn('Simulation requires RPC_URL and SIMULATE_ACCOUNT in .env file')\n\t\treturn\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Simulating on-chain...')\n\n\ttry {\n\t\tconst client = createPublicClient({\n\t\t\ttransport: http(rpcUrl),\n\t\t})\n\n\t\t// Get chain info\n\t\tconst chainId = await client.getChainId()\n\t\tconst blockNumber = await client.getBlockNumber()\n\n\t\tspinner.stop('Simulating on-chain...')\n\n\t\tlog('')\n\t\tinfo(`Chain ID: ${chainId}`)\n\t\tinfo(`Block: ${blockNumber}`)\n\t\tinfo(`Account: ${account}`)\n\n\t\t// Simulate each call\n\t\tconst simulationSpinner = clack.spinner()\n\t\tsimulationSpinner.start('Running simulation...')\n\n\t\tfor (const call of calls) {\n\t\t\ttry {\n\t\t\t\tawait client.call({\n\t\t\t\t\taccount: account as Address,\n\t\t\t\t\tto: call.to,\n\t\t\t\t\tdata: call.data,\n\t\t\t\t})\n\t\t\t} catch (err) {\n\t\t\t\tsimulationSpinner.stop('Simulation failed')\n\t\t\t\tlog('')\n\t\t\t\terror(\n\t\t\t\t\t`Call to ${call.to} would revert: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Get gas price\n\t\tconst gasPrice = await client.getGasPrice()\n\n\t\tsimulationSpinner.stop('Simulation successful!')\n\n\t\tlog('')\n\t\tstep('Simulation results:')\n\t\tlog(` ${pc.green('✓')} All calls would succeed`)\n\t\tlog(` Gas price: ${formatEther(gasPrice)} ETH`)\n\t} catch (err) {\n\t\tspinner.stop('Simulation failed')\n\t\tlog('')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t}\n}\n","import { spawn } from 'node:child_process'\nimport { dirname, resolve } from 'node:path'\nimport type { TaskResult } from '@thyme-sh/sdk'\n\nexport interface TaskConfig {\n\tmemory: number // MB\n\ttimeout: number // seconds\n\tnetwork: boolean\n\trpcUrl?: string // RPC URL for public client\n}\n\nexport interface RunResult {\n\tsuccess: boolean\n\tresult?: TaskResult\n\tlogs: string[]\n\terror?: string\n\texecutionTime?: number // milliseconds\n\tmemoryUsed?: number // bytes\n\trpcRequestCount?: number // number of RPC requests made\n}\n\n/**\n * Run a task in Deno sandbox - similar to Gelato's w3f test and @deno/sandbox\n * Creates an isolated Deno process with controlled permissions\n */\nexport async function runInDeno(\n\ttaskPath: string,\n\targs: unknown,\n\tconfig: TaskConfig,\n): Promise<RunResult> {\n\tconst taskDir = dirname(resolve(taskPath))\n\tconst absoluteTaskPath = resolve(taskPath)\n\n\tconst denoFlags = ['run', '--no-prompt']\n\n\t// Sandbox permissions - minimal by default, similar to @deno/sandbox\n\tdenoFlags.push(`--allow-read=${taskDir}`) // Only allow reading task directory\n\n\t// Add memory limit if specified\n\tif (config.memory) {\n\t\tdenoFlags.push(`--v8-flags=--max-old-space-size=${config.memory}`)\n\t}\n\n\t// Conditionally allow network (similar to allowNet in @deno/sandbox)\n\tif (config.network) {\n\t\tdenoFlags.push('--allow-net')\n\t}\n\n\t// Execute inline wrapper via stdin (similar to Gelato's approach)\n\tdenoFlags.push('-')\n\n\t// Execution wrapper that loads and runs the task\n\t// Similar to how Gelato's w3f test executes functions\n\tconst execScript = `\nimport task from '${absoluteTaskPath}';\nimport { createPublicClient, http } from 'npm:viem@2.21.54';\n\n// Create RPC request counter\nlet rpcRequestCount = 0;\n\n// Wrap the http transport to count requests\nconst countingHttp = (url) => {\n\tconst baseTransport = http(url);\n\treturn (config) => {\n\t\tconst transport = baseTransport(config);\n\t\treturn {\n\t\t\t...transport,\n\t\t\trequest: async (params) => {\n\t\t\t\trpcRequestCount++;\n\t\t\t\treturn transport.request(params);\n\t\t\t},\n\t\t};\n\t};\n};\n\n// Create public client for blockchain reads\nconst client = createPublicClient({\n\ttransport: countingHttp(${config.rpcUrl ? `'${config.rpcUrl}'` : 'undefined'}),\n});\n\nconst context = {\n\targs: ${JSON.stringify(args)},\n\tclient,\n};\n\ntry {\n\t// Track execution time and memory\n\tconst startTime = performance.now();\n\tconst startMemory = Deno.memoryUsage().heapUsed;\n\t\n\tconst result = await task.run(context);\n\t\n\tconst endTime = performance.now();\n\tconst endMemory = Deno.memoryUsage().heapUsed;\n\t\n\tconst executionTime = endTime - startTime;\n\tconst memoryUsed = endMemory - startMemory;\n\t\n\tconsole.log('__THYME_RESULT__' + JSON.stringify(result));\n\tconsole.log('__THYME_STATS__' + JSON.stringify({ executionTime, memoryUsed, rpcRequestCount }));\n} catch (error) {\n\tconsole.error('Task execution error:', error instanceof Error ? error.message : String(error));\n\tDeno.exit(1);\n}\n`\n\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn('deno', denoFlags, {\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\ttimeout: config.timeout * 1000,\n\t\t\tcwd: taskDir,\n\t\t})\n\n\t\tlet stdout = ''\n\t\tlet stderr = ''\n\t\tconst logs: string[] = []\n\n\t\t// Write the execution script to stdin\n\t\tproc.stdin?.write(execScript)\n\t\tproc.stdin?.end()\n\n\t\tproc.stdout?.on('data', (data) => {\n\t\t\tstdout += data.toString()\n\t\t})\n\n\t\tproc.stderr?.on('data', (data) => {\n\t\t\tstderr += data.toString()\n\t\t})\n\n\t\tproc.on('close', (code) => {\n\t\t\tif (code !== 0) {\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tlogs,\n\t\t\t\t\terror: stderr || `Process exited with code ${code}`,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Extract logs, result, and stats from stdout\n\t\t\t\tconst lines = stdout.trim().split('\\n')\n\t\t\t\tlet resultLine: string | undefined\n\t\t\t\tlet statsLine: string | undefined\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith('__THYME_RESULT__')) {\n\t\t\t\t\t\tresultLine = line.substring('__THYME_RESULT__'.length)\n\t\t\t\t\t} else if (line.startsWith('__THYME_STATS__')) {\n\t\t\t\t\t\tstatsLine = line.substring('__THYME_STATS__'.length)\n\t\t\t\t\t} else if (line.trim()) {\n\t\t\t\t\t\tlogs.push(line.trim())\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!resultLine) {\n\t\t\t\t\tthrow new Error('No result found in output')\n\t\t\t\t}\n\n\t\t\t\tconst result = JSON.parse(resultLine) as TaskResult\n\t\t\t\tconst stats = statsLine\n\t\t\t\t\t? JSON.parse(statsLine)\n\t\t\t\t\t: {\n\t\t\t\t\t\t\texecutionTime: undefined,\n\t\t\t\t\t\t\tmemoryUsed: undefined,\n\t\t\t\t\t\t\trpcRequestCount: undefined,\n\t\t\t\t\t\t}\n\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tresult,\n\t\t\t\t\tlogs,\n\t\t\t\t\texecutionTime: stats.executionTime,\n\t\t\t\t\tmemoryUsed: stats.memoryUsed,\n\t\t\t\t\trpcRequestCount: stats.rpcRequestCount,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tlogs,\n\t\t\t\t\terror: `Failed to parse result: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tproc.on('error', (error) => {\n\t\t\tresolve({\n\t\t\t\tsuccess: false,\n\t\t\t\tlogs,\n\t\t\t\terror: `Failed to spawn Deno: ${error.message}`,\n\t\t\t})\n\t\t})\n\t})\n}\n\n/**\n * Check if Deno is installed\n */\nexport async function checkDeno(): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn('deno', ['--version'], { stdio: 'ignore' })\n\t\tproc.on('close', (code) => resolve(code === 0))\n\t\tproc.on('error', () => resolve(false))\n\t})\n}\n","import { existsSync } from 'node:fs'\nimport { bundleTask } from '../utils/bundler'\nimport { compressTask } from '../utils/compress'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { extractSchemaFromTask } from '../utils/schema-extractor'\nimport { discoverTasks, getTaskPath, isThymeProject } from '../utils/tasks'\nimport { clack, error, info, intro, outro, pc, step, warn } from '../utils/ui'\n\nexport async function uploadCommand(taskName?: string, organizationId?: string) {\n\tintro('Thyme CLI - Upload Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project')\n\t\tprocess.exit(1)\n\t}\n\n\t// Check for auth token\n\tconst authToken = getEnv('THYME_AUTH_TOKEN')\n\tif (!authToken) {\n\t\terror('Not authenticated. Run `thyme login` first.')\n\t\tprocess.exit(1)\n\t}\n\n\t// Get API URL (Convex deployment URL)\n\tconst apiUrl = getEnv('THYME_API_URL')\n\tif (!apiUrl) {\n\t\terror(\n\t\t\t'THYME_API_URL is not set. Please set it to your Convex deployment URL in .env',\n\t\t)\n\t\tprocess.exit(1)\n\t}\n\n\t// Discover tasks if no task name provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst tasks = await discoverTasks(projectRoot)\n\n\t\tif (tasks.length === 0) {\n\t\t\terror('No tasks found. Create one with `thyme new`')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select a task to upload:',\n\t\t\toptions: tasks.map((task) => ({ value: task, label: task })),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = selected as string\n\t}\n\n\t// Fetch user's organizations\n\tconst orgSpinner = clack.spinner()\n\torgSpinner.start('Fetching organizations...')\n\n\tlet organizations: { id: string; name: string; role: string }[] = []\n\ttry {\n\t\tconst verifyResponse = await fetch(`${apiUrl}/api/auth/verify`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t\t},\n\t\t})\n\n\t\tif (!verifyResponse.ok) {\n\t\t\torgSpinner.stop('Failed to fetch organizations')\n\t\t\terror('Failed to authenticate. Please run `thyme login` again.')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst verifyData = (await verifyResponse.json()) as {\n\t\t\tuser: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\temail: string\n\t\t\t}\n\t\t\torganizations: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\trole: string\n\t\t\t}[]\n\t\t}\n\n\t\torganizations = verifyData.organizations || []\n\t\torgSpinner.stop('Organizations loaded')\n\t} catch (err) {\n\t\torgSpinner.stop('Failed to fetch organizations')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n\n\t// Check if user has any organizations\n\tif (organizations.length === 0) {\n\t\terror('You are not a member of any organizations. Please create or join an organization first.')\n\t\tprocess.exit(1)\n\t}\n\n\t// Determine organization to upload to\n\tlet selectedOrgId = organizationId\n\n\t// If organization ID was provided, validate it\n\tif (selectedOrgId) {\n\t\tconst orgExists = organizations.find((org) => org.id === selectedOrgId)\n\t\tif (!orgExists) {\n\t\t\terror(`Organization with ID \"${selectedOrgId}\" not found or you don't have access to it.`)\n\t\t\tprocess.exit(1)\n\t\t}\n\t} else {\n\t\t// Prompt user to select an organization\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select an organization to upload to:',\n\t\t\toptions: organizations.map((org) => ({\n\t\t\t\tvalue: org.id,\n\t\t\t\tlabel: `${org.name} ${pc.dim(`(${org.role})`)}`,\n\t\t\t})),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tselectedOrgId = selected as string\n\t}\n\n\tconst taskPath = getTaskPath(projectRoot, finalTaskName)\n\n\t// Check if task exists\n\tif (!existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" not found`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Bundling task...')\n\n\ttry {\n\t\t// Bundle task code with all dependencies\n\t\tconst { source, bundle } = await bundleTask(taskPath)\n\n\t\tspinner.message('Extracting schema...')\n\n\t\t// Extract schema from source code\n\t\tconst schema = extractSchemaFromTask(source)\n\n\t\tspinner.message('Compressing files...')\n\n\t\t// Compress source and bundle into ZIP\n\t\tconst { zipBuffer, checksum } = compressTask(source, bundle)\n\n\t\tspinner.message('Uploading to cloud...')\n\n\t\t// Create form data\n\t\tconst formData = new FormData()\n\n\t\t// Add metadata\n\t\tformData.append(\n\t\t\t'data',\n\t\t\tJSON.stringify({\n\t\t\t\torganizationId: selectedOrgId as string,\n\t\t\t\tcheckSum: checksum,\n\t\t\t\tschema: schema || undefined,\n\t\t\t}),\n\t\t)\n\n\t\t// Add ZIP blob\n\t\tformData.append('blob', new Blob([zipBuffer]), 'task.zip')\n\n\t\t// Upload to API\n\t\tconst response = await fetch(`${apiUrl}/api/task/upload`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tthrow new Error(`Upload failed: ${errorText}`)\n\t\t}\n\n\t\tconst result = await response.json()\n\n\t\tspinner.stop('Task uploaded successfully!')\n\n\t\tconst selectedOrg = organizations.find((org) => org.id === selectedOrgId)\n\n\t\tclack.log.message('')\n\t\tclack.log.success('Upload details:')\n\t\tclack.log.message(` ${pc.dim('Task:')} ${pc.cyan(finalTaskName)}`)\n\t\tclack.log.message(\n\t\t\t` ${pc.dim('Organization:')} ${pc.cyan(selectedOrg?.name || 'Unknown')}`,\n\t\t)\n\t\tclack.log.message(\n\t\t\t` ${pc.dim('Size:')} ${(zipBuffer.length / 1024).toFixed(2)} KB`,\n\t\t)\n\t\tclack.log.message(` ${pc.dim('Checksum:')} ${checksum.slice(0, 16)}...`)\n\t\tif (result.taskId) {\n\t\t\tclack.log.message(` ${pc.dim('Task ID:')} ${pc.green(result.taskId)}`)\n\t\t}\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Task uploaded!\\n\\n` +\n\t\t\t\t`Configure triggers in the dashboard: ${pc.cyan('https://thyme.sh/dashboard')}`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Upload failed')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { readFile } from 'node:fs/promises'\nimport { build } from 'esbuild'\n\nexport interface BundleResult {\n\tsource: string\n\tbundle: string\n}\n\n/**\n * Bundle task code with all dependencies using esbuild\n * Target: ESM format for Deno compatibility\n */\nexport async function bundleTask(taskPath: string): Promise<BundleResult> {\n\t// Read original source\n\tconst source = await readFile(taskPath, 'utf-8')\n\n\t// Node.js built-in modules that should not be bundled\n\tconst nodeBuiltins = [\n\t\t'assert',\n\t\t'buffer',\n\t\t'child_process',\n\t\t'cluster',\n\t\t'crypto',\n\t\t'dgram',\n\t\t'dns',\n\t\t'events',\n\t\t'fs',\n\t\t'http',\n\t\t'http2',\n\t\t'https',\n\t\t'net',\n\t\t'os',\n\t\t'path',\n\t\t'perf_hooks',\n\t\t'process',\n\t\t'querystring',\n\t\t'readline',\n\t\t'stream',\n\t\t'string_decoder',\n\t\t'timers',\n\t\t'tls',\n\t\t'tty',\n\t\t'url',\n\t\t'util',\n\t\t'v8',\n\t\t'vm',\n\t\t'zlib',\n\t\t// Node: prefix versions\n\t\t'node:assert',\n\t\t'node:buffer',\n\t\t'node:child_process',\n\t\t'node:cluster',\n\t\t'node:crypto',\n\t\t'node:dgram',\n\t\t'node:dns',\n\t\t'node:events',\n\t\t'node:fs',\n\t\t'node:http',\n\t\t'node:http2',\n\t\t'node:https',\n\t\t'node:net',\n\t\t'node:os',\n\t\t'node:path',\n\t\t'node:perf_hooks',\n\t\t'node:process',\n\t\t'node:querystring',\n\t\t'node:readline',\n\t\t'node:stream',\n\t\t'node:string_decoder',\n\t\t'node:timers',\n\t\t'node:tls',\n\t\t'node:tty',\n\t\t'node:url',\n\t\t'node:util',\n\t\t'node:v8',\n\t\t'node:vm',\n\t\t'node:zlib',\n\t]\n\n\t// Bundle with esbuild\n\tconst result = await build({\n\t\tentryPoints: [taskPath],\n\t\tbundle: true,\n\t\tformat: 'esm',\n\t\tplatform: 'neutral',\n\t\ttarget: 'esnext',\n\t\twrite: false,\n\t\ttreeShaking: true,\n\t\tminify: false, // Keep readable for debugging\n\t\tsourcemap: false,\n\t\texternal: nodeBuiltins, // Don't bundle Node.js built-ins\n\t\tlogLevel: 'silent',\n\t})\n\n\tif (result.outputFiles.length === 0) {\n\t\tthrow new Error('No output from bundler')\n\t}\n\n\tconst bundle = result.outputFiles[0].text\n\n\treturn {\n\t\tsource,\n\t\tbundle,\n\t}\n}\n","import { compressTask as sdkCompressTask } from '@thyme-sh/sdk'\n\nexport interface CompressResult {\n\tzipBuffer: Buffer\n\tchecksum: string\n}\n\n/**\n * Compress source and bundle into a ZIP archive\n * Uses SDK's compression function with fflate\n */\nexport function compressTask(source: string, bundle: string): CompressResult {\n\tconst { zipBuffer, checksum } = sdkCompressTask(source, bundle)\n\n\t// Convert Uint8Array to Buffer for Node.js\n\treturn {\n\t\tzipBuffer: Buffer.from(zipBuffer),\n\t\tchecksum,\n\t}\n}\n","import { z } from 'zod'\n\n/**\n * Extract Zod schema from task code and convert to JSON Schema\n * This allows the frontend to generate forms for task arguments\n */\nexport function extractSchemaFromTask(taskCode: string): string | null {\n\ttry {\n\t\t// Create a sandbox to safely evaluate the task code\n\t\t// We'll extract the schema by running the code and capturing the schema definition\n\t\tconst schemaExtractor = `\n const { z } = require('zod');\n const { zodToJsonSchema } = require('zod-to-json-schema');\n \n // Extended z with address validator\n const zodExtended = {\n ...z,\n address: () => z.string().refine((val) => /^0x[a-fA-F0-9]{40}$/.test(val), {\n message: 'Invalid Ethereum address',\n }),\n };\n \n // Mock defineTask to capture schema\n let capturedSchema = null;\n const defineTask = (definition) => {\n if (definition.schema) {\n capturedSchema = definition.schema;\n }\n return definition;\n };\n \n // Mock viem exports\n const encodeFunctionData = () => '0x';\n \n // Evaluate task code\n ${taskCode}\n \n // Convert schema to JSON Schema\n if (capturedSchema) {\n const jsonSchema = zodToJsonSchema(capturedSchema, { target: 'openApi3' });\n console.log(JSON.stringify(jsonSchema));\n } else {\n console.log('null');\n }\n `\n\n\t\t// For now, return a simple extraction by parsing the code\n\t\t// This is a simplified version - in production you might want to use a proper parser\n\t\tconst schemaMatch = taskCode.match(/schema:\\s*z\\.object\\(\\{([^}]+)\\}\\)/)\n\n\t\tif (!schemaMatch) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Parse the schema fields\n\t\tconst schemaContent = schemaMatch[1]\n\t\tconst fields: Record<string, unknown> = {}\n\n\t\t// Simple regex to extract field definitions\n\t\tconst fieldMatches = schemaContent.matchAll(\n\t\t\t/(\\w+):\\s*z\\.(\\w+)\\(\\)/g,\n\t\t)\n\n\t\tfor (const match of fieldMatches) {\n\t\t\tconst [, fieldName, fieldType] = match\n\t\t\tif (fieldName && fieldType) {\n\t\t\t\t// Convert Zod types to JSON Schema types\n\t\t\t\tlet jsonType = 'string'\n\t\t\t\tswitch (fieldType) {\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tjsonType = 'number'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\tjsonType = 'boolean'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'address':\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t}\n\n\t\t\t\tfields[fieldName] = {\n\t\t\t\t\ttype: jsonType,\n\t\t\t\t\t...(fieldType === 'address' && {\n\t\t\t\t\t\tpattern: '^0x[a-fA-F0-9]{40}$',\n\t\t\t\t\t\tdescription: 'Ethereum address',\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Object.keys(fields).length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst jsonSchema = {\n\t\t\ttype: 'object',\n\t\t\tproperties: fields,\n\t\t\trequired: Object.keys(fields),\n\t\t}\n\n\t\treturn JSON.stringify(jsonSchema)\n\t} catch (err) {\n\t\tconsole.error('Error extracting schema:', err)\n\t\treturn null\n\t}\n}\n"],"mappings":"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","names":["intro","outro","log","intro","outro","existsSync","join","intro","outro","existsSync","writeFile","join","existsSync","join","intro","join","existsSync","writeFile","outro","existsSync","mkdir","writeFile","join","intro","join","existsSync","mkdir","writeFile","outro","existsSync","readFile","config","resolve","error","intro","existsSync","config","readFile","log","outro","existsSync","readFile","intro","existsSync","outro"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/ui.ts","../src/utils/tasks.ts","../src/commands/list.ts","../src/commands/login.ts","../src/utils/env.ts","../src/commands/new.ts","../src/commands/run.ts","../src/deno/runner.ts","../src/commands/upload.ts","../src/utils/bundler.ts","../src/utils/compress.ts","../src/utils/schema-extractor.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { initCommand } from './commands/init'\nimport { listCommand } from './commands/list'\nimport { loginCommand } from './commands/login'\nimport { newCommand } from './commands/new'\nimport { runCommand } from './commands/run'\nimport { uploadCommand } from './commands/upload'\n\nconst program = new Command()\n\nprogram\n\t.name('thyme')\n\t.description('CLI for developing and deploying Thyme tasks')\n\t.version('0.1.0')\n\nprogram\n\t.command('init')\n\t.description('Initialize a new Thyme project')\n\t.argument('[name]', 'Project name')\n\t.action(initCommand)\n\nprogram\n\t.command('new')\n\t.description('Create a new task')\n\t.argument('[name]', 'Task name')\n\t.action(newCommand)\n\nprogram\n\t.command('run')\n\t.description('Run a task locally')\n\t.argument('[task]', 'Task name')\n\t.option('--simulate', 'Simulate on-chain execution')\n\t.action((task, options) => runCommand(task, options))\n\nprogram.command('list').description('List all tasks').action(listCommand)\n\nprogram\n\t.command('login')\n\t.description('Authenticate with Thyme Cloud')\n\t.action(loginCommand)\n\nprogram\n\t.command('upload')\n\t.description('Upload a task to Thyme Cloud')\n\t.argument('[task]', 'Task name')\n\t.option('-o, --organization <id>', 'Organization ID to upload to')\n\t.action((task, options) => uploadCommand(task, options.organization))\n\nprogram.parse()\n","import { existsSync } from 'node:fs'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\nexport async function initCommand(projectName?: string) {\n\tintro('Thyme CLI - Initialize Project')\n\n\t// Prompt for project name if not provided\n\tlet finalProjectName = projectName\n\tif (!finalProjectName) {\n\t\tconst name = await clack.text({\n\t\t\tmessage: 'What is your project name?',\n\t\t\tplaceholder: 'my-thyme-project',\n\t\t\tvalidate: (value) => {\n\t\t\t\tif (!value) return 'Project name is required'\n\t\t\t\tif (!/^[a-z0-9-]+$/.test(value))\n\t\t\t\t\treturn 'Project name must be lowercase alphanumeric with hyphens'\n\t\t\t},\n\t\t})\n\n\t\tif (clack.isCancel(name)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalProjectName = name as string\n\t}\n\n\tconst projectPath = join(process.cwd(), finalProjectName)\n\n\t// Check if directory exists\n\tif (existsSync(projectPath)) {\n\t\terror(`Directory \"${finalProjectName}\" already exists`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Creating project structure...')\n\n\ttry {\n\t\t// Create directories\n\t\tawait mkdir(projectPath, { recursive: true })\n\t\tawait mkdir(join(projectPath, 'functions'), { recursive: true })\n\n\t\t// Create package.json\n\t\tconst packageJson = {\n\t\t\tname: finalProjectName,\n\t\t\tversion: '0.1.0',\n\t\t\ttype: 'module',\n\t\t\tprivate: true,\n\t\t\tscripts: {\n\t\t\t\tdev: 'thyme run',\n\t\t\t},\n\t\t\tdependencies: {\n\t\t\t\t'@thyme-sh/sdk': '^0.1.0',\n\t\t\t\tviem: '^2.21.54',\n\t\t\t\tzod: '^3.24.1',\n\t\t\t},\n\t\t\tdevDependencies: {\n\t\t\t\t'@thyme-sh/cli': '^0.1.0',\n\t\t\t\ttypescript: '^5.7.2',\n\t\t\t},\n\t\t}\n\n\t\tawait writeFile(\n\t\t\tjoin(projectPath, 'package.json'),\n\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t)\n\n\t\t// Create tsconfig.json\n\t\tconst tsconfig = {\n\t\t\tcompilerOptions: {\n\t\t\t\ttarget: 'ES2022',\n\t\t\t\tmodule: 'ESNext',\n\t\t\t\tmoduleResolution: 'bundler',\n\t\t\t\tlib: ['ES2022', 'DOM'],\n\t\t\t\tstrict: true,\n\t\t\t\tesModuleInterop: true,\n\t\t\t\tskipLibCheck: true,\n\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\tresolveJsonModule: true,\n\t\t\t},\n\t\t\tinclude: ['functions/**/*'],\n\t\t}\n\n\t\tawait writeFile(\n\t\t\tjoin(projectPath, 'tsconfig.json'),\n\t\t\tJSON.stringify(tsconfig, null, 2),\n\t\t)\n\n\t\t// Create .env.example\n\t\tconst envExample = `# Simulation settings (for --simulate flag)\nRPC_URL=https://eth-sepolia.g.alchemy.com/v2/your-key\nSIMULATE_ACCOUNT=0x742d35Cc6634C0532925a3b844Bc454e4438f44e\n\n# Cloud authentication (set by \\`thyme login\\`)\nTHYME_AUTH_TOKEN=\n\n# Cloud API URL (required - your Convex deployment URL)\n# Example: https://your-deployment.convex.cloud\nTHYME_API_URL=\n`\n\n\t\tawait writeFile(join(projectPath, '.env.example'), envExample)\n\n\t\t// Create .gitignore\n\t\tconst gitignore = `node_modules/\ndist/\n.env\n.env.local\n*.log\n`\n\n\t\tawait writeFile(join(projectPath, '.gitignore'), gitignore)\n\n\t\t// Create README\n\t\tconst readme = `# ${finalProjectName}\n\nA Thyme project for Web3 automation tasks.\n\n## Getting Started\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Create a new task\nthyme new my-task\n\n# Run a task locally\nthyme run my-task\n\n# Simulate on-chain\nthyme run my-task --simulate\n\n# Deploy to cloud\nthyme login\nthyme upload my-task\n\\`\\`\\`\n\n## Project Structure\n\n\\`\\`\\`\nfunctions/\n my-task/\n index.ts # Task definition\n args.json # Test arguments\n\\`\\`\\`\n`\n\n\t\tawait writeFile(join(projectPath, 'README.md'), readme)\n\n\t\tspinner.stop('Project created successfully!')\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Project initialized!\\n\\nNext steps:\\n ${pc.cyan('cd')} ${finalProjectName}\\n ${pc.cyan('npm install')}\\n ${pc.cyan('thyme new')} my-task\\n ${pc.cyan('thyme run')} my-task`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Failed to create project')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import * as clack from '@clack/prompts'\nimport pc from 'picocolors'\n\nexport { clack, pc }\n\nexport function intro(title: string) {\n\tclack.intro(pc.bgCyan(pc.black(` ${title} `)))\n}\n\nexport function outro(message: string) {\n\tclack.outro(message)\n}\n\nexport function error(message: string) {\n\tclack.log.error(pc.red(message))\n}\n\nexport function info(message: string) {\n\tclack.log.info(pc.cyan(message))\n}\n\nexport function warn(message: string) {\n\tclack.log.warn(pc.yellow(message))\n}\n\nexport function step(message: string) {\n\tclack.log.step(message)\n}\n\nexport function log(message: string) {\n\tclack.log.message(message)\n}\n","import { existsSync } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { join } from 'node:path'\n\n/**\n * Discover all tasks in the functions directory\n */\nexport async function discoverTasks(projectRoot: string): Promise<string[]> {\n\tconst functionsDir = join(projectRoot, 'functions')\n\n\tif (!existsSync(functionsDir)) {\n\t\treturn []\n\t}\n\n\ttry {\n\t\tconst entries = await readdir(functionsDir, { withFileTypes: true })\n\n\t\treturn entries\n\t\t\t.filter((e) => e.isDirectory())\n\t\t\t.filter((e) => existsSync(join(functionsDir, e.name, 'index.ts')))\n\t\t\t.map((e) => e.name)\n\t} catch {\n\t\treturn []\n\t}\n}\n\n/**\n * Get the path to a task's index file\n */\nexport function getTaskPath(projectRoot: string, taskName: string): string {\n\treturn join(projectRoot, 'functions', taskName, 'index.ts')\n}\n\n/**\n * Get the path to a task's args file\n */\nexport function getTaskArgsPath(projectRoot: string, taskName: string): string {\n\treturn join(projectRoot, 'functions', taskName, 'args.json')\n}\n\n/**\n * Check if we're in a Thyme project\n */\nexport function isThymeProject(projectRoot: string): boolean {\n\tconst functionsDir = join(projectRoot, 'functions')\n\treturn existsSync(functionsDir)\n}\n","import { discoverTasks, isThymeProject } from '../utils/tasks'\nimport { clack, intro, outro, pc, step } from '../utils/ui'\n\nexport async function listCommand() {\n\tintro('Thyme CLI - List Tasks')\n\n\tconst projectRoot = process.cwd()\n\n\tif (!isThymeProject(projectRoot)) {\n\t\toutro(pc.red('Not in a Thyme project'))\n\t\tprocess.exit(1)\n\t}\n\n\tconst tasks = await discoverTasks(projectRoot)\n\n\tif (tasks.length === 0) {\n\t\toutro(pc.yellow('No tasks found. Create one with `thyme new`'))\n\t\treturn\n\t}\n\n\tstep(`Found ${tasks.length} task(s):`)\n\tfor (const task of tasks) {\n\t\tclack.log.message(` ${pc.cyan('●')} ${task}`)\n\t}\n\n\toutro('')\n}\n","import { existsSync } from 'node:fs'\nimport { appendFile, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { clack, error, info, intro, outro, pc } from '../utils/ui'\n\nexport async function loginCommand() {\n\tintro('Thyme CLI - Login')\n\n\tconst projectRoot = process.cwd()\n\tconst envPath = join(projectRoot, '.env')\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Show instructions\n\tinfo('To authenticate with Thyme Cloud:')\n\tclack.log.message(\n\t\t` 1. Visit ${pc.cyan('https://thyme.sh/settings/api-keys')}`,\n\t)\n\tclack.log.message(' 2. Generate a new API token')\n\tclack.log.message(' 3. Copy the token and paste it below')\n\tclack.log.message('')\n\n\t// Prompt for token\n\tconst token = await clack.password({\n\t\tmessage: 'Paste your API token:',\n\t\tvalidate: (value) => {\n\t\t\tif (!value) return 'Token is required'\n\t\t\tif (value.length < 10) return 'Token seems too short'\n\t\t},\n\t})\n\n\tif (clack.isCancel(token)) {\n\t\tclack.cancel('Operation cancelled')\n\t\tprocess.exit(0)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Verifying token...')\n\n\ttry {\n\t\t// Get API URL (Convex deployment URL)\n\t\tconst apiUrl = getEnv('THYME_API_URL')\n\n\t\tif (!apiUrl) {\n\t\t\tspinner.stop('Configuration error')\n\t\t\terror(\n\t\t\t\t'THYME_API_URL is not set. Please set it to your Convex deployment URL (e.g., https://your-deployment.convex.cloud)',\n\t\t\t)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\t// Verify token with API\n\t\tconst verifyResponse = await fetch(`${apiUrl}/api/auth/verify`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t},\n\t\t})\n\n\t\tif (!verifyResponse.ok) {\n\t\t\tspinner.stop('Token verification failed')\n\t\t\tconst errorText = await verifyResponse.text()\n\t\t\terror(`Invalid token: ${errorText}`)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst verifyData = (await verifyResponse.json()) as {\n\t\t\tuser: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\temail: string\n\t\t\t}\n\t\t\torganizations: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\trole: string\n\t\t\t}[]\n\t\t}\n\n\t\tspinner.stop('Token verified!')\n\n\t\t// Save token\n\t\tconst saveSpinner = clack.spinner()\n\t\tsaveSpinner.start('Saving token...')\n\n\t\t// Read existing .env or create new\n\t\tlet envContent = ''\n\t\tif (existsSync(envPath)) {\n\t\t\tenvContent = await readFile(envPath, 'utf-8')\n\t\t}\n\n\t\t// Check if THYME_AUTH_TOKEN already exists\n\t\tconst tokenRegex = /^THYME_AUTH_TOKEN=.*$/m\n\t\tif (tokenRegex.test(envContent)) {\n\t\t\t// Replace existing token\n\t\t\tenvContent = envContent.replace(tokenRegex, `THYME_AUTH_TOKEN=${token}`)\n\t\t\tawait writeFile(envPath, envContent)\n\t\t} else {\n\t\t\t// Append new token\n\t\t\tconst newLine = envContent && !envContent.endsWith('\\n') ? '\\n' : ''\n\t\t\tawait appendFile(envPath, `${newLine}THYME_AUTH_TOKEN=${token}\\n`)\n\t\t}\n\n\t\tsaveSpinner.stop('Token saved successfully!')\n\n\t\t// Display user info\n\t\tclack.log.message('')\n\t\tclack.log.success('Authenticated as:')\n\t\tclack.log.message(\n\t\t\t` ${pc.cyan('User:')} ${verifyData.user.name || verifyData.user.email}`,\n\t\t)\n\t\tclack.log.message(` ${pc.cyan('Email:')} ${verifyData.user.email}`)\n\n\t\tif (verifyData.organizations && verifyData.organizations.length > 0) {\n\t\t\tclack.log.message('')\n\t\t\tclack.log.message(`${pc.cyan('Organizations:')}`)\n\t\t\tfor (const org of verifyData.organizations) {\n\t\t\t\tclack.log.message(` • ${org.name} ${pc.dim(`(${org.role})`)}`)\n\t\t\t}\n\t\t}\n\n\t\toutro(`\\nYou can now upload tasks with ${pc.cyan('thyme upload')}`)\n\t} catch (err) {\n\t\tspinner.stop('Failed to verify token')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { config } from 'dotenv'\n\n/**\n * Load environment variables from .env file\n */\nexport function loadEnv(projectRoot: string): void {\n\tconst envPath = join(projectRoot, '.env')\n\tif (existsSync(envPath)) {\n\t\tconfig({ path: envPath })\n\t}\n}\n\n/**\n * Get environment variable with fallback\n */\nexport function getEnv(key: string, fallback?: string): string | undefined {\n\treturn process.env[key] ?? fallback\n}\n\n/**\n * Get required environment variable\n */\nexport function getRequiredEnv(key: string): string {\n\tconst value = process.env[key]\n\tif (!value) {\n\t\tthrow new Error(`Missing required environment variable: ${key}`)\n\t}\n\treturn value\n}\n","import { existsSync } from 'node:fs'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { isThymeProject } from '../utils/tasks'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\nexport async function newCommand(taskName?: string) {\n\tintro('Thyme CLI - Create New Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project. Run `thyme init` first.')\n\t\tprocess.exit(1)\n\t}\n\n\t// Prompt for task name if not provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst name = await clack.text({\n\t\t\tmessage: 'What is your task name?',\n\t\t\tplaceholder: 'my-task',\n\t\t\tvalidate: (value) => {\n\t\t\t\tif (!value) return 'Task name is required'\n\t\t\t\tif (!/^[a-z0-9-]+$/.test(value))\n\t\t\t\t\treturn 'Task name must be lowercase alphanumeric with hyphens'\n\t\t\t},\n\t\t})\n\n\t\tif (clack.isCancel(name)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = name as string\n\t}\n\n\tconst taskPath = join(projectRoot, 'functions', finalTaskName)\n\n\t// Check if task already exists\n\tif (existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" already exists`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Creating task...')\n\n\ttry {\n\t\t// Create task directory\n\t\tawait mkdir(taskPath, { recursive: true })\n\n\t\t// Create index.ts\n\t\tconst indexTs = `import { defineTask, z } from '@thyme-sh/sdk'\nimport { encodeFunctionData } from 'viem'\n\nexport default defineTask({\n\tschema: z.object({\n\t\ttargetAddress: z.address(),\n\t}),\n\n\tasync run(ctx) {\n\t\tconst { targetAddress } = ctx.args\n\n\t\t// Your task logic here\n\t\tconsole.log('Running task with address:', targetAddress)\n\n\t\t// Example: Read from blockchain using the public client\n\t\t// const balance = await ctx.client.getBalance({ address: targetAddress })\n\t\t// const blockNumber = await ctx.client.getBlockNumber()\n\t\t// const value = await ctx.client.readContract({\n\t\t// address: targetAddress,\n\t\t// abi: [...],\n\t\t// functionName: 'balanceOf',\n\t\t// args: [someAddress],\n\t\t// })\n\n\t\t// Example: Return calls to execute\n\t\treturn {\n\t\t\tcanExec: true,\n\t\t\tcalls: [\n\t\t\t\t{\n\t\t\t\t\tto: targetAddress,\n\t\t\t\t\tdata: '0x' as const,\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\n\t\t// Example with encodeFunctionData:\n\t\t// const abi = [...] as const\n\t\t// return {\n\t\t// canExec: true,\n\t\t// calls: [\n\t\t// {\n\t\t// to: targetAddress,\n\t\t// data: encodeFunctionData({\n\t\t// abi,\n\t\t// functionName: 'transfer',\n\t\t// args: [recipientAddress, 1000n],\n\t\t// }),\n\t\t// },\n\t\t// ],\n\t\t// }\n\n\t\t// Or return false if conditions not met\n\t\t// return {\n\t\t// canExec: false,\n\t\t// message: 'Conditions not met'\n\t\t// }\n\t},\n})\n`\n\n\t\tawait writeFile(join(taskPath, 'index.ts'), indexTs)\n\n\t\t// Create args.json\n\t\tconst args = {\n\t\t\ttargetAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',\n\t\t}\n\n\t\tawait writeFile(join(taskPath, 'args.json'), JSON.stringify(args, null, 2))\n\n\t\tspinner.stop('Task created successfully!')\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Task \"${finalTaskName}\" created!\\n\\nNext steps:\\n ${pc.cyan('Edit')} functions/${finalTaskName}/index.ts\\n ${pc.cyan('Update')} functions/${finalTaskName}/args.json\\n ${pc.cyan('thyme run')} ${finalTaskName}`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Failed to create task')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport type { Address } from 'viem'\nimport { createPublicClient, formatEther, http, isAddress } from 'viem'\nimport { checkDeno, runInDeno, type TaskConfig } from '../deno/runner'\nimport { getEnv, loadEnv } from '../utils/env'\nimport {\n\tdiscoverTasks,\n\tgetTaskArgsPath,\n\tgetTaskPath,\n\tisThymeProject,\n} from '../utils/tasks'\nimport {\n\tclack,\n\terror,\n\tinfo,\n\tintro,\n\tlog,\n\toutro,\n\tpc,\n\tstep,\n\twarn,\n} from '../utils/ui'\n\ninterface RunOptions {\n\tsimulate?: boolean\n}\n\nexport async function runCommand(taskName?: string, options: RunOptions = {}) {\n\tintro('Thyme CLI - Run Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project')\n\t\tprocess.exit(1)\n\t}\n\n\t// Check if Deno is installed\n\tconst hasDeno = await checkDeno()\n\tif (!hasDeno) {\n\t\terror('Deno is not installed. Please install Deno: https://deno.land/')\n\t\tprocess.exit(1)\n\t}\n\n\t// Discover tasks if no task name provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst tasks = await discoverTasks(projectRoot)\n\n\t\tif (tasks.length === 0) {\n\t\t\terror('No tasks found. Create one with `thyme new`')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select a task to run:',\n\t\t\toptions: tasks.map((task) => ({ value: task, label: task })),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = selected as string\n\t}\n\n\tconst taskPath = getTaskPath(projectRoot, finalTaskName)\n\tconst argsPath = getTaskArgsPath(projectRoot, finalTaskName)\n\n\t// Check if task exists\n\tif (!existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" not found`)\n\t\tprocess.exit(1)\n\t}\n\n\t// Use default config\n\tconst config: TaskConfig = {\n\t\tmemory: 128,\n\t\ttimeout: 30,\n\t\tnetwork: true,\n\t\trpcUrl: getEnv('RPC_URL'),\n\t}\n\n\t// Load args\n\tlet args: unknown = {}\n\tif (existsSync(argsPath)) {\n\t\ttry {\n\t\t\tconst argsData = await readFile(argsPath, 'utf-8')\n\t\t\targs = JSON.parse(argsData)\n\t\t} catch (err) {\n\t\t\twarn(\n\t\t\t\t`Failed to load args.json: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t)\n\t\t}\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Executing task in Deno sandbox...')\n\n\t// Run task\n\tconst result = await runInDeno(taskPath, args, config)\n\n\tif (!result.success) {\n\t\tspinner.stop('Task execution failed')\n\t\terror(result.error ?? 'Unknown error')\n\t\tif (result.logs.length > 0) {\n\t\t\tstep('Task output:')\n\t\t\tfor (const taskLog of result.logs) {\n\t\t\t\tlog(` ${taskLog}`)\n\t\t\t}\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop('Task executed successfully')\n\n\t// Show logs\n\tif (result.logs.length > 0) {\n\t\tlog('')\n\t\tstep('Task output:')\n\t\tfor (const taskLog of result.logs) {\n\t\t\tlog(` ${taskLog}`)\n\t\t}\n\t}\n\n\t// Show result\n\tif (!result.result) {\n\t\terror('No result returned from task')\n\t\tprocess.exit(1)\n\t}\n\n\tlog('')\n\tif (result.result.canExec) {\n\t\tinfo(\n\t\t\t`${pc.green('✓')} Result: canExec = true (${result.result.calls.length} call(s))`,\n\t\t)\n\n\t\t// Show calls\n\t\tlog('')\n\t\tstep('Calls to execute:')\n\t\tfor (const call of result.result.calls) {\n\t\t\tlog(` ${pc.cyan('→')} to: ${call.to}`)\n\t\t\tlog(` data: ${call.data}`)\n\t\t}\n\n\t\t// Simulate if requested\n\t\tif (options.simulate) {\n\t\t\tlog('')\n\t\t\tawait simulateCalls(result.result.calls)\n\t\t}\n\t} else {\n\t\twarn('Result: canExec = false')\n\t\tinfo(`Message: ${result.result.message}`)\n\t}\n\n\t// Show execution stats\n\tlog('')\n\tif (\n\t\tresult.executionTime !== undefined ||\n\t\tresult.memoryUsed !== undefined ||\n\t\tresult.rpcRequestCount !== undefined\n\t) {\n\t\tstep('Execution stats:')\n\t\tif (result.executionTime !== undefined) {\n\t\t\tlog(` Duration: ${result.executionTime.toFixed(2)}ms`)\n\t\t}\n\t\tif (result.memoryUsed !== undefined) {\n\t\t\tconst memoryMB = (result.memoryUsed / 1024 / 1024).toFixed(2)\n\t\t\tlog(` Memory: ${memoryMB}MB`)\n\t\t}\n\t\tif (result.rpcRequestCount !== undefined) {\n\t\t\tlog(` RPC Requests: ${result.rpcRequestCount}`)\n\t\t}\n\t}\n\n\t// Show simulation tip if task can execute and simulation wasn't run\n\tif (result.result?.canExec && !options.simulate) {\n\t\tlog('')\n\t\tinfo(\n\t\t\t`${pc.dim('💡 Tip: Test calls on-chain with:')} ${pc.cyan(`thyme run ${finalTaskName} --simulate`)}`,\n\t\t)\n\t\toutro('')\n\t} else {\n\t\toutro('')\n\t}\n}\n\nasync function simulateCalls(\n\tcalls: Array<{ to: Address; data: `0x${string}` }>,\n) {\n\tconst rpcUrl = getEnv('RPC_URL')\n\tconst account = getEnv('SIMULATE_ACCOUNT')\n\n\tif (!rpcUrl || !account) {\n\t\twarn('Simulation requires RPC_URL and SIMULATE_ACCOUNT in .env file')\n\t\treturn\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Simulating on-chain...')\n\n\ttry {\n\t\tconst client = createPublicClient({\n\t\t\ttransport: http(rpcUrl),\n\t\t})\n\n\t\t// Get chain info\n\t\tconst chainId = await client.getChainId()\n\t\tconst blockNumber = await client.getBlockNumber()\n\n\t\tspinner.stop('Simulating on-chain...')\n\n\t\tlog('')\n\t\tinfo(`Chain ID: ${chainId}`)\n\t\tinfo(`Block: ${blockNumber}`)\n\t\tinfo(`Account: ${account}`)\n\n\t\t// Validate account address\n\t\tif (!isAddress(account)) {\n\t\t\tspinner.stop('Invalid account address')\n\t\t\tlog('')\n\t\t\terror(`SIMULATE_ACCOUNT is not a valid Ethereum address: ${account}`)\n\t\t\treturn\n\t\t}\n\n\t\t// Simulate all calls at once using viem's simulateCalls\n\t\tconst simulationSpinner = clack.spinner()\n\t\tsimulationSpinner.start('Running simulation...')\n\n\t\tconst { results } = await client.simulateCalls({\n\t\t\taccount: account as Address,\n\t\t\tcalls: calls.map((call) => ({\n\t\t\t\tto: call.to,\n\t\t\t\tdata: call.data,\n\t\t\t})),\n\t\t})\n\n\t\tsimulationSpinner.stop('Simulation complete')\n\n\t\t// Check results for failures\n\t\tconst failedCalls: Array<{\n\t\t\tindex: number\n\t\t\tcall: { to: Address; data: `0x${string}` }\n\t\t\terror?: string\n\t\t}> = []\n\t\tfor (let i = 0; i < results.length; i++) {\n\t\t\tconst result = results[i]\n\t\t\tconst call = calls[i]\n\t\t\tif (!result || !call) continue\n\n\t\t\tif (result.status === 'failure') {\n\t\t\t\tfailedCalls.push({\n\t\t\t\t\tindex: i,\n\t\t\t\t\tcall,\n\t\t\t\t\terror: result.error?.message || 'Unknown error',\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tif (failedCalls.length > 0) {\n\t\t\tlog('')\n\t\t\terror('Some calls would revert:')\n\t\t\tfor (const failed of failedCalls) {\n\t\t\t\terror(\n\t\t\t\t\t` Call ${failed.index + 1} to ${failed.call.to}: ${failed.error}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Get gas price\n\t\tconst gasPrice = await client.getGasPrice()\n\n\t\tclack.log.step('Simulation results:')\n\t\tclack.log.success('All calls would succeed')\n\n\t\t// Show gas usage if available\n\t\tconst totalGas = results.reduce((sum, r) => sum + (r.gasUsed || 0n), 0n)\n\t\tif (totalGas > 0n) {\n\t\t\tclack.log.message(` Total gas: ${totalGas.toString()}`)\n\t\t}\n\n\t\tclack.log.message(` Gas price: ${formatEther(gasPrice)} ETH`)\n\t} catch (err) {\n\t\tspinner.stop('Simulation failed')\n\t\tlog('')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t}\n}\n","import { spawn } from 'node:child_process'\nimport { dirname, resolve } from 'node:path'\nimport type { TaskResult } from '@thyme-sh/sdk'\n\nexport interface TaskConfig {\n\tmemory: number // MB\n\ttimeout: number // seconds\n\tnetwork: boolean\n\trpcUrl?: string // RPC URL for public client\n}\n\nexport interface RunResult {\n\tsuccess: boolean\n\tresult?: TaskResult\n\tlogs: string[]\n\terror?: string\n\texecutionTime?: number // milliseconds\n\tmemoryUsed?: number // bytes\n\trpcRequestCount?: number // number of RPC requests made\n}\n\n/**\n * Run a task in Deno sandbox - similar to Gelato's w3f test and @deno/sandbox\n * Creates an isolated Deno process with controlled permissions\n */\nexport async function runInDeno(\n\ttaskPath: string,\n\targs: unknown,\n\tconfig: TaskConfig,\n): Promise<RunResult> {\n\tconst taskDir = dirname(resolve(taskPath))\n\tconst absoluteTaskPath = resolve(taskPath)\n\n\tconst denoFlags = ['run', '--no-prompt']\n\n\t// Sandbox permissions - minimal by default, similar to @deno/sandbox\n\tdenoFlags.push(`--allow-read=${taskDir}`) // Only allow reading task directory\n\n\t// Add memory limit if specified\n\tif (config.memory) {\n\t\tdenoFlags.push(`--v8-flags=--max-old-space-size=${config.memory}`)\n\t}\n\n\t// Conditionally allow network (similar to allowNet in @deno/sandbox)\n\tif (config.network) {\n\t\tdenoFlags.push('--allow-net')\n\t}\n\n\t// Execute inline wrapper via stdin (similar to Gelato's approach)\n\tdenoFlags.push('-')\n\n\t// Execution wrapper that loads and runs the task\n\t// Similar to how Gelato's w3f test executes functions\n\tconst execScript = `\nimport task from '${absoluteTaskPath}';\nimport { createPublicClient, http } from 'npm:viem@2.21.54';\n\n// Create RPC request counter\nlet rpcRequestCount = 0;\n\n// Wrap the http transport to count requests\nconst countingHttp = (url) => {\n\tconst baseTransport = http(url);\n\treturn (config) => {\n\t\tconst transport = baseTransport(config);\n\t\treturn {\n\t\t\t...transport,\n\t\t\trequest: async (params) => {\n\t\t\t\trpcRequestCount++;\n\t\t\t\treturn transport.request(params);\n\t\t\t},\n\t\t};\n\t};\n};\n\n// Create public client for blockchain reads\nconst client = createPublicClient({\n\ttransport: countingHttp(${config.rpcUrl ? `'${config.rpcUrl}'` : 'undefined'}),\n});\n\nconst context = {\n\targs: ${JSON.stringify(args)},\n\tclient,\n};\n\ntry {\n\t// Track execution time and memory\n\tconst startTime = performance.now();\n\tconst startMemory = Deno.memoryUsage().heapUsed;\n\t\n\tconst result = await task.run(context);\n\t\n\tconst endTime = performance.now();\n\tconst endMemory = Deno.memoryUsage().heapUsed;\n\t\n\tconst executionTime = endTime - startTime;\n\tconst memoryUsed = endMemory - startMemory;\n\t\n\tconsole.log('__THYME_RESULT__' + JSON.stringify(result));\n\tconsole.log('__THYME_STATS__' + JSON.stringify({ executionTime, memoryUsed, rpcRequestCount }));\n} catch (error) {\n\tconsole.error('Task execution error:', error instanceof Error ? error.message : String(error));\n\tDeno.exit(1);\n}\n`\n\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn('deno', denoFlags, {\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\ttimeout: config.timeout * 1000,\n\t\t\tcwd: taskDir,\n\t\t})\n\n\t\tlet stdout = ''\n\t\tlet stderr = ''\n\t\tconst logs: string[] = []\n\n\t\t// Write the execution script to stdin\n\t\tproc.stdin?.write(execScript)\n\t\tproc.stdin?.end()\n\n\t\tproc.stdout?.on('data', (data) => {\n\t\t\tstdout += data.toString()\n\t\t})\n\n\t\tproc.stderr?.on('data', (data) => {\n\t\t\tstderr += data.toString()\n\t\t})\n\n\t\tproc.on('close', (code) => {\n\t\t\tif (code !== 0) {\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tlogs,\n\t\t\t\t\terror: stderr || `Process exited with code ${code}`,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Extract logs, result, and stats from stdout\n\t\t\t\tconst lines = stdout.trim().split('\\n')\n\t\t\t\tlet resultLine: string | undefined\n\t\t\t\tlet statsLine: string | undefined\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith('__THYME_RESULT__')) {\n\t\t\t\t\t\tresultLine = line.substring('__THYME_RESULT__'.length)\n\t\t\t\t\t} else if (line.startsWith('__THYME_STATS__')) {\n\t\t\t\t\t\tstatsLine = line.substring('__THYME_STATS__'.length)\n\t\t\t\t\t} else if (line.trim()) {\n\t\t\t\t\t\tlogs.push(line.trim())\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!resultLine) {\n\t\t\t\t\tthrow new Error('No result found in output')\n\t\t\t\t}\n\n\t\t\t\tconst result = JSON.parse(resultLine) as TaskResult\n\t\t\t\tconst stats = statsLine\n\t\t\t\t\t? JSON.parse(statsLine)\n\t\t\t\t\t: {\n\t\t\t\t\t\t\texecutionTime: undefined,\n\t\t\t\t\t\t\tmemoryUsed: undefined,\n\t\t\t\t\t\t\trpcRequestCount: undefined,\n\t\t\t\t\t\t}\n\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tresult,\n\t\t\t\t\tlogs,\n\t\t\t\t\texecutionTime: stats.executionTime,\n\t\t\t\t\tmemoryUsed: stats.memoryUsed,\n\t\t\t\t\trpcRequestCount: stats.rpcRequestCount,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tresolve({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tlogs,\n\t\t\t\t\terror: `Failed to parse result: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\tproc.on('error', (error) => {\n\t\t\tresolve({\n\t\t\t\tsuccess: false,\n\t\t\t\tlogs,\n\t\t\t\terror: `Failed to spawn Deno: ${error.message}`,\n\t\t\t})\n\t\t})\n\t})\n}\n\n/**\n * Check if Deno is installed\n */\nexport async function checkDeno(): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn('deno', ['--version'], { stdio: 'ignore' })\n\t\tproc.on('close', (code) => resolve(code === 0))\n\t\tproc.on('error', () => resolve(false))\n\t})\n}\n","import { existsSync } from 'node:fs'\nimport { bundleTask } from '../utils/bundler'\nimport { compressTask } from '../utils/compress'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { extractSchemaFromTask } from '../utils/schema-extractor'\nimport { discoverTasks, getTaskPath, isThymeProject } from '../utils/tasks'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\nexport async function uploadCommand(\n\ttaskName?: string,\n\torganizationId?: string,\n) {\n\tintro('Thyme CLI - Upload Task')\n\n\tconst projectRoot = process.cwd()\n\n\t// Load environment variables\n\tloadEnv(projectRoot)\n\n\t// Check if we're in a Thyme project\n\tif (!isThymeProject(projectRoot)) {\n\t\terror('Not in a Thyme project')\n\t\tprocess.exit(1)\n\t}\n\n\t// Check for auth token\n\tconst authToken = getEnv('THYME_AUTH_TOKEN')\n\tif (!authToken) {\n\t\terror('Not authenticated. Run `thyme login` first.')\n\t\tprocess.exit(1)\n\t}\n\n\t// Get API URL (Convex deployment URL)\n\tconst apiUrl = getEnv('THYME_API_URL')\n\tif (!apiUrl) {\n\t\terror(\n\t\t\t'THYME_API_URL is not set. Please set it to your Convex deployment URL in .env',\n\t\t)\n\t\tprocess.exit(1)\n\t}\n\n\t// Discover tasks if no task name provided\n\tlet finalTaskName = taskName\n\tif (!finalTaskName) {\n\t\tconst tasks = await discoverTasks(projectRoot)\n\n\t\tif (tasks.length === 0) {\n\t\t\terror('No tasks found. Create one with `thyme new`')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select a task to upload:',\n\t\t\toptions: tasks.map((task) => ({ value: task, label: task })),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tfinalTaskName = selected as string\n\t}\n\n\t// Fetch user's organizations\n\tconst orgSpinner = clack.spinner()\n\torgSpinner.start('Fetching organizations...')\n\n\tlet organizations: { id: string; name: string; role: string }[] = []\n\ttry {\n\t\tconst verifyResponse = await fetch(`${apiUrl}/api/auth/verify`, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t\t},\n\t\t})\n\n\t\tif (!verifyResponse.ok) {\n\t\t\torgSpinner.stop('Failed to fetch organizations')\n\t\t\terror('Failed to authenticate. Please run `thyme login` again.')\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst verifyData = (await verifyResponse.json()) as {\n\t\t\tuser: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\temail: string\n\t\t\t}\n\t\t\torganizations: {\n\t\t\t\tid: string\n\t\t\t\tname: string\n\t\t\t\trole: string\n\t\t\t}[]\n\t\t}\n\n\t\torganizations = verifyData.organizations || []\n\t\torgSpinner.stop('Organizations loaded')\n\t} catch (err) {\n\t\torgSpinner.stop('Failed to fetch organizations')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n\n\t// Check if user has any organizations\n\tif (organizations.length === 0) {\n\t\terror(\n\t\t\t'You are not a member of any organizations. Please create or join an organization first.',\n\t\t)\n\t\tprocess.exit(1)\n\t}\n\n\t// Determine organization to upload to\n\tlet selectedOrgId = organizationId\n\n\t// If organization ID was provided, validate it\n\tif (selectedOrgId) {\n\t\tconst orgExists = organizations.find((org) => org.id === selectedOrgId)\n\t\tif (!orgExists) {\n\t\t\terror(\n\t\t\t\t`Organization with ID \"${selectedOrgId}\" not found or you don't have access to it.`,\n\t\t\t)\n\t\t\tprocess.exit(1)\n\t\t}\n\t} else {\n\t\t// Prompt user to select an organization\n\t\tconst selected = await clack.select({\n\t\t\tmessage: 'Select an organization to upload to:',\n\t\t\toptions: organizations.map((org) => ({\n\t\t\t\tvalue: org.id,\n\t\t\t\tlabel: `${org.name} ${pc.dim(`(${org.role})`)}`,\n\t\t\t})),\n\t\t})\n\n\t\tif (clack.isCancel(selected)) {\n\t\t\tclack.cancel('Operation cancelled')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tselectedOrgId = selected as string\n\t}\n\n\tconst taskPath = getTaskPath(projectRoot, finalTaskName)\n\n\t// Check if task exists\n\tif (!existsSync(taskPath)) {\n\t\terror(`Task \"${finalTaskName}\" not found`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = clack.spinner()\n\tspinner.start('Bundling task...')\n\n\ttry {\n\t\t// Bundle task code with all dependencies\n\t\tconst { source, bundle } = await bundleTask(taskPath)\n\n\t\tspinner.message('Extracting schema...')\n\n\t\t// Extract schema from source code\n\t\tconst schema = extractSchemaFromTask(source)\n\n\t\tspinner.message('Compressing files...')\n\n\t\t// Compress source and bundle into ZIP\n\t\tconst { zipBuffer, checksum } = compressTask(source, bundle)\n\n\t\tspinner.message('Uploading to cloud...')\n\n\t\t// Create form data\n\t\tconst formData = new FormData()\n\n\t\t// Add metadata\n\t\tformData.append(\n\t\t\t'data',\n\t\t\tJSON.stringify({\n\t\t\t\torganizationId: selectedOrgId as string,\n\t\t\t\tcheckSum: checksum,\n\t\t\t\tschema: schema || undefined,\n\t\t\t}),\n\t\t)\n\n\t\t// Add ZIP blob\n\t\tformData.append('blob', new Blob([zipBuffer]), 'task.zip')\n\n\t\t// Upload to API\n\t\tconst response = await fetch(`${apiUrl}/api/task/upload`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t\t},\n\t\t\tbody: formData,\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tthrow new Error(`Upload failed: ${errorText}`)\n\t\t}\n\n\t\tconst result = (await response.json()) as { taskId?: string }\n\n\t\tspinner.stop('Task uploaded successfully!')\n\n\t\tconst selectedOrg = organizations.find((org) => org.id === selectedOrgId)\n\n\t\tclack.log.message('')\n\t\tclack.log.success('Upload details:')\n\t\tclack.log.message(` ${pc.dim('Task:')} ${pc.cyan(finalTaskName)}`)\n\t\tclack.log.message(\n\t\t\t` ${pc.dim('Organization:')} ${pc.cyan(selectedOrg?.name || 'Unknown')}`,\n\t\t)\n\t\tclack.log.message(\n\t\t\t` ${pc.dim('Size:')} ${(zipBuffer.length / 1024).toFixed(2)} KB`,\n\t\t)\n\t\tclack.log.message(` ${pc.dim('Checksum:')} ${checksum.slice(0, 16)}...`)\n\t\tif (result.taskId) {\n\t\t\tclack.log.message(` ${pc.dim('Task ID:')} ${pc.green(result.taskId)}`)\n\t\t}\n\n\t\toutro(\n\t\t\t`${pc.green('✓')} Task uploaded!\\n\\n` +\n\t\t\t\t`Configure triggers in the dashboard: ${pc.cyan('https://thyme.sh/dashboard')}`,\n\t\t)\n\t} catch (err) {\n\t\tspinner.stop('Upload failed')\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\n}\n","import { readFile } from 'node:fs/promises'\nimport { build } from 'esbuild'\n\nexport interface BundleResult {\n\tsource: string\n\tbundle: string\n}\n\n/**\n * Bundle task code with all dependencies using esbuild\n * Target: ESM format for Deno compatibility\n */\nexport async function bundleTask(taskPath: string): Promise<BundleResult> {\n\t// Read original source\n\tconst source = await readFile(taskPath, 'utf-8')\n\n\t// Node.js built-in modules that should not be bundled\n\tconst nodeBuiltins = [\n\t\t'assert',\n\t\t'buffer',\n\t\t'child_process',\n\t\t'cluster',\n\t\t'crypto',\n\t\t'dgram',\n\t\t'dns',\n\t\t'events',\n\t\t'fs',\n\t\t'http',\n\t\t'http2',\n\t\t'https',\n\t\t'net',\n\t\t'os',\n\t\t'path',\n\t\t'perf_hooks',\n\t\t'process',\n\t\t'querystring',\n\t\t'readline',\n\t\t'stream',\n\t\t'string_decoder',\n\t\t'timers',\n\t\t'tls',\n\t\t'tty',\n\t\t'url',\n\t\t'util',\n\t\t'v8',\n\t\t'vm',\n\t\t'zlib',\n\t\t// Node: prefix versions\n\t\t'node:assert',\n\t\t'node:buffer',\n\t\t'node:child_process',\n\t\t'node:cluster',\n\t\t'node:crypto',\n\t\t'node:dgram',\n\t\t'node:dns',\n\t\t'node:events',\n\t\t'node:fs',\n\t\t'node:http',\n\t\t'node:http2',\n\t\t'node:https',\n\t\t'node:net',\n\t\t'node:os',\n\t\t'node:path',\n\t\t'node:perf_hooks',\n\t\t'node:process',\n\t\t'node:querystring',\n\t\t'node:readline',\n\t\t'node:stream',\n\t\t'node:string_decoder',\n\t\t'node:timers',\n\t\t'node:tls',\n\t\t'node:tty',\n\t\t'node:url',\n\t\t'node:util',\n\t\t'node:v8',\n\t\t'node:vm',\n\t\t'node:zlib',\n\t]\n\n\t// Bundle with esbuild\n\tconst result = await build({\n\t\tentryPoints: [taskPath],\n\t\tbundle: true,\n\t\tformat: 'esm',\n\t\tplatform: 'neutral',\n\t\ttarget: 'esnext',\n\t\twrite: false,\n\t\ttreeShaking: true,\n\t\tminify: false, // Keep readable for debugging\n\t\tsourcemap: false,\n\t\texternal: nodeBuiltins, // Don't bundle Node.js built-ins\n\t\tlogLevel: 'silent',\n\t})\n\n\tif (result.outputFiles.length === 0) {\n\t\tthrow new Error('No output from bundler')\n\t}\n\n\tconst outputFile = result.outputFiles[0]\n\tif (!outputFile) {\n\t\tthrow new Error('No output from bundler')\n\t}\n\n\tconst bundle = outputFile.text\n\n\treturn {\n\t\tsource,\n\t\tbundle,\n\t}\n}\n","import { compressTask as sdkCompressTask } from '@thyme-sh/sdk'\n\nexport interface CompressResult {\n\tzipBuffer: Buffer\n\tchecksum: string\n}\n\n/**\n * Compress source and bundle into a ZIP archive\n * Uses SDK's compression function with fflate\n */\nexport function compressTask(source: string, bundle: string): CompressResult {\n\tconst { zipBuffer, checksum } = sdkCompressTask(source, bundle)\n\n\t// Convert Uint8Array to Buffer for Node.js\n\treturn {\n\t\tzipBuffer: Buffer.from(zipBuffer),\n\t\tchecksum,\n\t}\n}\n","/**\n * Extract Zod schema from task code and convert to JSON Schema\n * This allows the frontend to generate forms for task arguments\n */\nexport function extractSchemaFromTask(taskCode: string): string | null {\n\ttry {\n\t\t// For now, return a simple extraction by parsing the code\n\t\t// This is a simplified version - in production you might want to use a proper parser\n\t\tconst schemaMatch = taskCode.match(/schema:\\s*z\\.object\\(\\{([^}]+)\\}\\)/)\n\n\t\tif (!schemaMatch || !schemaMatch[1]) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Parse the schema fields\n\t\tconst schemaContent = schemaMatch[1]\n\t\tconst fields: Record<string, unknown> = {}\n\n\t\t// Simple regex to extract field definitions\n\t\tconst fieldMatches = schemaContent.matchAll(/(\\w+):\\s*z\\.(\\w+)\\(\\)/g)\n\n\t\tfor (const match of fieldMatches) {\n\t\t\tconst [, fieldName, fieldType] = match\n\t\t\tif (fieldName && fieldType) {\n\t\t\t\t// Convert Zod types to JSON Schema types\n\t\t\t\tlet jsonType = 'string'\n\t\t\t\tswitch (fieldType) {\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tjsonType = 'number'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\tjsonType = 'boolean'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'address':\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tjsonType = 'string'\n\t\t\t\t}\n\n\t\t\t\tfields[fieldName] = {\n\t\t\t\t\ttype: jsonType,\n\t\t\t\t\t...(fieldType === 'address' && {\n\t\t\t\t\t\tpattern: '^0x[a-fA-F0-9]{40}$',\n\t\t\t\t\t\tdescription: 'Ethereum address',\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Object.keys(fields).length === 0) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst jsonSchema = {\n\t\t\ttype: 'object',\n\t\t\tproperties: fields,\n\t\t\trequired: Object.keys(fields),\n\t\t}\n\n\t\treturn JSON.stringify(jsonSchema)\n\t} catch (err) {\n\t\tconsole.error('Error extracting schema:', err)\n\t\treturn null\n\t}\n}\n"],"mappings":"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","names":["intro","outro","log","intro","outro","existsSync","join","intro","outro","existsSync","writeFile","join","existsSync","join","intro","join","existsSync","writeFile","outro","existsSync","mkdir","writeFile","join","intro","join","existsSync","mkdir","writeFile","outro","existsSync","readFile","config","resolve","error","intro","existsSync","config","readFile","log","outro","existsSync","readFile","intro","existsSync","outro"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thyme-sh/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI for developing and deploying Thyme tasks",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/bnhpio/thyme-sdk.git",
|
|
8
|
+
"directory": "packages/cli"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
12
|
"thyme": "./dist/index.js"
|
|
@@ -22,9 +27,13 @@
|
|
|
22
27
|
],
|
|
23
28
|
"author": "",
|
|
24
29
|
"license": "MIT",
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"provenance": true
|
|
33
|
+
},
|
|
25
34
|
"dependencies": {
|
|
26
35
|
"@clack/prompts": "^0.8.2",
|
|
27
|
-
"@thyme-sh/sdk": "^0.
|
|
36
|
+
"@thyme-sh/sdk": "^0.3.0",
|
|
28
37
|
"commander": "^12.1.0",
|
|
29
38
|
"dotenv": "^16.4.7",
|
|
30
39
|
"esbuild": "^0.24.2",
|