runwork 0.18.4 → 0.19.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.
Files changed (2) hide show
  1. package/dist/index.js +473 -126
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -637,6 +637,35 @@ class ApiClient {
637
637
  const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`);
638
638
  return res.data;
639
639
  }
640
+ async createAppExport(workspaceId, appId, body) {
641
+ const res = await this.request(`/api/workspaces/${workspaceId}/apps/${appId}/exports`, { method: "POST", body: JSON.stringify(body) });
642
+ return res.data.job;
643
+ }
644
+ async getExportJob(workspaceId, exportId) {
645
+ const res = await this.request(`/api/workspaces/${workspaceId}/exports/${exportId}`);
646
+ return res.data.job;
647
+ }
648
+ async getExportManifest(workspaceId, exportId) {
649
+ const url = `${this.baseUrl}/api/workspaces/${workspaceId}/exports/${exportId}/manifest`;
650
+ const response = await httpFetch(url, {
651
+ headers: this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
652
+ });
653
+ if (!response.ok) {
654
+ throw new Error(`Failed to fetch export manifest: ${response.status} ${await response.text()}`);
655
+ }
656
+ return response.json();
657
+ }
658
+ async downloadExportChunk(workspaceId, exportId, file, chunkIndex) {
659
+ const query = `?file=${encodeURIComponent(file)}&fromChunk=${chunkIndex}&maxChunks=1`;
660
+ const url = `${this.baseUrl}/api/workspaces/${workspaceId}/exports/${exportId}/download${query}`;
661
+ const response = await httpFetch(url, {
662
+ headers: this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
663
+ });
664
+ if (!response.ok) {
665
+ throw new Error(`Failed to download export chunk ${chunkIndex}: ${response.status}`);
666
+ }
667
+ return response.arrayBuffer();
668
+ }
640
669
  async createEntityRecord(workspaceId, entityName, data) {
641
670
  const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}`, { method: "POST", body: JSON.stringify({ data }) });
642
671
  return res.data;
@@ -1058,10 +1087,21 @@ var init_credentials = __esm(() => {
1058
1087
  });
1059
1088
 
1060
1089
  // src/auth/login-flow.ts
1061
- async function performLogin(baseUrl) {
1090
+ function decorateLoginUrl(loginUrl, options) {
1091
+ const params = [];
1092
+ if (options?.register)
1093
+ params.push("mode=register");
1094
+ if (options?.provider)
1095
+ params.push(`provider=${encodeURIComponent(options.provider)}`);
1096
+ if (params.length === 0)
1097
+ return loginUrl;
1098
+ return `${loginUrl}${loginUrl.includes("?") ? "&" : "?"}${params.join("&")}`;
1099
+ }
1100
+ async function performLogin(baseUrl, options) {
1062
1101
  const url = baseUrl || DEFAULT_BASE_URL2;
1063
1102
  const client = new ApiClient({ apiKey: "", email: "", baseUrl: url });
1064
- const { sessionId, loginUrl } = await client.initiateLogin();
1103
+ const { sessionId, loginUrl: rawLoginUrl } = await client.initiateLogin();
1104
+ const loginUrl = decorateLoginUrl(rawLoginUrl, options);
1065
1105
  const open = await import("open");
1066
1106
  await open.default(loginUrl);
1067
1107
  console.log(`If browser didn't open, visit: ${loginUrl}`);
@@ -1136,7 +1176,7 @@ function extractBaseUrl(loginUrl) {
1136
1176
  }
1137
1177
  }
1138
1178
  async function pollAndSave(client, sessionId, baseUrl) {
1139
- const maxAttempts = 60;
1179
+ const maxAttempts = 360;
1140
1180
  const pollInterval = 5000;
1141
1181
  for (let i = 0;i < maxAttempts; i++) {
1142
1182
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
@@ -7583,7 +7623,7 @@ function createKeyboardListener() {
7583
7623
  }
7584
7624
 
7585
7625
  // src/generated/version.ts
7586
- var VERSION = "0.18.4";
7626
+ var VERSION = "0.19.1";
7587
7627
 
7588
7628
  // src/commands/dev.ts
7589
7629
  var exports_dev = {};
@@ -8574,7 +8614,7 @@ import { Command as Command36 } from "commander";
8574
8614
  init_login_flow();
8575
8615
  init_colors();
8576
8616
  import { Command } from "commander";
8577
- var loginCommand = new Command("login").description("Authenticate with Runwork platform").argument("[url]", "Login URL from a previous --no-open session").option("--base-url <url>", "Platform URL", "https://runwork.ai").option("--no-open", "Print login URL without opening browser (polls for completion)").option("--print-only", "With --no-open: print URL and exit without polling").option("--api-key <key>", "Authenticate directly with an API key (for CI)").action(async (url, options) => {
8617
+ var loginCommand = new Command("login").description("Authenticate with Runwork platform").argument("[url]", "Login URL from a previous --no-open session").option("--base-url <url>", "Platform URL", "https://runwork.ai").option("--no-open", "Print login URL without opening browser (polls for completion)").option("--print-only", "With --no-open: print URL and exit without polling").option("--api-key <key>", "Authenticate directly with an API key (for CI)").option("--register", "Open the browser on the registration form for a new account").option("--provider <provider>", "Start this OAuth provider flow directly (google, github)").action(async (url, options) => {
8578
8618
  if (!options)
8579
8619
  return;
8580
8620
  if (options.apiKey) {
@@ -8592,7 +8632,7 @@ var loginCommand = new Command("login").description("Authenticate with Runwork p
8592
8632
  printNextSteps();
8593
8633
  return;
8594
8634
  }
8595
- await performLogin(options.baseUrl);
8635
+ await performLogin(options.baseUrl, { register: options.register, provider: options.provider });
8596
8636
  printNextSteps();
8597
8637
  });
8598
8638
  function printNextSteps() {
@@ -13747,7 +13787,7 @@ var AGENT_REGISTRY = [
13747
13787
  { method: "windows-start-app", target: "Claude" }
13748
13788
  ]
13749
13789
  },
13750
- launch: { app: { macos: "Claude", windows: "Claude" } },
13790
+ launch: { app: { macos: "Claude", windows: "Claude" }, deepLink: "claude://claude.ai/new?q={prompt}" },
13751
13791
  logo: "claude",
13752
13792
  downloadUrl: "https://claude.ai/download",
13753
13793
  skillsPaths: { global: ".claude/skills", project: ".claude/skills" },
@@ -13888,7 +13928,7 @@ var AGENT_REGISTRY = [
13888
13928
  { method: "windows-start-app", target: "ChatGPT Work" }
13889
13929
  ]
13890
13930
  },
13891
- launch: { app: { macos: "ChatGPT Work", windows: "ChatGPT Work" }, bundleId: { macos: "com.openai.codex" }, appxPackage: "OpenAI.Codex" },
13931
+ launch: { app: { macos: "ChatGPT Work", windows: "ChatGPT Work" }, bundleId: { macos: "com.openai.codex" }, appxPackage: "OpenAI.Codex", deepLink: "codex://new?prompt={prompt}" },
13892
13932
  logo: "openai",
13893
13933
  downloadUrl: "https://chatgpt.com/download/",
13894
13934
  skillsPaths: { global: ".agents/skills", project: ".agents/skills" },
@@ -15983,6 +16023,7 @@ ${all.length} insight(s) from your recent work:
15983
16023
  init_store();
15984
16024
  init_client();
15985
16025
  import { Command as Command15 } from "commander";
16026
+ import * as path3 from "node:path";
15986
16027
  init_prompt();
15987
16028
 
15988
16029
  // src/utils/data-input.ts
@@ -16024,6 +16065,125 @@ function parseJson(content, source) {
16024
16065
  }
16025
16066
  }
16026
16067
 
16068
+ // src/export/download-job.ts
16069
+ import * as fs6 from "node:fs";
16070
+ import * as path2 from "node:path";
16071
+
16072
+ // src/export/download.ts
16073
+ function planFileResume(localSizeBytes, chunks) {
16074
+ let boundary = 0;
16075
+ let startChunk = 0;
16076
+ for (const chunk of chunks) {
16077
+ if (boundary + chunk.sizeBytes > localSizeBytes)
16078
+ break;
16079
+ boundary += chunk.sizeBytes;
16080
+ startChunk += 1;
16081
+ }
16082
+ return { startChunk, truncateTo: boundary };
16083
+ }
16084
+ async function downloadExportFile(options) {
16085
+ const retries = options.retriesPerChunk ?? 3;
16086
+ const { startChunk, truncateTo } = planFileResume(options.localSizeBytes, options.chunks);
16087
+ if (truncateTo !== options.localSizeBytes) {
16088
+ await options.truncate(truncateTo);
16089
+ }
16090
+ let downloaded = 0;
16091
+ for (let index = startChunk;index < options.chunks.length; index++) {
16092
+ const expected = options.chunks[index].sizeBytes;
16093
+ let lastError;
16094
+ let bytes = null;
16095
+ for (let attempt = 0;attempt < retries; attempt++) {
16096
+ try {
16097
+ const fetched = await options.fetchChunk(index);
16098
+ if (fetched.byteLength !== expected) {
16099
+ throw new Error(`Chunk ${index} size mismatch: expected ${expected} bytes, got ${fetched.byteLength}`);
16100
+ }
16101
+ bytes = fetched;
16102
+ break;
16103
+ } catch (error) {
16104
+ lastError = error;
16105
+ }
16106
+ }
16107
+ if (!bytes) {
16108
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
16109
+ }
16110
+ await options.append(bytes);
16111
+ downloaded += 1;
16112
+ options.onProgress?.(startChunk + downloaded, options.chunks.length);
16113
+ }
16114
+ return {
16115
+ downloadedChunks: downloaded,
16116
+ skippedChunks: startChunk,
16117
+ totalBytes: options.chunks.reduce((sum, chunk) => sum + chunk.sizeBytes, 0)
16118
+ };
16119
+ }
16120
+
16121
+ // src/export/download-job.ts
16122
+ async function downloadCompletedJob(client, workspaceId, jobId, outputDir, onProgress) {
16123
+ const manifest = await client.getExportManifest(workspaceId, jobId);
16124
+ const written = [];
16125
+ for (const file of manifest.files) {
16126
+ const localPath = path2.join(outputDir, ...file.name.split("/"));
16127
+ fs6.mkdirSync(path2.dirname(localPath), { recursive: true });
16128
+ const localSizeBytes = fs6.existsSync(localPath) ? fs6.statSync(localPath).size : 0;
16129
+ await downloadExportFile({
16130
+ chunks: file.chunks,
16131
+ localSizeBytes,
16132
+ fetchChunk: (chunkIndex) => client.downloadExportChunk(workspaceId, jobId, file.name, chunkIndex),
16133
+ truncate: async (sizeBytes) => {
16134
+ fs6.truncateSync(localPath, sizeBytes);
16135
+ },
16136
+ append: async (bytes) => {
16137
+ fs6.appendFileSync(localPath, Buffer.from(bytes));
16138
+ },
16139
+ onProgress: (done, total) => onProgress?.(file.name, done, total)
16140
+ });
16141
+ written.push(localPath);
16142
+ }
16143
+ fs6.mkdirSync(outputDir, { recursive: true });
16144
+ const manifestPath = path2.join(outputDir, "manifest.json");
16145
+ fs6.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
16146
+ written.push(manifestPath);
16147
+ return { outputDir, files: written };
16148
+ }
16149
+
16150
+ // src/export/targets.ts
16151
+ function resolveExportTargets(entities, filter) {
16152
+ let candidates = entities.filter((e) => e.deploymentMode !== "preview");
16153
+ if (filter.entityName) {
16154
+ candidates = candidates.filter((e) => e.entityName === filter.entityName);
16155
+ if (candidates.length === 0) {
16156
+ return { targets: [], error: `Entity "${filter.entityName}" is not registered in this workspace.` };
16157
+ }
16158
+ }
16159
+ if (filter.appId) {
16160
+ candidates = candidates.filter((e) => e.appId === filter.appId);
16161
+ }
16162
+ const byApp = new Map;
16163
+ for (const entity of candidates) {
16164
+ byApp.set(entity.appId, { appId: entity.appId, appName: entity.appName });
16165
+ }
16166
+ const targets = Array.from(byApp.values());
16167
+ if (filter.entityName && !filter.appId && targets.length > 1) {
16168
+ const names = targets.map((t) => t.appName).join(", ");
16169
+ return {
16170
+ targets: [],
16171
+ error: `Entity "${filter.entityName}" exists in multiple apps (${names}). Pass --app to pick one.`
16172
+ };
16173
+ }
16174
+ if (targets.length === 0) {
16175
+ return { targets: [], error: "No production entities found to export." };
16176
+ }
16177
+ return { targets };
16178
+ }
16179
+ function classifyExportError(message) {
16180
+ return message.includes("not deployed to production") ? "not_deployed" : "error";
16181
+ }
16182
+ function appSlugForPath(appName, appId) {
16183
+ const slug = appName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
16184
+ return slug || appId;
16185
+ }
16186
+
16027
16187
  // src/commands/entities.ts
16028
16188
  var listCommand3 = new Command15("list").description("List entities registered in the workspace").option("--workspace <name-or-id>", "Workspace name or ID").option("--app <id>", "Filter by app name or ID").option("--preview", "Show preview-mode entities only").action(async (opts, command) => {
16029
16189
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
@@ -16171,7 +16331,194 @@ var deleteCommand = new Command15("delete").description("Delete an entity record
16171
16331
  process.exit(1);
16172
16332
  }
16173
16333
  });
16174
- var entitiesCommand = new Command15("entities").alias("data").description("Manage workspace entity data").addCommand(listCommand3).addCommand(recordsCommand).addCommand(getCommand).addCommand(createCommand).addCommand(updateCommand).addCommand(deleteCommand);
16334
+ var POLL_INTERVAL_MS = 2000;
16335
+ var POLL_TIMEOUT_MS = 60 * 60 * 1000;
16336
+ var ACTIVE_EXPORT_STATUSES = new Set(["pending", "running"]);
16337
+ var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
16338
+ function exportProgressLine(job) {
16339
+ const done = job.entities.reduce((sum, e) => sum + e.exportedRecords, 0);
16340
+ const total = job.entities.reduce((sum, e) => e.totalRecords === null ? sum : sum + e.totalRecords, 0);
16341
+ return total > 0 ? `exporting ${done}/${total} records` : "preparing export";
16342
+ }
16343
+ async function waitForExportJob(client, workspaceId, jobId, onProgress) {
16344
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
16345
+ while (true) {
16346
+ const job = await client.getExportJob(workspaceId, jobId);
16347
+ if (!ACTIVE_EXPORT_STATUSES.has(job.status))
16348
+ return job;
16349
+ onProgress(exportProgressLine(job));
16350
+ if (Date.now() > deadline) {
16351
+ throw new Error(`Export ${jobId} did not finish within ${POLL_TIMEOUT_MS / 60000} minutes`);
16352
+ }
16353
+ await sleep(POLL_INTERVAL_MS);
16354
+ }
16355
+ }
16356
+ async function exportOneApp(client, workspaceId, target, options) {
16357
+ const log = (message) => {
16358
+ if (!options.quiet)
16359
+ console.log(message);
16360
+ };
16361
+ const job = await client.createAppExport(workspaceId, target.appId, {
16362
+ format: options.format,
16363
+ entityName: options.entityName
16364
+ });
16365
+ log(`${target.appName}: export job ${job.id} (${job.status})`);
16366
+ if (!options.wait) {
16367
+ return {
16368
+ appId: target.appId,
16369
+ appName: target.appName,
16370
+ jobId: job.id,
16371
+ status: job.status,
16372
+ records: job.recordCount,
16373
+ sizeBytes: job.sizeBytes,
16374
+ outputDir: null,
16375
+ files: [],
16376
+ error: job.error
16377
+ };
16378
+ }
16379
+ const finished = await waitForExportJob(client, workspaceId, job.id, (line) => {
16380
+ if (!options.quiet)
16381
+ process.stdout.write(`\r${target.appName}: ${line} `);
16382
+ });
16383
+ if (!options.quiet)
16384
+ process.stdout.write("\r");
16385
+ if (finished.status !== "completed") {
16386
+ log(`${target.appName}: export ${finished.status}${finished.error ? `: ${finished.error}` : ""}`);
16387
+ return {
16388
+ appId: target.appId,
16389
+ appName: target.appName,
16390
+ jobId: job.id,
16391
+ status: finished.status,
16392
+ records: finished.recordCount,
16393
+ sizeBytes: finished.sizeBytes,
16394
+ outputDir: null,
16395
+ files: [],
16396
+ error: finished.error
16397
+ };
16398
+ }
16399
+ const outputDir = path3.join(options.outputRoot, appSlugForPath(target.appName, target.appId));
16400
+ const { files: writtenFiles } = await downloadCompletedJob(client, workspaceId, job.id, outputDir, (fileName, done, total) => {
16401
+ if (!options.quiet)
16402
+ process.stdout.write(`\r${target.appName}: downloading ${fileName} (${done}/${total} chunks) `);
16403
+ });
16404
+ if (!options.quiet)
16405
+ process.stdout.write("\r");
16406
+ log(`${target.appName}: ${finished.recordCount} record(s) exported to ${outputDir}`);
16407
+ return {
16408
+ appId: target.appId,
16409
+ appName: target.appName,
16410
+ jobId: job.id,
16411
+ status: finished.status,
16412
+ records: finished.recordCount,
16413
+ sizeBytes: finished.sizeBytes,
16414
+ outputDir,
16415
+ files: writtenFiles,
16416
+ error: null
16417
+ };
16418
+ }
16419
+ var exportCommand = new Command15("export").description("Export entity data to local files (free on every plan; production data only)").argument("[entity]", "Restrict the export to a single entity").option("--workspace <name-or-id>", "Workspace name or ID").option("--app <name-or-id>", "App to export; omit to export every app that has entities").option("--format <format>", "Export format: json (newline-delimited JSON) or csv", "json").option("--output <dir>", "Output directory", "runwork-export").option("--no-wait", "Create the export job(s) and exit without downloading").option("--job <exportId>", "Download an existing completed export job instead of starting a new one").action(async (entity, opts, command) => {
16420
+ const useJson = shouldOutputJson(command.optsWithGlobals().json);
16421
+ const credentials = requireAuth();
16422
+ const client = new ApiClient(credentials);
16423
+ const { workspaceId } = await resolveWorkspace2(client, opts);
16424
+ if (opts.job) {
16425
+ try {
16426
+ const job = await client.getExportJob(workspaceId, opts.job);
16427
+ if (job.status !== "completed") {
16428
+ console.error(`Export ${opts.job} is not downloadable (status: ${job.status}${job.error ? `, error: ${job.error}` : ""}).`);
16429
+ process.exit(1);
16430
+ }
16431
+ const apps = await client.listApps(workspaceId);
16432
+ const appName = apps.find((a) => a.id === job.appId)?.name ?? job.appId;
16433
+ const outputDir = path3.join(opts.output, appSlugForPath(appName, job.appId));
16434
+ const result = await downloadCompletedJob(client, workspaceId, job.id, outputDir, (fileName, done, total) => {
16435
+ if (!useJson)
16436
+ process.stdout.write(`\rdownloading ${fileName} (${done}/${total} chunks) `);
16437
+ });
16438
+ if (!useJson)
16439
+ process.stdout.write("\r");
16440
+ if (useJson) {
16441
+ jsonOut({ export: { jobId: job.id, appId: job.appId, appName, status: job.status, records: job.recordCount, sizeBytes: job.sizeBytes, outputDir: result.outputDir, files: result.files } });
16442
+ } else {
16443
+ console.log(`${appName}: ${job.recordCount} record(s) saved to ${result.outputDir}`);
16444
+ }
16445
+ } catch (err) {
16446
+ console.error("Export download failed:", err instanceof Error ? err.message : err);
16447
+ process.exit(1);
16448
+ }
16449
+ return;
16450
+ }
16451
+ const formatInput = String(opts.format).toLowerCase();
16452
+ if (formatInput !== "json" && formatInput !== "ndjson" && formatInput !== "csv") {
16453
+ console.error(`Unknown format "${opts.format}". Use json or csv.`);
16454
+ process.exit(1);
16455
+ }
16456
+ const format = formatInput === "csv" ? "csv" : "ndjson";
16457
+ try {
16458
+ let appId;
16459
+ if (opts.app) {
16460
+ const resolved = await resolveApp2(client, workspaceId, { app: opts.app });
16461
+ appId = resolved.appId;
16462
+ }
16463
+ const entities = await client.listEntities(workspaceId);
16464
+ const { targets, error } = resolveExportTargets(entities, { appId, entityName: entity });
16465
+ if (error) {
16466
+ console.error(error);
16467
+ process.exit(1);
16468
+ }
16469
+ const results = [];
16470
+ for (const target of targets) {
16471
+ try {
16472
+ results.push(await exportOneApp(client, workspaceId, target, {
16473
+ format,
16474
+ entityName: entity,
16475
+ wait: opts.wait !== false,
16476
+ outputRoot: opts.output,
16477
+ quiet: useJson
16478
+ }));
16479
+ } catch (err) {
16480
+ const message = err instanceof Error ? err.message : String(err);
16481
+ const kind = classifyExportError(message);
16482
+ const status = kind === "not_deployed" ? "skipped" : "failed";
16483
+ if (!useJson) {
16484
+ console.error(kind === "not_deployed" ? `${target.appName}: skipped (not deployed to production)` : `${target.appName}: failed: ${message}`);
16485
+ }
16486
+ results.push({
16487
+ appId: target.appId,
16488
+ appName: target.appName,
16489
+ jobId: "",
16490
+ status,
16491
+ records: 0,
16492
+ sizeBytes: 0,
16493
+ outputDir: null,
16494
+ files: [],
16495
+ error: message
16496
+ });
16497
+ }
16498
+ }
16499
+ if (useJson) {
16500
+ jsonOut({ exports: results });
16501
+ return;
16502
+ }
16503
+ const exported = results.filter((r) => r.status === "completed");
16504
+ const skipped = results.filter((r) => r.status === "skipped");
16505
+ const failed = results.filter((r) => r.status === "failed");
16506
+ const summary = [`${exported.length} app(s) exported`];
16507
+ if (skipped.length > 0)
16508
+ summary.push(`${skipped.length} skipped (not deployed)`);
16509
+ if (failed.length > 0)
16510
+ summary.push(`${failed.length} failed`);
16511
+ console.log(`
16512
+ ${summary.join(", ")}.`);
16513
+ if (failed.length > 0 || opts.app && skipped.length > 0) {
16514
+ process.exit(1);
16515
+ }
16516
+ } catch (err) {
16517
+ console.error("Export failed:", err instanceof Error ? err.message : err);
16518
+ process.exit(1);
16519
+ }
16520
+ });
16521
+ var entitiesCommand = new Command15("entities").alias("data").description("Manage workspace entity data").addCommand(listCommand3).addCommand(recordsCommand).addCommand(getCommand).addCommand(createCommand).addCommand(updateCommand).addCommand(deleteCommand).addCommand(exportCommand);
16175
16522
 
16176
16523
  // src/commands/workflows.ts
16177
16524
  init_store();
@@ -16575,12 +16922,12 @@ Workspace: ${workspaceName || workspaceId}
16575
16922
  console.log(" " + "-".repeat(90));
16576
16923
  for (const e of endpoints) {
16577
16924
  const method = e.method.toUpperCase().padEnd(8);
16578
- const path2 = e.endpointPath.padEnd(36);
16925
+ const path4 = e.endpointPath.padEnd(36);
16579
16926
  const app = (e.appName || e.appId).padEnd(20);
16580
16927
  const auth = (e.auth || "").padEnd(10);
16581
16928
  const desc = truncate3(e.description, 40);
16582
16929
  const mode = e.deploymentMode ? ` [${e.deploymentMode}]` : "";
16583
- console.log(` ${method} ${path2} ${app} ${auth} ${desc}${mode}`);
16930
+ console.log(` ${method} ${path4} ${app} ${auth} ${desc}${mode}`);
16584
16931
  }
16585
16932
  console.log("");
16586
16933
  } catch (err) {
@@ -16588,7 +16935,7 @@ Workspace: ${workspaceName || workspaceId}
16588
16935
  process.exit(1);
16589
16936
  }
16590
16937
  });
16591
- var callCommand2 = new Command18("call").description("Call a workspace endpoint directly").argument("<method>", "HTTP method (GET, POST, PUT, DELETE, etc.)").argument("<path>", "Endpoint path (e.g. /my-endpoint)").option("--workspace <name-or-id>", "Workspace name or ID").option("--app <name>", "App name or ID (narrows endpoint lookup)").option("--body <json>", "Request body as JSON string").option("--header <header>", 'Request header (format: "Key: Value", repeatable)', (val, prev) => [...prev, val], []).option("--query <string>", 'Query string to append to the URL (e.g. "foo=bar&baz=1")').option("--api-key <key>", "API key for Authorization: Bearer header").action(async (method, path2, opts, command) => {
16938
+ var callCommand2 = new Command18("call").description("Call a workspace endpoint directly").argument("<method>", "HTTP method (GET, POST, PUT, DELETE, etc.)").argument("<path>", "Endpoint path (e.g. /my-endpoint)").option("--workspace <name-or-id>", "Workspace name or ID").option("--app <name>", "App name or ID (narrows endpoint lookup)").option("--body <json>", "Request body as JSON string").option("--header <header>", 'Request header (format: "Key: Value", repeatable)', (val, prev) => [...prev, val], []).option("--query <string>", 'Query string to append to the URL (e.g. "foo=bar&baz=1")').option("--api-key <key>", "API key for Authorization: Bearer header").action(async (method, path4, opts, command) => {
16592
16939
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
16593
16940
  const credentials = requireAuth();
16594
16941
  const client = new ApiClient(credentials);
@@ -16599,9 +16946,9 @@ var callCommand2 = new Command18("call").description("Call a workspace endpoint
16599
16946
  endpoints = endpoints.filter((e) => e.appId === opts.app || e.appName === opts.app);
16600
16947
  }
16601
16948
  const targetMethod = method.toUpperCase();
16602
- const endpoint = endpoints.find((e) => e.method.toUpperCase() === targetMethod && e.endpointPath === path2);
16949
+ const endpoint = endpoints.find((e) => e.method.toUpperCase() === targetMethod && e.endpointPath === path4);
16603
16950
  if (!endpoint) {
16604
- console.error(`Endpoint not found: ${targetMethod} ${path2}`);
16951
+ console.error(`Endpoint not found: ${targetMethod} ${path4}`);
16605
16952
  if (endpoints.length > 0) {
16606
16953
  console.error(`
16607
16954
  Available endpoints:`);
@@ -16620,7 +16967,7 @@ Available endpoints:`);
16620
16967
  process.exit(1);
16621
16968
  }
16622
16969
  const baseUrl = `https://${workspaceName}.runwork.ai`;
16623
- let url = `${baseUrl}/${appSlug}/endpoints${path2}`;
16970
+ let url = `${baseUrl}/${appSlug}/endpoints${path4}`;
16624
16971
  if (opts.query) {
16625
16972
  url = `${url}?${opts.query}`;
16626
16973
  }
@@ -16704,7 +17051,7 @@ var endpointsCommand = new Command18("endpoints").alias("routes").description("M
16704
17051
  init_store();
16705
17052
  init_client();
16706
17053
  import { Command as Command19 } from "commander";
16707
- import { writeFileSync as writeFileSync28, readFileSync as readFileSync32 } from "fs";
17054
+ import { writeFileSync as writeFileSync29, readFileSync as readFileSync32 } from "fs";
16708
17055
  import { basename as basename2 } from "path";
16709
17056
  init_prompt();
16710
17057
  init_http();
@@ -16798,7 +17145,7 @@ var downloadCommand = new Command19("download").description("Download a file fro
16798
17145
  if (!response.ok) {
16799
17146
  throw new Error(`Download failed: ${response.status} ${response.statusText}`);
16800
17147
  }
16801
- writeFileSync28(outputPath, Buffer.from(await response.arrayBuffer()));
17148
+ writeFileSync29(outputPath, Buffer.from(await response.arrayBuffer()));
16802
17149
  if (useJson) {
16803
17150
  jsonOut({ success: true, bucket, key, outputPath });
16804
17151
  return;
@@ -17315,8 +17662,8 @@ var mcpCommand = new Command23("mcp").description("Manage workspace MCP servers"
17315
17662
  init_store();
17316
17663
  init_client();
17317
17664
  import { Command as Command25 } from "commander";
17318
- import { writeFileSync as writeFileSync30, mkdirSync as mkdirSync27 } from "fs";
17319
- import { join as join37 } from "path";
17665
+ import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync28 } from "fs";
17666
+ import { join as join39 } from "path";
17320
17667
  import { homedir as homedir19 } from "os";
17321
17668
  init_prompt();
17322
17669
 
@@ -17324,8 +17671,8 @@ init_prompt();
17324
17671
  init_store();
17325
17672
  init_client();
17326
17673
  import { Command as Command24 } from "commander";
17327
- import { readFileSync as readFileSync33, writeFileSync as writeFileSync29, existsSync as existsSync41 } from "fs";
17328
- import { join as join35 } from "path";
17674
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync30, existsSync as existsSync42 } from "fs";
17675
+ import { join as join37 } from "path";
17329
17676
  import { homedir as homedir17 } from "os";
17330
17677
 
17331
17678
  // src/commands/mcp-entries.ts
@@ -18584,7 +18931,7 @@ Tip: ${hint.title}`);
18584
18931
  } catch {}
18585
18932
  }
18586
18933
  function loadSetupState(filePath) {
18587
- if (!existsSync41(filePath))
18934
+ if (!existsSync42(filePath))
18588
18935
  return null;
18589
18936
  try {
18590
18937
  return JSON.parse(readFileSync33(filePath, "utf-8"));
@@ -18608,14 +18955,14 @@ function readLocalSkills(state) {
18608
18955
  if (!baseDir)
18609
18956
  continue;
18610
18957
  for (const skillName of state.skills) {
18611
- const skillMdPath = join35(baseDir, skillName, "SKILL.md");
18612
- if (existsSync41(skillMdPath)) {
18958
+ const skillMdPath = join37(baseDir, skillName, "SKILL.md");
18959
+ if (existsSync42(skillMdPath)) {
18613
18960
  results.push({ name: skillName, content: readFileSync33(skillMdPath, "utf-8") });
18614
18961
  continue;
18615
18962
  }
18616
18963
  const filename = skillName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
18617
- const flatPath = join35(baseDir, `${filename}.md`);
18618
- if (existsSync41(flatPath)) {
18964
+ const flatPath = join37(baseDir, `${filename}.md`);
18965
+ if (existsSync42(flatPath)) {
18619
18966
  results.push({ name: skillName, content: readFileSync33(flatPath, "utf-8") });
18620
18967
  }
18621
18968
  }
@@ -18820,7 +19167,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
18820
19167
  persona: state.persona
18821
19168
  });
18822
19169
  let projectAppSkillFilter = null;
18823
- if (existsSync41(".runwork.json")) {
19170
+ if (existsSync42(".runwork.json")) {
18824
19171
  try {
18825
19172
  const config = JSON.parse(readFileSync33(".runwork.json", "utf-8"));
18826
19173
  if (config.appName) {
@@ -19059,7 +19406,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19059
19406
  }
19060
19407
  for (const adapter2 of adapters) {
19061
19408
  if (adapter2 instanceof CodexAdapter) {
19062
- const runworkDir = join35(homedir17(), ".runwork");
19409
+ const runworkDir = join37(homedir17(), ".runwork");
19063
19410
  const result = adapter2.registerDesktopWorkspace(runworkDir, "Runwork");
19064
19411
  if (result === "written") {
19065
19412
  vlog(` [${adapter2.name}] Registered workspace in Codex desktop app`);
@@ -19134,7 +19481,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19134
19481
  delete mergedHashes[del.name];
19135
19482
  }
19136
19483
  state.skillHashes = mergedHashes;
19137
- writeFileSync29(statePath2, JSON.stringify(state, null, 2));
19484
+ writeFileSync30(statePath2, JSON.stringify(state, null, 2));
19138
19485
  try {
19139
19486
  const telemetryNow = new Date().toISOString();
19140
19487
  const telemetry = await collectTelemetryEvents({
@@ -19154,7 +19501,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19154
19501
  if (telemetry.healthReported) {
19155
19502
  state.lastHealthReportAt = new Date().toISOString();
19156
19503
  }
19157
- writeFileSync29(statePath2, JSON.stringify(state, null, 2));
19504
+ writeFileSync30(statePath2, JSON.stringify(state, null, 2));
19158
19505
  } catch {}
19159
19506
  const failedNote = summary.adaptersFailed > 0 ? ` (${summary.adaptersFailed} failed)` : "";
19160
19507
  if (isVerbose()) {
@@ -19192,8 +19539,8 @@ var syncCommand = new Command24("sync").description("Sync skills bidirectionally
19192
19539
  verbose: !!opts.verbose,
19193
19540
  redetect: !!opts.redetect
19194
19541
  };
19195
- const projectStatePath = join35(process.cwd(), ".runwork", "setup.json");
19196
- const userStatePath = join35(homedir17(), ".runwork", "setup.json");
19542
+ const projectStatePath = join37(process.cwd(), ".runwork", "setup.json");
19543
+ const userStatePath = join37(homedir17(), ".runwork", "setup.json");
19197
19544
  const projectState = loadSetupState(projectStatePath);
19198
19545
  const userState = loadSetupState(userStatePath);
19199
19546
  if (!projectState && !userState) {
@@ -19214,14 +19561,14 @@ Sync complete.`);
19214
19561
  });
19215
19562
 
19216
19563
  // src/utils/setup-state.ts
19217
- import { existsSync as existsSync42, readFileSync as readFileSync34 } from "fs";
19218
- import { join as join36 } from "path";
19564
+ import { existsSync as existsSync43, readFileSync as readFileSync34 } from "fs";
19565
+ import { join as join38 } from "path";
19219
19566
  import { homedir as homedir18 } from "os";
19220
19567
  function loadSetupState2() {
19221
- const projectPath = join36(process.cwd(), ".runwork", "setup.json");
19222
- const userPath = join36(homedir18(), ".runwork", "setup.json");
19568
+ const projectPath = join38(process.cwd(), ".runwork", "setup.json");
19569
+ const userPath = join38(homedir18(), ".runwork", "setup.json");
19223
19570
  for (const p of [projectPath, userPath]) {
19224
- if (existsSync42(p)) {
19571
+ if (existsSync43(p)) {
19225
19572
  try {
19226
19573
  return JSON.parse(readFileSync34(p, "utf-8"));
19227
19574
  } catch {
@@ -19343,9 +19690,9 @@ Configuring all agents (--yes).
19343
19690
  };
19344
19691
  const scopes = scope === "both" ? ["project", "user"] : [scope];
19345
19692
  for (const s of scopes) {
19346
- const dir = s === "project" ? ".runwork" : join37(homedir19(), ".runwork");
19347
- mkdirSync27(dir, { recursive: true });
19348
- writeFileSync30(join37(dir, "setup.json"), JSON.stringify(state, null, 2));
19693
+ const dir = s === "project" ? ".runwork" : join39(homedir19(), ".runwork");
19694
+ mkdirSync28(dir, { recursive: true });
19695
+ writeFileSync31(join39(dir, "setup.json"), JSON.stringify(state, null, 2));
19349
19696
  }
19350
19697
  if (opts.dryRun) {
19351
19698
  console.log(`
@@ -19361,7 +19708,7 @@ Re-run without --dry-run to sync workspace data.`);
19361
19708
  Syncing workspace data...
19362
19709
  `);
19363
19710
  for (const s of scopes) {
19364
- const statePath2 = s === "project" ? join37(process.cwd(), ".runwork", "setup.json") : join37(homedir19(), ".runwork", "setup.json");
19711
+ const statePath2 = s === "project" ? join39(process.cwd(), ".runwork", "setup.json") : join39(homedir19(), ".runwork", "setup.json");
19365
19712
  await syncFromState(state, statePath2, credentials, {
19366
19713
  dryRun: false,
19367
19714
  pullOnly: true,
@@ -19378,11 +19725,11 @@ Syncing workspace data...
19378
19725
  init_store();
19379
19726
  init_client();
19380
19727
  import { Command as Command26 } from "commander";
19381
- import { existsSync as existsSync43, readFileSync as readFileSync35 } from "fs";
19382
- import { resolve as resolve3, join as join38 } from "path";
19728
+ import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
19729
+ import { resolve as resolve3, join as join40 } from "path";
19383
19730
  import { homedir as homedir20 } from "os";
19384
19731
  function loadSetupState3(filePath) {
19385
- if (!existsSync43(filePath))
19732
+ if (!existsSync44(filePath))
19386
19733
  return null;
19387
19734
  try {
19388
19735
  return JSON.parse(readFileSync35(filePath, "utf-8"));
@@ -19401,8 +19748,8 @@ var buildPluginCommand = new Command26("build-plugin").description("Build an ins
19401
19748
  process.exit(1);
19402
19749
  }
19403
19750
  const credentials = requireAuth();
19404
- const projectStatePath = join38(process.cwd(), ".runwork", "setup.json");
19405
- const userStatePath = join38(homedir20(), ".runwork", "setup.json");
19751
+ const projectStatePath = join40(process.cwd(), ".runwork", "setup.json");
19752
+ const userStatePath = join40(homedir20(), ".runwork", "setup.json");
19406
19753
  const state = loadSetupState3(projectStatePath) ?? loadSetupState3(userStatePath);
19407
19754
  if (!state) {
19408
19755
  console.error("No setup state found. Run `runwork setup` first.");
@@ -19492,12 +19839,12 @@ var buildPluginCommand = new Command26("build-plugin").description("Build an ins
19492
19839
 
19493
19840
  // src/commands/uninstall.ts
19494
19841
  import { Command as Command27 } from "commander";
19495
- import { existsSync as existsSync44, readFileSync as readFileSync36, rmSync as rmSync12, unlinkSync as unlinkSync7 } from "fs";
19496
- import { join as join39 } from "path";
19842
+ import { existsSync as existsSync45, readFileSync as readFileSync36, rmSync as rmSync12, unlinkSync as unlinkSync7 } from "fs";
19843
+ import { join as join41 } from "path";
19497
19844
  import { homedir as homedir21 } from "os";
19498
19845
  init_prompt();
19499
19846
  function loadSetupState4(filePath) {
19500
- if (!existsSync44(filePath))
19847
+ if (!existsSync45(filePath))
19501
19848
  return null;
19502
19849
  try {
19503
19850
  return JSON.parse(readFileSync36(filePath, "utf-8"));
@@ -19506,8 +19853,8 @@ function loadSetupState4(filePath) {
19506
19853
  }
19507
19854
  }
19508
19855
  var uninstallCommand = new Command27("uninstall").description("Remove all Runwork configuration from local agents (MCP servers, skills, instructions)").option("-y, --yes", "Skip confirmation prompt").option("--keep-auth", "Keep authentication credentials (only remove agent configs)").action(async (opts) => {
19509
- const projectStatePath = join39(process.cwd(), ".runwork", "setup.json");
19510
- const userStatePath = join39(homedir21(), ".runwork", "setup.json");
19856
+ const projectStatePath = join41(process.cwd(), ".runwork", "setup.json");
19857
+ const userStatePath = join41(homedir21(), ".runwork", "setup.json");
19511
19858
  const projectState = loadSetupState4(projectStatePath);
19512
19859
  const userState = loadSetupState4(userStatePath);
19513
19860
  if (!projectState && !userState) {
@@ -19587,10 +19934,10 @@ This will remove all Runwork configuration from your local agents:
19587
19934
  }
19588
19935
  }
19589
19936
  }
19590
- const stateDir = label === "project" ? join39(process.cwd(), ".runwork") : join39(homedir21(), ".runwork");
19937
+ const stateDir = label === "project" ? join41(process.cwd(), ".runwork") : join41(homedir21(), ".runwork");
19591
19938
  if (opts.keepAuth && label === "user") {
19592
- const setupFile = join39(stateDir, "setup.json");
19593
- if (existsSync44(setupFile)) {
19939
+ const setupFile = join41(stateDir, "setup.json");
19940
+ if (existsSync45(setupFile)) {
19594
19941
  try {
19595
19942
  unlinkSync7(setupFile);
19596
19943
  console.log(` Removed ${setupFile} (kept credentials)`);
@@ -19599,7 +19946,7 @@ This will remove all Runwork configuration from your local agents:
19599
19946
  errors++;
19600
19947
  }
19601
19948
  }
19602
- } else if (existsSync44(stateDir)) {
19949
+ } else if (existsSync45(stateDir)) {
19603
19950
  try {
19604
19951
  rmSync12(stateDir, { recursive: true, force: true });
19605
19952
  console.log(` Removed ${stateDir}`);
@@ -19751,12 +20098,12 @@ Examples:
19751
20098
 
19752
20099
  Authentication uses your stored Runwork credentials; the API key never needs
19753
20100
  to be read or pasted manually. Prefer a dedicated command when one exists
19754
- (runwork apps/members/schedules/...).`).action(async (method, path2, opts, command) => {
20101
+ (runwork apps/members/schedules/...).`).action(async (method, path4, opts, command) => {
19755
20102
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
19756
20103
  const credentials = requireAuth();
19757
20104
  const client = new ApiClient(credentials);
19758
20105
  let finalMethod = method;
19759
- let finalPath = path2;
20106
+ let finalPath = path4;
19760
20107
  const headers = {};
19761
20108
  let body;
19762
20109
  const query = opts.query;
@@ -19833,8 +20180,8 @@ init_subprocess();
19833
20180
  init_store();
19834
20181
  init_client();
19835
20182
  import { parse as parse2 } from "smol-toml";
19836
- import { existsSync as existsSync45, readFileSync as readFileSync38 } from "fs";
19837
- import { join as join40, sep as sep4 } from "path";
20183
+ import { existsSync as existsSync46, readFileSync as readFileSync38 } from "fs";
20184
+ import { join as join42, sep as sep4 } from "path";
19838
20185
  import { homedir as homedir22, platform as osPlatform2, arch as osArch } from "os";
19839
20186
  init_http();
19840
20187
  init_preflight();
@@ -19866,8 +20213,8 @@ function buildContext() {
19866
20213
  const credentials = getCredentials();
19867
20214
  const client = credentials ? new ApiClient(credentials) : null;
19868
20215
  let config = null;
19869
- const configPath = join40(process.cwd(), ".runwork.json");
19870
- if (existsSync45(configPath)) {
20216
+ const configPath = join42(process.cwd(), ".runwork.json");
20217
+ if (existsSync46(configPath)) {
19871
20218
  try {
19872
20219
  config = JSON.parse(readFileSync38(configPath, "utf-8"));
19873
20220
  } catch {}
@@ -19971,8 +20318,8 @@ async function checkCliArtifactReachable() {
19971
20318
  async function checkCliInstallLocation() {
19972
20319
  const isWindows2 = osPlatform2() === "win32";
19973
20320
  const home = homedir22();
19974
- const canonicalDir = join40(home, ".runwork", "bin");
19975
- const canonicalBinary = isWindows2 ? join40(canonicalDir, "runwork.exe") : join40(canonicalDir, "runwork");
20321
+ const canonicalDir = join42(home, ".runwork", "bin");
20322
+ const canonicalBinary = isWindows2 ? join42(canonicalDir, "runwork.exe") : join42(canonicalDir, "runwork");
19976
20323
  const candidates = [process.execPath, process.argv[1] || ""].filter(Boolean);
19977
20324
  const runsFromCanonical = candidates.some((p) => normalizePath(p) === normalizePath(canonicalBinary));
19978
20325
  if (runsFromCanonical) {
@@ -19982,7 +20329,7 @@ async function checkCliInstallLocation() {
19982
20329
  message: `canonical (${canonicalBinary})`
19983
20330
  };
19984
20331
  }
19985
- if (existsSync45(canonicalBinary)) {
20332
+ if (existsSync46(canonicalBinary)) {
19986
20333
  return {
19987
20334
  name: "cli-install-location",
19988
20335
  status: "warn",
@@ -20104,8 +20451,8 @@ async function checkGitCredentialHelper(ctx) {
20104
20451
  };
20105
20452
  }
20106
20453
  async function checkProjectConfig(ctx) {
20107
- const configPath = join40(ctx.cwd, ".runwork.json");
20108
- if (!existsSync45(configPath)) {
20454
+ const configPath = join42(ctx.cwd, ".runwork.json");
20455
+ if (!existsSync46(configPath)) {
20109
20456
  if (!ctx.credentials) {
20110
20457
  return { name: "project-config", status: "skip", message: "no project (not logged in)" };
20111
20458
  }
@@ -20167,7 +20514,7 @@ async function checkGitRemote(ctx) {
20167
20514
  if (!ctx.config) {
20168
20515
  return { name: "git-remote", status: "skip", message: "skipped (no project)" };
20169
20516
  }
20170
- if (!existsSync45(join40(ctx.cwd, ".git"))) {
20517
+ if (!existsSync46(join42(ctx.cwd, ".git"))) {
20171
20518
  return {
20172
20519
  name: "git-remote",
20173
20520
  status: "fail",
@@ -20221,10 +20568,10 @@ async function checkDeployFreshness(ctx) {
20221
20568
  return { name: "deploy-freshness", status: "skip", message: "local HEAD unknown" };
20222
20569
  }
20223
20570
  function loadSetupState5() {
20224
- const projectPath = join40(process.cwd(), ".runwork", "setup.json");
20225
- const userPath = join40(homedir22(), ".runwork", "setup.json");
20571
+ const projectPath = join42(process.cwd(), ".runwork", "setup.json");
20572
+ const userPath = join42(homedir22(), ".runwork", "setup.json");
20226
20573
  for (const p of [projectPath, userPath]) {
20227
- if (existsSync45(p)) {
20574
+ if (existsSync46(p)) {
20228
20575
  try {
20229
20576
  return JSON.parse(readFileSync38(p, "utf-8"));
20230
20577
  } catch {
@@ -20241,8 +20588,8 @@ async function checkCodexNetwork() {
20241
20588
  if (!state || !state.configuredAgents.includes("codex")) {
20242
20589
  return { name, status: "skip", message: "Codex not configured for Runwork" };
20243
20590
  }
20244
- const configPath = join40(homedir22(), ".codex", "config.toml");
20245
- if (!existsSync45(configPath)) {
20591
+ const configPath = join42(homedir22(), ".codex", "config.toml");
20592
+ if (!existsSync46(configPath)) {
20246
20593
  return { name, status: "skip", message: "no Codex config found" };
20247
20594
  }
20248
20595
  let parsed;
@@ -20300,8 +20647,8 @@ async function checkCodexDesktopProject() {
20300
20647
  if (!usesCodex) {
20301
20648
  return { name, status: "skip", message: "Codex not configured for Runwork" };
20302
20649
  }
20303
- const statePath2 = join40(homedir22(), ".codex", ".codex-global-state.json");
20304
- if (!existsSync45(statePath2)) {
20650
+ const statePath2 = join42(homedir22(), ".codex", ".codex-global-state.json");
20651
+ if (!existsSync46(statePath2)) {
20305
20652
  return { name, status: "skip", message: "Codex desktop app not detected" };
20306
20653
  }
20307
20654
  let savedRoots = [];
@@ -20312,7 +20659,7 @@ async function checkCodexDesktopProject() {
20312
20659
  } catch {
20313
20660
  return { name, status: "warn", message: "could not read Codex desktop state" };
20314
20661
  }
20315
- const runworkDir = join40(homedir22(), ".runwork");
20662
+ const runworkDir = join42(homedir22(), ".runwork");
20316
20663
  if (savedRoots.includes(runworkDir)) {
20317
20664
  return { name, status: "pass", message: "Runwork project added to Codex desktop sidebar" };
20318
20665
  }
@@ -20365,7 +20712,7 @@ async function checkAgentSetup() {
20365
20712
  if (!adapter2 || !adapter2.supportsMcpScope("user"))
20366
20713
  continue;
20367
20714
  const mcpConfigPath = getMcpConfigPath2(slug, "user");
20368
- if (mcpConfigPath && existsSync45(mcpConfigPath)) {
20715
+ if (mcpConfigPath && existsSync46(mcpConfigPath)) {
20369
20716
  try {
20370
20717
  const content = readFileSync38(mcpConfigPath, "utf-8");
20371
20718
  const missingMcp = state.mcpServers.filter((name) => !content.includes(name));
@@ -20390,8 +20737,8 @@ async function checkAgentSetup() {
20390
20737
  if (!skillsDir)
20391
20738
  continue;
20392
20739
  const missingSkills = state.skills.filter((name) => {
20393
- const skillPath = join40(skillsDir, name, "SKILL.md");
20394
- return !existsSync45(skillPath);
20740
+ const skillPath = join42(skillsDir, name, "SKILL.md");
20741
+ return !existsSync46(skillPath);
20395
20742
  });
20396
20743
  if (missingSkills.length > 0) {
20397
20744
  details.push(`${missingSkills.length} skill(s) missing from ${slug}`);
@@ -20419,16 +20766,16 @@ function getMcpConfigPath2(slug, scope) {
20419
20766
  const home = homedir22();
20420
20767
  switch (slug) {
20421
20768
  case "claude-code":
20422
- return scope === "project" ? join40(process.cwd(), ".mcp.json") : join40(home, ".claude", "settings.json");
20769
+ return scope === "project" ? join42(process.cwd(), ".mcp.json") : join42(home, ".claude", "settings.json");
20423
20770
  case "cursor":
20424
- return scope === "project" ? join40(process.cwd(), ".cursor", "mcp.json") : join40(home, ".cursor", "mcp.json");
20771
+ return scope === "project" ? join42(process.cwd(), ".cursor", "mcp.json") : join42(home, ".cursor", "mcp.json");
20425
20772
  case "windsurf":
20426
- return scope === "project" ? join40(process.cwd(), ".windsurf", "mcp.json") : join40(home, ".windsurf", "mcp.json");
20773
+ return scope === "project" ? join42(process.cwd(), ".windsurf", "mcp.json") : join42(home, ".windsurf", "mcp.json");
20427
20774
  case "codex":
20428
20775
  case "codex-app":
20429
- return scope === "user" ? join40(home, ".codex", "config.toml") : null;
20776
+ return scope === "user" ? join42(home, ".codex", "config.toml") : null;
20430
20777
  case "gemini":
20431
- return scope === "user" ? join40(home, ".gemini", "settings.json") : null;
20778
+ return scope === "user" ? join42(home, ".gemini", "settings.json") : null;
20432
20779
  default:
20433
20780
  return null;
20434
20781
  }
@@ -20437,12 +20784,12 @@ function getSkillsDir(slug, scope) {
20437
20784
  const home = homedir22();
20438
20785
  switch (slug) {
20439
20786
  case "claude-code":
20440
- return scope === "project" ? join40(process.cwd(), ".claude", "skills") : join40(home, ".claude", "skills");
20787
+ return scope === "project" ? join42(process.cwd(), ".claude", "skills") : join42(home, ".claude", "skills");
20441
20788
  case "codex":
20442
20789
  case "codex-app":
20443
- return scope === "project" ? join40(process.cwd(), ".agents", "skills") : join40(home, ".agents", "skills");
20790
+ return scope === "project" ? join42(process.cwd(), ".agents", "skills") : join42(home, ".agents", "skills");
20444
20791
  case "gemini":
20445
- return scope === "project" ? join40(process.cwd(), ".gemini", "skills") : join40(home, ".gemini", "skills");
20792
+ return scope === "project" ? join42(process.cwd(), ".gemini", "skills") : join42(home, ".gemini", "skills");
20446
20793
  default:
20447
20794
  return null;
20448
20795
  }
@@ -20494,8 +20841,8 @@ async function runAllChecks(options) {
20494
20841
  // src/health/fix.ts
20495
20842
  init_credentials();
20496
20843
  init_remote();
20497
- import { existsSync as existsSync46 } from "fs";
20498
- import { join as join41 } from "path";
20844
+ import { existsSync as existsSync47 } from "fs";
20845
+ import { join as join43 } from "path";
20499
20846
  async function applyDoctorFixes(ctx, failingNames) {
20500
20847
  const failing = new Set(failingNames);
20501
20848
  const outcomes = [];
@@ -20522,7 +20869,7 @@ async function applyDoctorFixes(ctx, failingNames) {
20522
20869
  applied: false,
20523
20870
  message: "no project config -- run inside an app directory"
20524
20871
  });
20525
- } else if (!existsSync46(join41(ctx.cwd, ".git"))) {
20872
+ } else if (!existsSync47(join43(ctx.cwd, ".git"))) {
20526
20873
  outcomes.push({
20527
20874
  name: "git-remote",
20528
20875
  applied: false,
@@ -20541,10 +20888,10 @@ async function applyDoctorFixes(ctx, failingNames) {
20541
20888
  }
20542
20889
 
20543
20890
  // src/agents/runtime-detection.ts
20544
- import { existsSync as existsSync47, readFileSync as readFileSync39, statSync as statSync7, readdirSync as readdirSync13 } from "fs";
20891
+ import { existsSync as existsSync48, readFileSync as readFileSync39, statSync as statSync8, readdirSync as readdirSync13 } from "fs";
20545
20892
  import { homedir as homedir23 } from "os";
20546
- import { join as join42 } from "path";
20547
- var RUNWORK_SESSIONS_DIR = join42(homedir23(), ".runwork", "sessions");
20893
+ import { join as join44 } from "path";
20894
+ var RUNWORK_SESSIONS_DIR = join44(homedir23(), ".runwork", "sessions");
20548
20895
  function detectCurrentAgent() {
20549
20896
  const claudeCodeSessionId = process.env.CLAUDE_CODE_SESSION_ID;
20550
20897
  if (claudeCodeSessionId) {
@@ -20607,11 +20954,11 @@ function detectCurrentAgent() {
20607
20954
  return null;
20608
20955
  }
20609
20956
  function readHookSessionInfo(sessionId) {
20610
- const path2 = join42(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
20611
- if (!existsSync47(path2))
20957
+ const path4 = join44(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
20958
+ if (!existsSync48(path4))
20612
20959
  return null;
20613
20960
  try {
20614
- const raw = readFileSync39(path2, "utf8");
20961
+ const raw = readFileSync39(path4, "utf8");
20615
20962
  const parsed = JSON.parse(raw);
20616
20963
  return parsed;
20617
20964
  } catch {
@@ -20619,8 +20966,8 @@ function readHookSessionInfo(sessionId) {
20619
20966
  }
20620
20967
  }
20621
20968
  function findClaudeCodeSessionFile(sessionId) {
20622
- const root = join42(homedir23(), ".claude", "projects");
20623
- if (!existsSync47(root))
20969
+ const root = join44(homedir23(), ".claude", "projects");
20970
+ if (!existsSync48(root))
20624
20971
  return null;
20625
20972
  let projectDirs;
20626
20973
  try {
@@ -20629,15 +20976,15 @@ function findClaudeCodeSessionFile(sessionId) {
20629
20976
  return null;
20630
20977
  }
20631
20978
  for (const dir of projectDirs) {
20632
- const candidate = join42(root, dir, `${sessionId}.jsonl`);
20633
- if (existsSync47(candidate))
20979
+ const candidate = join44(root, dir, `${sessionId}.jsonl`);
20980
+ if (existsSync48(candidate))
20634
20981
  return candidate;
20635
20982
  }
20636
20983
  return null;
20637
20984
  }
20638
20985
  function findCodexRolloutFile(threadId) {
20639
- const root = join42(homedir23(), ".codex", "sessions");
20640
- if (!existsSync47(root))
20986
+ const root = join44(homedir23(), ".codex", "sessions");
20987
+ if (!existsSync48(root))
20641
20988
  return null;
20642
20989
  const stack = [root];
20643
20990
  while (stack.length > 0) {
@@ -20649,10 +20996,10 @@ function findCodexRolloutFile(threadId) {
20649
20996
  continue;
20650
20997
  }
20651
20998
  for (const entry of entries) {
20652
- const full = join42(dir, entry);
20999
+ const full = join44(dir, entry);
20653
21000
  let s;
20654
21001
  try {
20655
- s = statSync7(full);
21002
+ s = statSync8(full);
20656
21003
  } catch {
20657
21004
  continue;
20658
21005
  }
@@ -20666,8 +21013,8 @@ function findCodexRolloutFile(threadId) {
20666
21013
  return null;
20667
21014
  }
20668
21015
  function findNewestClaudeCodeSession() {
20669
- const root = join42(homedir23(), ".claude", "projects");
20670
- if (!existsSync47(root))
21016
+ const root = join44(homedir23(), ".claude", "projects");
21017
+ if (!existsSync48(root))
20671
21018
  return null;
20672
21019
  let projectDirs;
20673
21020
  try {
@@ -20677,7 +21024,7 @@ function findNewestClaudeCodeSession() {
20677
21024
  }
20678
21025
  let best = null;
20679
21026
  for (const dir of projectDirs) {
20680
- const projectPath = join42(root, dir);
21027
+ const projectPath = join44(root, dir);
20681
21028
  let files;
20682
21029
  try {
20683
21030
  files = readdirSync13(projectPath);
@@ -20687,9 +21034,9 @@ function findNewestClaudeCodeSession() {
20687
21034
  for (const file of files) {
20688
21035
  if (!file.endsWith(".jsonl"))
20689
21036
  continue;
20690
- const full = join42(projectPath, file);
21037
+ const full = join44(projectPath, file);
20691
21038
  try {
20692
- const s = statSync7(full);
21039
+ const s = statSync8(full);
20693
21040
  if (!best || s.mtimeMs > best.mtime) {
20694
21041
  best = {
20695
21042
  sessionId: file.replace(/\.jsonl$/, ""),
@@ -20705,8 +21052,8 @@ function findNewestClaudeCodeSession() {
20705
21052
  return best ? { sessionId: best.sessionId, path: best.path } : null;
20706
21053
  }
20707
21054
  function findNewestCodexRollout() {
20708
- const root = join42(homedir23(), ".codex", "sessions");
20709
- if (!existsSync47(root))
21055
+ const root = join44(homedir23(), ".codex", "sessions");
21056
+ if (!existsSync48(root))
20710
21057
  return null;
20711
21058
  const stack = [root];
20712
21059
  let best = null;
@@ -20719,10 +21066,10 @@ function findNewestCodexRollout() {
20719
21066
  continue;
20720
21067
  }
20721
21068
  for (const entry of entries) {
20722
- const full = join42(dir, entry);
21069
+ const full = join44(dir, entry);
20723
21070
  let s;
20724
21071
  try {
20725
- s = statSync7(full);
21072
+ s = statSync8(full);
20726
21073
  } catch {
20727
21074
  continue;
20728
21075
  }
@@ -20950,7 +21297,7 @@ var doctorCommand = new Command31("doctor").description("Check system health: au
20950
21297
  init_store();
20951
21298
  init_client();
20952
21299
  import { Command as Command32 } from "commander";
20953
- import { readFileSync as readFileSync40, existsSync as existsSync48 } from "fs";
21300
+ import { readFileSync as readFileSync40, existsSync as existsSync49 } from "fs";
20954
21301
  import { createHash as createHash4 } from "crypto";
20955
21302
  function nativeBundleFormatForAgent(slug) {
20956
21303
  if (slug === "claude-code" || slug === "claude-desktop")
@@ -20971,7 +21318,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
20971
21318
  console.error("Error: --transcript-file is required. Pass the path to the LLM-emitted markdown transcript.");
20972
21319
  process.exit(1);
20973
21320
  }
20974
- if (!existsSync48(opts.transcriptFile)) {
21321
+ if (!existsSync49(opts.transcriptFile)) {
20975
21322
  console.error(`Error: transcript file does not exist: ${opts.transcriptFile}`);
20976
21323
  process.exit(1);
20977
21324
  }
@@ -21005,12 +21352,12 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
21005
21352
  const sourceAgent = opts.sourceAgent ?? detected?.slug ?? "generic";
21006
21353
  let nativeFilePath = null;
21007
21354
  if (opts.nativeFile) {
21008
- if (!existsSync48(opts.nativeFile)) {
21355
+ if (!existsSync49(opts.nativeFile)) {
21009
21356
  console.error(`Error: --native-file path does not exist: ${opts.nativeFile}`);
21010
21357
  process.exit(1);
21011
21358
  }
21012
21359
  nativeFilePath = opts.nativeFile;
21013
- } else if (detected?.sessionFilePath && existsSync48(detected.sessionFilePath)) {
21360
+ } else if (detected?.sessionFilePath && existsSync49(detected.sessionFilePath)) {
21014
21361
  nativeFilePath = detected.sessionFilePath;
21015
21362
  }
21016
21363
  if (nativeFilePath) {
@@ -21139,9 +21486,9 @@ Shared conversations (${scope}, ${total}):
21139
21486
  init_store();
21140
21487
  init_client();
21141
21488
  import { Command as Command35 } from "commander";
21142
- import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync28, realpathSync } from "fs";
21489
+ import { writeFileSync as writeFileSync32, mkdirSync as mkdirSync29, realpathSync } from "fs";
21143
21490
  import { homedir as homedir24 } from "os";
21144
- import { join as join43 } from "path";
21491
+ import { join as join45 } from "path";
21145
21492
  import { spawn as spawn5 } from "child_process";
21146
21493
  function encodeClaudeCodeCwd(cwd) {
21147
21494
  let canonical;
@@ -21178,10 +21525,10 @@ function extractCodexUuid(rolloutContent) {
21178
21525
  }
21179
21526
  function placeClaudeJsonl(uuid, content, recipientCwd) {
21180
21527
  const encoded = encodeClaudeCodeCwd(recipientCwd);
21181
- const projectDir = join43(homedir24(), ".claude", "projects", encoded);
21182
- mkdirSync28(projectDir, { recursive: true });
21183
- const placedAt = join43(projectDir, `${uuid}.jsonl`);
21184
- writeFileSync31(placedAt, content);
21528
+ const projectDir = join45(homedir24(), ".claude", "projects", encoded);
21529
+ mkdirSync29(projectDir, { recursive: true });
21530
+ const placedAt = join45(projectDir, `${uuid}.jsonl`);
21531
+ writeFileSync32(placedAt, content);
21185
21532
  return { placedAt, runFromCwd: recipientCwd };
21186
21533
  }
21187
21534
  function placeCodexRollout(uuid, content) {
@@ -21189,11 +21536,11 @@ function placeCodexRollout(uuid, content) {
21189
21536
  const yyyy = String(now.getUTCFullYear());
21190
21537
  const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
21191
21538
  const dd = String(now.getUTCDate()).padStart(2, "0");
21192
- const dir = join43(homedir24(), ".codex", "sessions", yyyy, mm, dd);
21193
- mkdirSync28(dir, { recursive: true });
21539
+ const dir = join45(homedir24(), ".codex", "sessions", yyyy, mm, dd);
21540
+ mkdirSync29(dir, { recursive: true });
21194
21541
  const ts = now.toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
21195
- const placedAt = join43(dir, `rollout-${ts}-${uuid}.jsonl`);
21196
- writeFileSync31(placedAt, content);
21542
+ const placedAt = join45(dir, `rollout-${ts}-${uuid}.jsonl`);
21543
+ writeFileSync32(placedAt, content);
21197
21544
  return { placedAt };
21198
21545
  }
21199
21546
  function pickTargetAgent(opts, sourceAgent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runwork",
3
- "version": "0.18.4",
3
+ "version": "0.19.1",
4
4
  "description": "CLI for Runwork: develop, preview, and deploy Runwork apps from your local machine.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Runwork, Inc. <info@runwork.ai> (https://www.runwork.ai)",