@thyme-sh/cli 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
2
8
 
3
9
  // src/index.ts
10
+ import { readFileSync } from "fs";
11
+ import { dirname as dirname2, join as join6 } from "path";
12
+ import { fileURLToPath } from "url";
4
13
  import { Command } from "commander";
5
14
 
6
15
  // src/commands/init.ts
@@ -176,7 +185,31 @@ Next steps:
176
185
  // src/utils/tasks.ts
177
186
  import { existsSync as existsSync2 } from "fs";
178
187
  import { readdir } from "fs/promises";
179
- import { join as join2 } from "path";
188
+ import { join as join2, resolve } from "path";
189
+ var VALID_TASK_NAME_PATTERN = /^[a-z0-9-]+$/;
190
+ var MAX_TASK_NAME_LENGTH = 64;
191
+ function validateTaskName(taskName) {
192
+ if (!taskName) {
193
+ throw new Error("Task name is required");
194
+ }
195
+ if (taskName.length > MAX_TASK_NAME_LENGTH) {
196
+ throw new Error(
197
+ `Task name too long: ${taskName.length} characters (max: ${MAX_TASK_NAME_LENGTH})`
198
+ );
199
+ }
200
+ if (taskName.includes("..") || taskName.includes("/") || taskName.includes("\\")) {
201
+ throw new Error("Invalid task name: path traversal characters not allowed");
202
+ }
203
+ if (!VALID_TASK_NAME_PATTERN.test(taskName)) {
204
+ throw new Error(
205
+ "Task name must be lowercase alphanumeric with hyphens only"
206
+ );
207
+ }
208
+ const reservedNames = ["node_modules", "dist", "build", "src", "lib"];
209
+ if (reservedNames.includes(taskName)) {
210
+ throw new Error(`Task name "${taskName}" is reserved`);
211
+ }
212
+ }
180
213
  async function discoverTasks(projectRoot) {
181
214
  const functionsDir = join2(projectRoot, "functions");
182
215
  if (!existsSync2(functionsDir)) {
@@ -184,20 +217,56 @@ async function discoverTasks(projectRoot) {
184
217
  }
185
218
  try {
186
219
  const entries = await readdir(functionsDir, { withFileTypes: true });
187
- return entries.filter((e) => e.isDirectory()).filter((e) => existsSync2(join2(functionsDir, e.name, "index.ts"))).map((e) => e.name);
220
+ return entries.filter((e) => e.isDirectory()).filter((e) => {
221
+ try {
222
+ validateTaskName(e.name);
223
+ return existsSync2(join2(functionsDir, e.name, "index.ts"));
224
+ } catch {
225
+ return false;
226
+ }
227
+ }).map((e) => e.name);
188
228
  } catch {
189
229
  return [];
190
230
  }
191
231
  }
192
232
  function getTaskPath(projectRoot, taskName) {
193
- return join2(projectRoot, "functions", taskName, "index.ts");
233
+ validateTaskName(taskName);
234
+ const functionsDir = resolve(projectRoot, "functions");
235
+ const taskPath = resolve(functionsDir, taskName, "index.ts");
236
+ if (!taskPath.startsWith(functionsDir)) {
237
+ throw new Error("Invalid task path: path traversal detected");
238
+ }
239
+ return taskPath;
194
240
  }
195
241
  function getTaskArgsPath(projectRoot, taskName) {
196
- return join2(projectRoot, "functions", taskName, "args.json");
242
+ validateTaskName(taskName);
243
+ const functionsDir = resolve(projectRoot, "functions");
244
+ const argsPath = resolve(functionsDir, taskName, "args.json");
245
+ if (!argsPath.startsWith(functionsDir)) {
246
+ throw new Error("Invalid task path: path traversal detected");
247
+ }
248
+ return argsPath;
197
249
  }
198
250
  function isThymeProject(projectRoot) {
199
251
  const functionsDir = join2(projectRoot, "functions");
200
- return existsSync2(functionsDir);
252
+ const packageJsonPath = join2(projectRoot, "package.json");
253
+ if (!existsSync2(functionsDir)) {
254
+ return false;
255
+ }
256
+ if (existsSync2(packageJsonPath)) {
257
+ try {
258
+ const fs = __require("fs");
259
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
260
+ const deps = {
261
+ ...packageJson.dependencies,
262
+ ...packageJson.devDependencies
263
+ };
264
+ return "@thyme-sh/sdk" in deps || "@thyme-sh/cli" in deps;
265
+ } catch {
266
+ return true;
267
+ }
268
+ }
269
+ return true;
201
270
  }
202
271
 
203
272
  // src/commands/list.ts
@@ -224,6 +293,7 @@ async function listCommand() {
224
293
  import { existsSync as existsSync4 } from "fs";
225
294
  import { appendFile, readFile, writeFile as writeFile2 } from "fs/promises";
226
295
  import { join as join4 } from "path";
296
+ import { z } from "zod";
227
297
 
228
298
  // src/utils/env.ts
229
299
  import { existsSync as existsSync3 } from "fs";
@@ -240,6 +310,20 @@ function getEnv(key, fallback) {
240
310
  }
241
311
 
242
312
  // src/commands/login.ts
313
+ var verifyResponseSchema = z.object({
314
+ user: z.object({
315
+ id: z.string(),
316
+ name: z.string().optional().default(""),
317
+ email: z.string()
318
+ }),
319
+ organizations: z.array(
320
+ z.object({
321
+ id: z.string(),
322
+ name: z.string(),
323
+ role: z.string()
324
+ })
325
+ ).optional().default([])
326
+ });
243
327
  async function loginCommand() {
244
328
  intro2("Thyme CLI - Login");
245
329
  const projectRoot = process.cwd();
@@ -286,7 +370,14 @@ async function loginCommand() {
286
370
  error(`Invalid token: ${errorText}`);
287
371
  process.exit(1);
288
372
  }
289
- const verifyData = await verifyResponse.json();
373
+ const rawData = await verifyResponse.json();
374
+ const parseResult = verifyResponseSchema.safeParse(rawData);
375
+ if (!parseResult.success) {
376
+ spinner.stop("Invalid API response");
377
+ error(`API returned unexpected data format: ${parseResult.error.message}`);
378
+ process.exit(1);
379
+ }
380
+ const verifyData = parseResult.data;
290
381
  spinner.stop("Token verified!");
291
382
  const saveSpinner = clack.spinner();
292
383
  saveSpinner.start("Saving token...");
@@ -338,14 +429,23 @@ async function newCommand(taskName) {
338
429
  process.exit(1);
339
430
  }
340
431
  let finalTaskName = taskName;
341
- if (!finalTaskName) {
432
+ if (finalTaskName) {
433
+ try {
434
+ validateTaskName(finalTaskName);
435
+ } catch (err) {
436
+ error(err instanceof Error ? err.message : String(err));
437
+ process.exit(1);
438
+ }
439
+ } else {
342
440
  const name = await clack.text({
343
441
  message: "What is your task name?",
344
442
  placeholder: "my-task",
345
443
  validate: (value) => {
346
- if (!value) return "Task name is required";
347
- if (!/^[a-z0-9-]+$/.test(value))
348
- return "Task name must be lowercase alphanumeric with hyphens";
444
+ try {
445
+ validateTaskName(value);
446
+ } catch (err) {
447
+ return err instanceof Error ? err.message : String(err);
448
+ }
349
449
  }
350
450
  });
351
451
  if (clack.isCancel(name)) {
@@ -373,13 +473,19 @@ export default defineTask({
373
473
 
374
474
  async run(ctx) {
375
475
  const { targetAddress } = ctx.args
476
+ const { logger } = ctx
376
477
 
377
- // Your task logic here
378
- console.log('Running task with address:', targetAddress)
478
+ // Use the logger to output messages to the Thyme dashboard
479
+ logger.info('Starting task execution')
480
+ logger.info(\`Processing address: \${targetAddress}\`)
379
481
 
380
482
  // Example: Read from blockchain using the public client
381
483
  // const balance = await ctx.client.getBalance({ address: targetAddress })
484
+ // logger.info(\`Balance: \${balance}\`)
485
+ //
382
486
  // const blockNumber = await ctx.client.getBlockNumber()
487
+ // logger.info(\`Current block: \${blockNumber}\`)
488
+ //
383
489
  // const value = await ctx.client.readContract({
384
490
  // address: targetAddress,
385
491
  // abi: [...],
@@ -387,7 +493,12 @@ export default defineTask({
387
493
  // args: [someAddress],
388
494
  // })
389
495
 
496
+ // Example: Log warnings and errors
497
+ // logger.warn('Low balance detected')
498
+ // logger.error('Failed to fetch data')
499
+
390
500
  // Example: Return calls to execute
501
+ logger.info('Task completed successfully')
391
502
  return {
392
503
  canExec: true,
393
504
  calls: [
@@ -450,10 +561,33 @@ import { createPublicClient, formatEther, http, isAddress } from "viem";
450
561
 
451
562
  // src/deno/runner.ts
452
563
  import { spawn } from "child_process";
453
- import { dirname, resolve } from "path";
564
+ import { dirname, resolve as resolve2 } from "path";
565
+ function escapeJsString(str) {
566
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\0/g, "\\0");
567
+ }
568
+ function sanitizeArgs(args) {
569
+ if (args === null || args === void 0) return args;
570
+ if (typeof args !== "object") return args;
571
+ try {
572
+ return JSON.parse(JSON.stringify(args));
573
+ } catch {
574
+ return {};
575
+ }
576
+ }
577
+ function sanitizeErrorMessage(error2) {
578
+ let sanitized = error2.replace(/\/[^\s:]+\//g, ".../");
579
+ sanitized = sanitized.replace(/\s+at\s+.+/g, "");
580
+ if (sanitized.length > 500) {
581
+ sanitized = `${sanitized.substring(0, 500)}...`;
582
+ }
583
+ return sanitized.trim();
584
+ }
454
585
  async function runInDeno(taskPath, args, config2) {
455
- const taskDir = dirname(resolve(taskPath));
456
- const absoluteTaskPath = resolve(taskPath);
586
+ const taskDir = dirname(resolve2(taskPath));
587
+ const absoluteTaskPath = resolve2(taskPath);
588
+ const safeTaskPath = escapeJsString(absoluteTaskPath);
589
+ const safeArgs = sanitizeArgs(args);
590
+ const safeRpcUrl = config2.rpcUrl ? JSON.stringify(config2.rpcUrl) : "undefined";
457
591
  const denoFlags = ["run", "--no-prompt"];
458
592
  denoFlags.push(`--allow-read=${taskDir}`);
459
593
  if (config2.memory) {
@@ -464,9 +598,25 @@ async function runInDeno(taskPath, args, config2) {
464
598
  }
465
599
  denoFlags.push("-");
466
600
  const execScript = `
467
- import task from '${absoluteTaskPath}';
601
+ import task from '${safeTaskPath}';
468
602
  import { createPublicClient, http } from 'npm:viem@2.21.54';
469
603
 
604
+ // Logger for local development - prints directly to console
605
+ // (In production, the logger outputs with __THYME_LOG__ prefix for capture)
606
+ class Logger {
607
+ info(message) {
608
+ console.log('[INFO]', message);
609
+ }
610
+
611
+ warn(message) {
612
+ console.log('[WARN]', message);
613
+ }
614
+
615
+ error(message) {
616
+ console.log('[ERROR]', message);
617
+ }
618
+ }
619
+
470
620
  // Create RPC request counter
471
621
  let rpcRequestCount = 0;
472
622
 
@@ -487,12 +637,13 @@ const countingHttp = (url) => {
487
637
 
488
638
  // Create public client for blockchain reads
489
639
  const client = createPublicClient({
490
- transport: countingHttp(${config2.rpcUrl ? `'${config2.rpcUrl}'` : "undefined"}),
640
+ transport: countingHttp(${safeRpcUrl}),
491
641
  });
492
642
 
493
643
  const context = {
494
- args: ${JSON.stringify(args)},
644
+ args: ${JSON.stringify(safeArgs)},
495
645
  client,
646
+ logger: new Logger(),
496
647
  };
497
648
 
498
649
  try {
@@ -506,7 +657,8 @@ try {
506
657
  const endMemory = Deno.memoryUsage().heapUsed;
507
658
 
508
659
  const executionTime = endTime - startTime;
509
- const memoryUsed = endMemory - startMemory;
660
+ // Ensure memory measurement is non-negative (GC can cause negative values)
661
+ const memoryUsed = Math.max(0, endMemory - startMemory);
510
662
 
511
663
  console.log('__THYME_RESULT__' + JSON.stringify(result));
512
664
  console.log('__THYME_STATS__' + JSON.stringify({ executionTime, memoryUsed, rpcRequestCount }));
@@ -515,10 +667,9 @@ try {
515
667
  Deno.exit(1);
516
668
  }
517
669
  `;
518
- return new Promise((resolve2) => {
670
+ return new Promise((resolve3) => {
519
671
  const proc = spawn("deno", denoFlags, {
520
672
  stdio: ["pipe", "pipe", "pipe"],
521
- timeout: config2.timeout * 1e3,
522
673
  cwd: taskDir
523
674
  });
524
675
  let stdout = "";
@@ -534,10 +685,12 @@ try {
534
685
  });
535
686
  proc.on("close", (code) => {
536
687
  if (code !== 0) {
537
- resolve2({
688
+ resolve3({
538
689
  success: false,
539
690
  logs,
540
- error: stderr || `Process exited with code ${code}`
691
+ error: sanitizeErrorMessage(
692
+ stderr || `Process exited with code ${code}`
693
+ )
541
694
  });
542
695
  return;
543
696
  }
@@ -563,7 +716,7 @@ try {
563
716
  memoryUsed: void 0,
564
717
  rpcRequestCount: void 0
565
718
  };
566
- resolve2({
719
+ resolve3({
567
720
  success: true,
568
721
  result,
569
722
  logs,
@@ -572,27 +725,29 @@ try {
572
725
  rpcRequestCount: stats.rpcRequestCount
573
726
  });
574
727
  } catch (error2) {
575
- resolve2({
728
+ resolve3({
576
729
  success: false,
577
730
  logs,
578
- error: `Failed to parse result: ${error2 instanceof Error ? error2.message : String(error2)}`
731
+ error: sanitizeErrorMessage(
732
+ `Failed to parse result: ${error2 instanceof Error ? error2.message : String(error2)}`
733
+ )
579
734
  });
580
735
  }
581
736
  });
582
737
  proc.on("error", (error2) => {
583
- resolve2({
738
+ resolve3({
584
739
  success: false,
585
740
  logs,
586
- error: `Failed to spawn Deno: ${error2.message}`
741
+ error: sanitizeErrorMessage(`Failed to spawn Deno: ${error2.message}`)
587
742
  });
588
743
  });
589
744
  });
590
745
  }
591
746
  async function checkDeno() {
592
- return new Promise((resolve2) => {
747
+ return new Promise((resolve3) => {
593
748
  const proc = spawn("deno", ["--version"], { stdio: "ignore" });
594
- proc.on("close", (code) => resolve2(code === 0));
595
- proc.on("error", () => resolve2(false));
749
+ proc.on("close", (code) => resolve3(code === 0));
750
+ proc.on("error", () => resolve3(false));
596
751
  });
597
752
  }
598
753
 
@@ -611,7 +766,14 @@ async function runCommand(taskName, options = {}) {
611
766
  process.exit(1);
612
767
  }
613
768
  let finalTaskName = taskName;
614
- if (!finalTaskName) {
769
+ if (finalTaskName) {
770
+ try {
771
+ validateTaskName(finalTaskName);
772
+ } catch (err) {
773
+ error(err instanceof Error ? err.message : String(err));
774
+ process.exit(1);
775
+ }
776
+ } else {
615
777
  const tasks = await discoverTasks(projectRoot);
616
778
  if (tasks.length === 0) {
617
779
  error("No tasks found. Create one with `thyme new`");
@@ -627,8 +789,15 @@ async function runCommand(taskName, options = {}) {
627
789
  }
628
790
  finalTaskName = selected;
629
791
  }
630
- const taskPath = getTaskPath(projectRoot, finalTaskName);
631
- const argsPath = getTaskArgsPath(projectRoot, finalTaskName);
792
+ let taskPath;
793
+ let argsPath;
794
+ try {
795
+ taskPath = getTaskPath(projectRoot, finalTaskName);
796
+ argsPath = getTaskArgsPath(projectRoot, finalTaskName);
797
+ } catch (err) {
798
+ error(err instanceof Error ? err.message : String(err));
799
+ process.exit(1);
800
+ }
632
801
  if (!existsSync6(taskPath)) {
633
802
  error(`Task "${finalTaskName}" not found`);
634
803
  process.exit(1);
@@ -795,6 +964,7 @@ async function simulateCalls(calls) {
795
964
 
796
965
  // src/commands/upload.ts
797
966
  import { existsSync as existsSync7 } from "fs";
967
+ import { z as z2 } from "zod";
798
968
 
799
969
  // src/utils/bundler.ts
800
970
  import { readFile as readFile3 } from "fs/promises";
@@ -956,6 +1126,22 @@ function extractSchemaFromTask(taskCode) {
956
1126
  }
957
1127
 
958
1128
  // src/commands/upload.ts
1129
+ var organizationSchema = z2.object({
1130
+ id: z2.string(),
1131
+ name: z2.string(),
1132
+ role: z2.string()
1133
+ });
1134
+ var verifyResponseSchema2 = z2.object({
1135
+ user: z2.object({
1136
+ id: z2.string(),
1137
+ name: z2.string().optional().default(""),
1138
+ email: z2.string()
1139
+ }),
1140
+ organizations: z2.array(organizationSchema).optional().default([])
1141
+ });
1142
+ var uploadResponseSchema = z2.object({
1143
+ taskId: z2.string().optional()
1144
+ });
959
1145
  async function uploadCommand(taskName, organizationId) {
960
1146
  intro2("Thyme CLI - Upload Task");
961
1147
  const projectRoot = process.cwd();
@@ -977,7 +1163,14 @@ async function uploadCommand(taskName, organizationId) {
977
1163
  process.exit(1);
978
1164
  }
979
1165
  let finalTaskName = taskName;
980
- if (!finalTaskName) {
1166
+ if (finalTaskName) {
1167
+ try {
1168
+ validateTaskName(finalTaskName);
1169
+ } catch (err) {
1170
+ error(err instanceof Error ? err.message : String(err));
1171
+ process.exit(1);
1172
+ }
1173
+ } else {
981
1174
  const tasks = await discoverTasks(projectRoot);
982
1175
  if (tasks.length === 0) {
983
1176
  error("No tasks found. Create one with `thyme new`");
@@ -1008,8 +1201,14 @@ async function uploadCommand(taskName, organizationId) {
1008
1201
  error("Failed to authenticate. Please run `thyme login` again.");
1009
1202
  process.exit(1);
1010
1203
  }
1011
- const verifyData = await verifyResponse.json();
1012
- organizations = verifyData.organizations || [];
1204
+ const rawData = await verifyResponse.json();
1205
+ const parseResult = verifyResponseSchema2.safeParse(rawData);
1206
+ if (!parseResult.success) {
1207
+ orgSpinner.stop("Invalid API response");
1208
+ error(`API returned unexpected data format: ${parseResult.error.message}`);
1209
+ process.exit(1);
1210
+ }
1211
+ organizations = parseResult.data.organizations;
1013
1212
  orgSpinner.stop("Organizations loaded");
1014
1213
  } catch (err) {
1015
1214
  orgSpinner.stop("Failed to fetch organizations");
@@ -1045,7 +1244,13 @@ async function uploadCommand(taskName, organizationId) {
1045
1244
  }
1046
1245
  selectedOrgId = selected;
1047
1246
  }
1048
- const taskPath = getTaskPath(projectRoot, finalTaskName);
1247
+ let taskPath;
1248
+ try {
1249
+ taskPath = getTaskPath(projectRoot, finalTaskName);
1250
+ } catch (err) {
1251
+ error(err instanceof Error ? err.message : String(err));
1252
+ process.exit(1);
1253
+ }
1049
1254
  if (!existsSync7(taskPath)) {
1050
1255
  error(`Task "${finalTaskName}" not found`);
1051
1256
  process.exit(1);
@@ -1080,7 +1285,14 @@ async function uploadCommand(taskName, organizationId) {
1080
1285
  const errorText = await response.text();
1081
1286
  throw new Error(`Upload failed: ${errorText}`);
1082
1287
  }
1083
- const result = await response.json();
1288
+ const rawResult = await response.json();
1289
+ const resultParseResult = uploadResponseSchema.safeParse(rawResult);
1290
+ if (!resultParseResult.success) {
1291
+ throw new Error(
1292
+ `Invalid upload response: ${resultParseResult.error.message}`
1293
+ );
1294
+ }
1295
+ const result = resultParseResult.data;
1084
1296
  spinner.stop("Task uploaded successfully!");
1085
1297
  const selectedOrg = organizations.find((org) => org.id === selectedOrgId);
1086
1298
  clack.log.message("");
@@ -1109,8 +1321,24 @@ Configure triggers in the dashboard: ${pc.cyan("https://thyme.sh/dashboard")}`
1109
1321
  }
1110
1322
 
1111
1323
  // src/index.ts
1324
+ var __dirname2 = dirname2(fileURLToPath(import.meta.url));
1325
+ var version = "0.0.0";
1326
+ try {
1327
+ const packageJson = JSON.parse(
1328
+ readFileSync(join6(__dirname2, "../package.json"), "utf-8")
1329
+ );
1330
+ version = packageJson.version || version;
1331
+ } catch {
1332
+ try {
1333
+ const packageJson = JSON.parse(
1334
+ readFileSync(join6(__dirname2, "../../package.json"), "utf-8")
1335
+ );
1336
+ version = packageJson.version || version;
1337
+ } catch {
1338
+ }
1339
+ }
1112
1340
  var program = new Command();
1113
- program.name("thyme").description("CLI for developing and deploying Thyme tasks").version("0.1.0");
1341
+ program.name("thyme").description("CLI for developing and deploying Thyme tasks").version(version);
1114
1342
  program.command("init").description("Initialize a new Thyme project").argument("[name]", "Project name").action(initCommand);
1115
1343
  program.command("new").description("Create a new task").argument("[name]", "Task name").action(newCommand);
1116
1344
  program.command("run").description("Run a task locally").argument("[task]", "Task name").option("--simulate", "Simulate on-chain execution").action((task, options) => runCommand(task, options));
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 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"]}
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 { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { 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\n// Read version from package.json dynamically\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nlet version = '0.0.0'\ntry {\n\tconst packageJson = JSON.parse(\n\t\treadFileSync(join(__dirname, '../package.json'), 'utf-8'),\n\t)\n\tversion = packageJson.version || version\n} catch {\n\t// Fallback if package.json can't be read (e.g., in bundled builds)\n\t// Try one more level up for bundled scenarios\n\ttry {\n\t\tconst packageJson = JSON.parse(\n\t\t\treadFileSync(join(__dirname, '../../package.json'), 'utf-8'),\n\t\t)\n\t\tversion = packageJson.version || version\n\t} catch {\n\t\t// Use default version\n\t}\n}\n\nconst program = new Command()\n\nprogram\n\t.name('thyme')\n\t.description('CLI for developing and deploying Thyme tasks')\n\t.version(version)\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, resolve } from 'node:path'\n\n/**\n * Regex pattern for valid task names\n * Only lowercase alphanumeric characters and hyphens allowed\n */\nconst VALID_TASK_NAME_PATTERN = /^[a-z0-9-]+$/\n\n/**\n * Maximum length for task names\n */\nconst MAX_TASK_NAME_LENGTH = 64\n\n/**\n * Validate a task name for security and consistency\n * Prevents path traversal and ensures valid naming conventions\n *\n * @throws Error if task name is invalid\n */\nexport function validateTaskName(taskName: string): void {\n\tif (!taskName) {\n\t\tthrow new Error('Task name is required')\n\t}\n\n\tif (taskName.length > MAX_TASK_NAME_LENGTH) {\n\t\tthrow new Error(\n\t\t\t`Task name too long: ${taskName.length} characters (max: ${MAX_TASK_NAME_LENGTH})`,\n\t\t)\n\t}\n\n\t// Check for path traversal attempts\n\tif (\n\t\ttaskName.includes('..') ||\n\t\ttaskName.includes('/') ||\n\t\ttaskName.includes('\\\\')\n\t) {\n\t\tthrow new Error('Invalid task name: path traversal characters not allowed')\n\t}\n\n\t// Check for valid characters\n\tif (!VALID_TASK_NAME_PATTERN.test(taskName)) {\n\t\tthrow new Error(\n\t\t\t'Task name must be lowercase alphanumeric with hyphens only',\n\t\t)\n\t}\n\n\t// Check for reserved names\n\tconst reservedNames = ['node_modules', 'dist', 'build', 'src', 'lib']\n\tif (reservedNames.includes(taskName)) {\n\t\tthrow new Error(`Task name \"${taskName}\" is reserved`)\n\t}\n}\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) => {\n\t\t\t\t// Validate task name format\n\t\t\t\ttry {\n\t\t\t\t\tvalidateTaskName(e.name)\n\t\t\t\t\treturn existsSync(join(functionsDir, e.name, 'index.ts'))\n\t\t\t\t} catch {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t})\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 * Includes path traversal protection\n *\n * @throws Error if task name is invalid or path escapes functions directory\n */\nexport function getTaskPath(projectRoot: string, taskName: string): string {\n\t// Validate task name first\n\tvalidateTaskName(taskName)\n\n\tconst functionsDir = resolve(projectRoot, 'functions')\n\tconst taskPath = resolve(functionsDir, taskName, 'index.ts')\n\n\t// Ensure the resolved path is within the functions directory\n\tif (!taskPath.startsWith(functionsDir)) {\n\t\tthrow new Error('Invalid task path: path traversal detected')\n\t}\n\n\treturn taskPath\n}\n\n/**\n * Get the path to a task's args file\n * Includes path traversal protection\n *\n * @throws Error if task name is invalid or path escapes functions directory\n */\nexport function getTaskArgsPath(projectRoot: string, taskName: string): string {\n\t// Validate task name first\n\tvalidateTaskName(taskName)\n\n\tconst functionsDir = resolve(projectRoot, 'functions')\n\tconst argsPath = resolve(functionsDir, taskName, 'args.json')\n\n\t// Ensure the resolved path is within the functions directory\n\tif (!argsPath.startsWith(functionsDir)) {\n\t\tthrow new Error('Invalid task path: path traversal detected')\n\t}\n\n\treturn argsPath\n}\n\n/**\n * Check if we're in a Thyme project\n * Validates by checking for functions directory AND package.json with @thyme-sh/sdk\n */\nexport function isThymeProject(projectRoot: string): boolean {\n\tconst functionsDir = join(projectRoot, 'functions')\n\tconst packageJsonPath = join(projectRoot, 'package.json')\n\n\t// Must have functions directory\n\tif (!existsSync(functionsDir)) {\n\t\treturn false\n\t}\n\n\t// Check for package.json with thyme SDK dependency\n\tif (existsSync(packageJsonPath)) {\n\t\ttry {\n\t\t\t// Synchronous check for simplicity in this validation function\n\t\t\tconst fs = require('node:fs')\n\t\t\tconst packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n\t\t\tconst deps = {\n\t\t\t\t...packageJson.dependencies,\n\t\t\t\t...packageJson.devDependencies,\n\t\t\t}\n\t\t\treturn '@thyme-sh/sdk' in deps || '@thyme-sh/cli' in deps\n\t\t} catch {\n\t\t\t// If we can't read package.json, fall back to just checking functions dir\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn true\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 { z } from 'zod'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { clack, error, info, intro, outro, pc } from '../utils/ui'\n\n// Zod schema for API response validation\nconst verifyResponseSchema = z.object({\n\tuser: z.object({\n\t\tid: z.string(),\n\t\tname: z.string().optional().default(''),\n\t\temail: z.string(),\n\t}),\n\torganizations: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\tname: z.string(),\n\t\t\t\trole: z.string(),\n\t\t\t}),\n\t\t)\n\t\t.optional()\n\t\t.default([]),\n})\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 rawData = await verifyResponse.json()\n\n\t\t// Validate response with Zod\n\t\tconst parseResult = verifyResponseSchema.safeParse(rawData)\n\t\tif (!parseResult.success) {\n\t\t\tspinner.stop('Invalid API response')\n\t\t\terror(`API returned unexpected data format: ${parseResult.error.message}`)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\tconst verifyData = parseResult.data\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, validateTaskName } 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\n\t// Validate task name if provided via CLI argument\n\tif (finalTaskName) {\n\t\ttry {\n\t\t\tvalidateTaskName(finalTaskName)\n\t\t} catch (err) {\n\t\t\terror(err instanceof Error ? err.message : String(err))\n\t\t\tprocess.exit(1)\n\t\t}\n\t} else {\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\ttry {\n\t\t\t\t\tvalidateTaskName(value)\n\t\t\t\t} catch (err) {\n\t\t\t\t\treturn err instanceof Error ? err.message : String(err)\n\t\t\t\t}\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\t\tconst { logger } = ctx\n\n\t\t// Use the logger to output messages to the Thyme dashboard\n\t\tlogger.info('Starting task execution')\n\t\tlogger.info(\\`Processing 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// logger.info(\\`Balance: \\${balance}\\`)\n\t\t//\n\t\t// const blockNumber = await ctx.client.getBlockNumber()\n\t\t// logger.info(\\`Current block: \\${blockNumber}\\`)\n\t\t//\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: Log warnings and errors\n\t\t// logger.warn('Low balance detected')\n\t\t// logger.error('Failed to fetch data')\n\n\t\t// Example: Return calls to execute\n\t\tlogger.info('Task completed successfully')\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\tvalidateTaskName,\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\n\t// Validate task name if provided via CLI argument\n\tif (finalTaskName) {\n\t\ttry {\n\t\t\tvalidateTaskName(finalTaskName)\n\t\t} catch (err) {\n\t\t\terror(err instanceof Error ? err.message : String(err))\n\t\t\tprocess.exit(1)\n\t\t}\n\t} else {\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\tlet taskPath: string\n\tlet argsPath: string\n\ttry {\n\t\ttaskPath = getTaskPath(projectRoot, finalTaskName)\n\t\targsPath = getTaskArgsPath(projectRoot, finalTaskName)\n\t} catch (err) {\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\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 * Escape a string for safe use in JavaScript string literals\n * Prevents command injection attacks\n */\nfunction escapeJsString(str: string): string {\n\treturn str\n\t\t.replace(/\\\\/g, '\\\\\\\\')\n\t\t.replace(/'/g, \"\\\\'\")\n\t\t.replace(/\"/g, '\\\\\"')\n\t\t.replace(/\\n/g, '\\\\n')\n\t\t.replace(/\\r/g, '\\\\r')\n\t\t.replace(/\\t/g, '\\\\t')\n\t\t.replace(/\\0/g, '\\\\0')\n}\n\n/**\n * Sanitize args to prevent prototype pollution and injection\n * Deep clones the object to remove any prototype chain issues\n */\nfunction sanitizeArgs(args: unknown): unknown {\n\tif (args === null || args === undefined) return args\n\tif (typeof args !== 'object') return args\n\n\t// Deep clone via JSON to strip prototypes and non-serializable values\n\ttry {\n\t\treturn JSON.parse(JSON.stringify(args))\n\t} catch {\n\t\treturn {}\n\t}\n}\n\n/**\n * Sanitize error messages to prevent information disclosure\n * Removes sensitive paths and internal details\n */\nfunction sanitizeErrorMessage(error: string): string {\n\t// Remove absolute paths (keep only filename)\n\tlet sanitized = error.replace(/\\/[^\\s:]+\\//g, '.../')\n\n\t// Remove stack traces\n\tsanitized = sanitized.replace(/\\s+at\\s+.+/g, '')\n\n\t// Limit length\n\tif (sanitized.length > 500) {\n\t\tsanitized = `${sanitized.substring(0, 500)}...`\n\t}\n\n\treturn sanitized.trim()\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\t// Escape path for safe JavaScript string interpolation\n\tconst safeTaskPath = escapeJsString(absoluteTaskPath)\n\n\t// Sanitize args to prevent prototype pollution\n\tconst safeArgs = sanitizeArgs(args)\n\n\t// Safely serialize RPC URL\n\tconst safeRpcUrl = config.rpcUrl ? JSON.stringify(config.rpcUrl) : 'undefined'\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 '${safeTaskPath}';\nimport { createPublicClient, http } from 'npm:viem@2.21.54';\n\n// Logger for local development - prints directly to console\n// (In production, the logger outputs with __THYME_LOG__ prefix for capture)\nclass Logger {\n\tinfo(message) {\n\t\tconsole.log('[INFO]', message);\n\t}\n\t\n\twarn(message) {\n\t\tconsole.log('[WARN]', message);\n\t}\n\t\n\terror(message) {\n\t\tconsole.log('[ERROR]', message);\n\t}\n}\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(${safeRpcUrl}),\n});\n\nconst context = {\n\targs: ${JSON.stringify(safeArgs)},\n\tclient,\n\tlogger: new Logger(),\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\t// Ensure memory measurement is non-negative (GC can cause negative values)\n\tconst memoryUsed = Math.max(0, 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\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: sanitizeErrorMessage(\n\t\t\t\t\t\tstderr || `Process exited with code ${code}`,\n\t\t\t\t\t),\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: sanitizeErrorMessage(\n\t\t\t\t\t\t`Failed to parse result: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t),\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: sanitizeErrorMessage(`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 { z } from 'zod'\nimport { bundleTask } from '../utils/bundler'\nimport { compressTask } from '../utils/compress'\nimport { getEnv, loadEnv } from '../utils/env'\nimport { extractSchemaFromTask } from '../utils/schema-extractor'\nimport {\n\tdiscoverTasks,\n\tgetTaskPath,\n\tisThymeProject,\n\tvalidateTaskName,\n} from '../utils/tasks'\nimport { clack, error, intro, outro, pc } from '../utils/ui'\n\n// Zod schemas for API response validation\nconst organizationSchema = z.object({\n\tid: z.string(),\n\tname: z.string(),\n\trole: z.string(),\n})\n\nconst verifyResponseSchema = z.object({\n\tuser: z.object({\n\t\tid: z.string(),\n\t\tname: z.string().optional().default(''),\n\t\temail: z.string(),\n\t}),\n\torganizations: z.array(organizationSchema).optional().default([]),\n})\n\nconst uploadResponseSchema = z.object({\n\ttaskId: z.string().optional(),\n})\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\n\t// Validate task name if provided via CLI argument\n\tif (finalTaskName) {\n\t\ttry {\n\t\t\tvalidateTaskName(finalTaskName)\n\t\t} catch (err) {\n\t\t\terror(err instanceof Error ? err.message : String(err))\n\t\t\tprocess.exit(1)\n\t\t}\n\t} else {\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: z.infer<typeof organizationSchema>[] = []\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 rawData = await verifyResponse.json()\n\n\t\t// Validate response with Zod\n\t\tconst parseResult = verifyResponseSchema.safeParse(rawData)\n\t\tif (!parseResult.success) {\n\t\t\torgSpinner.stop('Invalid API response')\n\t\t\terror(`API returned unexpected data format: ${parseResult.error.message}`)\n\t\t\tprocess.exit(1)\n\t\t}\n\n\t\torganizations = parseResult.data.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\tlet taskPath: string\n\ttry {\n\t\ttaskPath = getTaskPath(projectRoot, finalTaskName)\n\t} catch (err) {\n\t\terror(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t}\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 rawResult = await response.json()\n\n\t\t// Validate response with Zod\n\t\tconst resultParseResult = uploadResponseSchema.safeParse(rawResult)\n\t\tif (!resultParseResult.success) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid upload response: ${resultParseResult.error.message}`,\n\t\t\t)\n\t\t}\n\n\t\tconst result = resultParseResult.data\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":["dirname","join","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","resolve","error","config","intro","existsSync","config","readFile","log","outro","existsSync","z","readFile","z","verifyResponseSchema","intro","existsSync","outro","__dirname","dirname","join"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thyme-sh/cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "CLI for developing and deploying Thyme tasks",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@clack/prompts": "^0.8.2",
36
- "@thyme-sh/sdk": "^0.3.0",
36
+ "@thyme-sh/sdk": "^0.3.1",
37
37
  "commander": "^12.1.0",
38
38
  "dotenv": "^16.4.7",
39
39
  "esbuild": "^0.24.2",