runwork 0.18.4 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +427 -121
  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;
@@ -7583,7 +7612,7 @@ function createKeyboardListener() {
7583
7612
  }
7584
7613
 
7585
7614
  // src/generated/version.ts
7586
- var VERSION = "0.18.4";
7615
+ var VERSION = "0.19.0";
7587
7616
 
7588
7617
  // src/commands/dev.ts
7589
7618
  var exports_dev = {};
@@ -13747,7 +13776,7 @@ var AGENT_REGISTRY = [
13747
13776
  { method: "windows-start-app", target: "Claude" }
13748
13777
  ]
13749
13778
  },
13750
- launch: { app: { macos: "Claude", windows: "Claude" } },
13779
+ launch: { app: { macos: "Claude", windows: "Claude" }, deepLink: "claude://claude.ai/new?q={prompt}" },
13751
13780
  logo: "claude",
13752
13781
  downloadUrl: "https://claude.ai/download",
13753
13782
  skillsPaths: { global: ".claude/skills", project: ".claude/skills" },
@@ -13888,7 +13917,7 @@ var AGENT_REGISTRY = [
13888
13917
  { method: "windows-start-app", target: "ChatGPT Work" }
13889
13918
  ]
13890
13919
  },
13891
- launch: { app: { macos: "ChatGPT Work", windows: "ChatGPT Work" }, bundleId: { macos: "com.openai.codex" }, appxPackage: "OpenAI.Codex" },
13920
+ launch: { app: { macos: "ChatGPT Work", windows: "ChatGPT Work" }, bundleId: { macos: "com.openai.codex" }, appxPackage: "OpenAI.Codex", deepLink: "codex://new?prompt={prompt}" },
13892
13921
  logo: "openai",
13893
13922
  downloadUrl: "https://chatgpt.com/download/",
13894
13923
  skillsPaths: { global: ".agents/skills", project: ".agents/skills" },
@@ -15983,6 +16012,7 @@ ${all.length} insight(s) from your recent work:
15983
16012
  init_store();
15984
16013
  init_client();
15985
16014
  import { Command as Command15 } from "commander";
16015
+ import * as path3 from "node:path";
15986
16016
  init_prompt();
15987
16017
 
15988
16018
  // src/utils/data-input.ts
@@ -16024,6 +16054,122 @@ function parseJson(content, source) {
16024
16054
  }
16025
16055
  }
16026
16056
 
16057
+ // src/export/download-job.ts
16058
+ import * as fs6 from "node:fs";
16059
+ import * as path2 from "node:path";
16060
+
16061
+ // src/export/download.ts
16062
+ function planFileResume(localSizeBytes, chunks) {
16063
+ let boundary = 0;
16064
+ let startChunk = 0;
16065
+ for (const chunk of chunks) {
16066
+ if (boundary + chunk.sizeBytes > localSizeBytes)
16067
+ break;
16068
+ boundary += chunk.sizeBytes;
16069
+ startChunk += 1;
16070
+ }
16071
+ return { startChunk, truncateTo: boundary };
16072
+ }
16073
+ async function downloadExportFile(options) {
16074
+ const retries = options.retriesPerChunk ?? 3;
16075
+ const { startChunk, truncateTo } = planFileResume(options.localSizeBytes, options.chunks);
16076
+ if (truncateTo !== options.localSizeBytes) {
16077
+ await options.truncate(truncateTo);
16078
+ }
16079
+ let downloaded = 0;
16080
+ for (let index = startChunk;index < options.chunks.length; index++) {
16081
+ const expected = options.chunks[index].sizeBytes;
16082
+ let lastError;
16083
+ let bytes = null;
16084
+ for (let attempt = 0;attempt < retries; attempt++) {
16085
+ try {
16086
+ const fetched = await options.fetchChunk(index);
16087
+ if (fetched.byteLength !== expected) {
16088
+ throw new Error(`Chunk ${index} size mismatch: expected ${expected} bytes, got ${fetched.byteLength}`);
16089
+ }
16090
+ bytes = fetched;
16091
+ break;
16092
+ } catch (error) {
16093
+ lastError = error;
16094
+ }
16095
+ }
16096
+ if (!bytes) {
16097
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
16098
+ }
16099
+ await options.append(bytes);
16100
+ downloaded += 1;
16101
+ options.onProgress?.(startChunk + downloaded, options.chunks.length);
16102
+ }
16103
+ return {
16104
+ downloadedChunks: downloaded,
16105
+ skippedChunks: startChunk,
16106
+ totalBytes: options.chunks.reduce((sum, chunk) => sum + chunk.sizeBytes, 0)
16107
+ };
16108
+ }
16109
+
16110
+ // src/export/download-job.ts
16111
+ async function downloadCompletedJob(client, workspaceId, jobId, outputDir, onProgress) {
16112
+ const manifest = await client.getExportManifest(workspaceId, jobId);
16113
+ const written = [];
16114
+ for (const file of manifest.files) {
16115
+ const localPath = path2.join(outputDir, ...file.name.split("/"));
16116
+ fs6.mkdirSync(path2.dirname(localPath), { recursive: true });
16117
+ const localSizeBytes = fs6.existsSync(localPath) ? fs6.statSync(localPath).size : 0;
16118
+ await downloadExportFile({
16119
+ chunks: file.chunks,
16120
+ localSizeBytes,
16121
+ fetchChunk: (chunkIndex) => client.downloadExportChunk(workspaceId, jobId, file.name, chunkIndex),
16122
+ truncate: async (sizeBytes) => {
16123
+ fs6.truncateSync(localPath, sizeBytes);
16124
+ },
16125
+ append: async (bytes) => {
16126
+ fs6.appendFileSync(localPath, Buffer.from(bytes));
16127
+ },
16128
+ onProgress: (done, total) => onProgress?.(file.name, done, total)
16129
+ });
16130
+ written.push(localPath);
16131
+ }
16132
+ fs6.mkdirSync(outputDir, { recursive: true });
16133
+ const manifestPath = path2.join(outputDir, "manifest.json");
16134
+ fs6.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
16135
+ written.push(manifestPath);
16136
+ return { outputDir, files: written };
16137
+ }
16138
+
16139
+ // src/export/targets.ts
16140
+ function resolveExportTargets(entities, filter) {
16141
+ let candidates = entities.filter((e) => e.deploymentMode !== "preview");
16142
+ if (filter.entityName) {
16143
+ candidates = candidates.filter((e) => e.entityName === filter.entityName);
16144
+ if (candidates.length === 0) {
16145
+ return { targets: [], error: `Entity "${filter.entityName}" is not registered in this workspace.` };
16146
+ }
16147
+ }
16148
+ if (filter.appId) {
16149
+ candidates = candidates.filter((e) => e.appId === filter.appId);
16150
+ }
16151
+ const byApp = new Map;
16152
+ for (const entity of candidates) {
16153
+ byApp.set(entity.appId, { appId: entity.appId, appName: entity.appName });
16154
+ }
16155
+ const targets = Array.from(byApp.values());
16156
+ if (filter.entityName && !filter.appId && targets.length > 1) {
16157
+ const names = targets.map((t) => t.appName).join(", ");
16158
+ return {
16159
+ targets: [],
16160
+ error: `Entity "${filter.entityName}" exists in multiple apps (${names}). Pass --app to pick one.`
16161
+ };
16162
+ }
16163
+ if (targets.length === 0) {
16164
+ return { targets: [], error: "No production entities found to export." };
16165
+ }
16166
+ return { targets };
16167
+ }
16168
+ function appSlugForPath(appName, appId) {
16169
+ const slug = appName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
16170
+ return slug || appId;
16171
+ }
16172
+
16027
16173
  // src/commands/entities.ts
16028
16174
  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
16175
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
@@ -16171,7 +16317,167 @@ var deleteCommand = new Command15("delete").description("Delete an entity record
16171
16317
  process.exit(1);
16172
16318
  }
16173
16319
  });
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);
16320
+ var POLL_INTERVAL_MS = 2000;
16321
+ var POLL_TIMEOUT_MS = 60 * 60 * 1000;
16322
+ var ACTIVE_EXPORT_STATUSES = new Set(["pending", "running"]);
16323
+ var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
16324
+ function exportProgressLine(job) {
16325
+ const done = job.entities.reduce((sum, e) => sum + e.exportedRecords, 0);
16326
+ const total = job.entities.reduce((sum, e) => e.totalRecords === null ? sum : sum + e.totalRecords, 0);
16327
+ return total > 0 ? `exporting ${done}/${total} records` : "preparing export";
16328
+ }
16329
+ async function waitForExportJob(client, workspaceId, jobId, onProgress) {
16330
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
16331
+ while (true) {
16332
+ const job = await client.getExportJob(workspaceId, jobId);
16333
+ if (!ACTIVE_EXPORT_STATUSES.has(job.status))
16334
+ return job;
16335
+ onProgress(exportProgressLine(job));
16336
+ if (Date.now() > deadline) {
16337
+ throw new Error(`Export ${jobId} did not finish within ${POLL_TIMEOUT_MS / 60000} minutes`);
16338
+ }
16339
+ await sleep(POLL_INTERVAL_MS);
16340
+ }
16341
+ }
16342
+ async function exportOneApp(client, workspaceId, target, options) {
16343
+ const log = (message) => {
16344
+ if (!options.quiet)
16345
+ console.log(message);
16346
+ };
16347
+ const job = await client.createAppExport(workspaceId, target.appId, {
16348
+ format: options.format,
16349
+ entityName: options.entityName
16350
+ });
16351
+ log(`${target.appName}: export job ${job.id} (${job.status})`);
16352
+ if (!options.wait) {
16353
+ return {
16354
+ appId: target.appId,
16355
+ appName: target.appName,
16356
+ jobId: job.id,
16357
+ status: job.status,
16358
+ records: job.recordCount,
16359
+ sizeBytes: job.sizeBytes,
16360
+ outputDir: null,
16361
+ files: [],
16362
+ error: job.error
16363
+ };
16364
+ }
16365
+ const finished = await waitForExportJob(client, workspaceId, job.id, (line) => {
16366
+ if (!options.quiet)
16367
+ process.stdout.write(`\r${target.appName}: ${line} `);
16368
+ });
16369
+ if (!options.quiet)
16370
+ process.stdout.write("\r");
16371
+ if (finished.status !== "completed") {
16372
+ log(`${target.appName}: export ${finished.status}${finished.error ? `: ${finished.error}` : ""}`);
16373
+ return {
16374
+ appId: target.appId,
16375
+ appName: target.appName,
16376
+ jobId: job.id,
16377
+ status: finished.status,
16378
+ records: finished.recordCount,
16379
+ sizeBytes: finished.sizeBytes,
16380
+ outputDir: null,
16381
+ files: [],
16382
+ error: finished.error
16383
+ };
16384
+ }
16385
+ const outputDir = path3.join(options.outputRoot, appSlugForPath(target.appName, target.appId));
16386
+ const { files: writtenFiles } = await downloadCompletedJob(client, workspaceId, job.id, outputDir, (fileName, done, total) => {
16387
+ if (!options.quiet)
16388
+ process.stdout.write(`\r${target.appName}: downloading ${fileName} (${done}/${total} chunks) `);
16389
+ });
16390
+ if (!options.quiet)
16391
+ process.stdout.write("\r");
16392
+ log(`${target.appName}: ${finished.recordCount} record(s) exported to ${outputDir}`);
16393
+ return {
16394
+ appId: target.appId,
16395
+ appName: target.appName,
16396
+ jobId: job.id,
16397
+ status: finished.status,
16398
+ records: finished.recordCount,
16399
+ sizeBytes: finished.sizeBytes,
16400
+ outputDir,
16401
+ files: writtenFiles,
16402
+ error: null
16403
+ };
16404
+ }
16405
+ 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) => {
16406
+ const useJson = shouldOutputJson(command.optsWithGlobals().json);
16407
+ const credentials = requireAuth();
16408
+ const client = new ApiClient(credentials);
16409
+ const { workspaceId } = await resolveWorkspace2(client, opts);
16410
+ if (opts.job) {
16411
+ try {
16412
+ const job = await client.getExportJob(workspaceId, opts.job);
16413
+ if (job.status !== "completed") {
16414
+ console.error(`Export ${opts.job} is not downloadable (status: ${job.status}${job.error ? `, error: ${job.error}` : ""}).`);
16415
+ process.exit(1);
16416
+ }
16417
+ const apps = await client.listApps(workspaceId);
16418
+ const appName = apps.find((a) => a.id === job.appId)?.name ?? job.appId;
16419
+ const outputDir = path3.join(opts.output, appSlugForPath(appName, job.appId));
16420
+ const result = await downloadCompletedJob(client, workspaceId, job.id, outputDir, (fileName, done, total) => {
16421
+ if (!useJson)
16422
+ process.stdout.write(`\rdownloading ${fileName} (${done}/${total} chunks) `);
16423
+ });
16424
+ if (!useJson)
16425
+ process.stdout.write("\r");
16426
+ if (useJson) {
16427
+ jsonOut({ export: { jobId: job.id, appId: job.appId, appName, status: job.status, records: job.recordCount, sizeBytes: job.sizeBytes, outputDir: result.outputDir, files: result.files } });
16428
+ } else {
16429
+ console.log(`${appName}: ${job.recordCount} record(s) saved to ${result.outputDir}`);
16430
+ }
16431
+ } catch (err) {
16432
+ console.error("Export download failed:", err instanceof Error ? err.message : err);
16433
+ process.exit(1);
16434
+ }
16435
+ return;
16436
+ }
16437
+ const formatInput = String(opts.format).toLowerCase();
16438
+ if (formatInput !== "json" && formatInput !== "ndjson" && formatInput !== "csv") {
16439
+ console.error(`Unknown format "${opts.format}". Use json or csv.`);
16440
+ process.exit(1);
16441
+ }
16442
+ const format = formatInput === "csv" ? "csv" : "ndjson";
16443
+ try {
16444
+ let appId;
16445
+ if (opts.app) {
16446
+ const resolved = await resolveApp2(client, workspaceId, { app: opts.app });
16447
+ appId = resolved.appId;
16448
+ }
16449
+ const entities = await client.listEntities(workspaceId);
16450
+ const { targets, error } = resolveExportTargets(entities, { appId, entityName: entity });
16451
+ if (error) {
16452
+ console.error(error);
16453
+ process.exit(1);
16454
+ }
16455
+ const results = [];
16456
+ for (const target of targets) {
16457
+ results.push(await exportOneApp(client, workspaceId, target, {
16458
+ format,
16459
+ entityName: entity,
16460
+ wait: opts.wait !== false,
16461
+ outputRoot: opts.output,
16462
+ quiet: useJson
16463
+ }));
16464
+ }
16465
+ if (useJson) {
16466
+ jsonOut({ exports: results });
16467
+ return;
16468
+ }
16469
+ const failed = results.filter((r) => r.status === "failed");
16470
+ if (failed.length > 0) {
16471
+ console.error(`
16472
+ ${failed.length} export(s) failed.`);
16473
+ process.exit(1);
16474
+ }
16475
+ } catch (err) {
16476
+ console.error("Export failed:", err instanceof Error ? err.message : err);
16477
+ process.exit(1);
16478
+ }
16479
+ });
16480
+ 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
16481
 
16176
16482
  // src/commands/workflows.ts
16177
16483
  init_store();
@@ -16575,12 +16881,12 @@ Workspace: ${workspaceName || workspaceId}
16575
16881
  console.log(" " + "-".repeat(90));
16576
16882
  for (const e of endpoints) {
16577
16883
  const method = e.method.toUpperCase().padEnd(8);
16578
- const path2 = e.endpointPath.padEnd(36);
16884
+ const path4 = e.endpointPath.padEnd(36);
16579
16885
  const app = (e.appName || e.appId).padEnd(20);
16580
16886
  const auth = (e.auth || "").padEnd(10);
16581
16887
  const desc = truncate3(e.description, 40);
16582
16888
  const mode = e.deploymentMode ? ` [${e.deploymentMode}]` : "";
16583
- console.log(` ${method} ${path2} ${app} ${auth} ${desc}${mode}`);
16889
+ console.log(` ${method} ${path4} ${app} ${auth} ${desc}${mode}`);
16584
16890
  }
16585
16891
  console.log("");
16586
16892
  } catch (err) {
@@ -16588,7 +16894,7 @@ Workspace: ${workspaceName || workspaceId}
16588
16894
  process.exit(1);
16589
16895
  }
16590
16896
  });
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) => {
16897
+ 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
16898
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
16593
16899
  const credentials = requireAuth();
16594
16900
  const client = new ApiClient(credentials);
@@ -16599,9 +16905,9 @@ var callCommand2 = new Command18("call").description("Call a workspace endpoint
16599
16905
  endpoints = endpoints.filter((e) => e.appId === opts.app || e.appName === opts.app);
16600
16906
  }
16601
16907
  const targetMethod = method.toUpperCase();
16602
- const endpoint = endpoints.find((e) => e.method.toUpperCase() === targetMethod && e.endpointPath === path2);
16908
+ const endpoint = endpoints.find((e) => e.method.toUpperCase() === targetMethod && e.endpointPath === path4);
16603
16909
  if (!endpoint) {
16604
- console.error(`Endpoint not found: ${targetMethod} ${path2}`);
16910
+ console.error(`Endpoint not found: ${targetMethod} ${path4}`);
16605
16911
  if (endpoints.length > 0) {
16606
16912
  console.error(`
16607
16913
  Available endpoints:`);
@@ -16620,7 +16926,7 @@ Available endpoints:`);
16620
16926
  process.exit(1);
16621
16927
  }
16622
16928
  const baseUrl = `https://${workspaceName}.runwork.ai`;
16623
- let url = `${baseUrl}/${appSlug}/endpoints${path2}`;
16929
+ let url = `${baseUrl}/${appSlug}/endpoints${path4}`;
16624
16930
  if (opts.query) {
16625
16931
  url = `${url}?${opts.query}`;
16626
16932
  }
@@ -16704,7 +17010,7 @@ var endpointsCommand = new Command18("endpoints").alias("routes").description("M
16704
17010
  init_store();
16705
17011
  init_client();
16706
17012
  import { Command as Command19 } from "commander";
16707
- import { writeFileSync as writeFileSync28, readFileSync as readFileSync32 } from "fs";
17013
+ import { writeFileSync as writeFileSync29, readFileSync as readFileSync32 } from "fs";
16708
17014
  import { basename as basename2 } from "path";
16709
17015
  init_prompt();
16710
17016
  init_http();
@@ -16798,7 +17104,7 @@ var downloadCommand = new Command19("download").description("Download a file fro
16798
17104
  if (!response.ok) {
16799
17105
  throw new Error(`Download failed: ${response.status} ${response.statusText}`);
16800
17106
  }
16801
- writeFileSync28(outputPath, Buffer.from(await response.arrayBuffer()));
17107
+ writeFileSync29(outputPath, Buffer.from(await response.arrayBuffer()));
16802
17108
  if (useJson) {
16803
17109
  jsonOut({ success: true, bucket, key, outputPath });
16804
17110
  return;
@@ -17315,8 +17621,8 @@ var mcpCommand = new Command23("mcp").description("Manage workspace MCP servers"
17315
17621
  init_store();
17316
17622
  init_client();
17317
17623
  import { Command as Command25 } from "commander";
17318
- import { writeFileSync as writeFileSync30, mkdirSync as mkdirSync27 } from "fs";
17319
- import { join as join37 } from "path";
17624
+ import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync28 } from "fs";
17625
+ import { join as join39 } from "path";
17320
17626
  import { homedir as homedir19 } from "os";
17321
17627
  init_prompt();
17322
17628
 
@@ -17324,8 +17630,8 @@ init_prompt();
17324
17630
  init_store();
17325
17631
  init_client();
17326
17632
  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";
17633
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync30, existsSync as existsSync42 } from "fs";
17634
+ import { join as join37 } from "path";
17329
17635
  import { homedir as homedir17 } from "os";
17330
17636
 
17331
17637
  // src/commands/mcp-entries.ts
@@ -18584,7 +18890,7 @@ Tip: ${hint.title}`);
18584
18890
  } catch {}
18585
18891
  }
18586
18892
  function loadSetupState(filePath) {
18587
- if (!existsSync41(filePath))
18893
+ if (!existsSync42(filePath))
18588
18894
  return null;
18589
18895
  try {
18590
18896
  return JSON.parse(readFileSync33(filePath, "utf-8"));
@@ -18608,14 +18914,14 @@ function readLocalSkills(state) {
18608
18914
  if (!baseDir)
18609
18915
  continue;
18610
18916
  for (const skillName of state.skills) {
18611
- const skillMdPath = join35(baseDir, skillName, "SKILL.md");
18612
- if (existsSync41(skillMdPath)) {
18917
+ const skillMdPath = join37(baseDir, skillName, "SKILL.md");
18918
+ if (existsSync42(skillMdPath)) {
18613
18919
  results.push({ name: skillName, content: readFileSync33(skillMdPath, "utf-8") });
18614
18920
  continue;
18615
18921
  }
18616
18922
  const filename = skillName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
18617
- const flatPath = join35(baseDir, `${filename}.md`);
18618
- if (existsSync41(flatPath)) {
18923
+ const flatPath = join37(baseDir, `${filename}.md`);
18924
+ if (existsSync42(flatPath)) {
18619
18925
  results.push({ name: skillName, content: readFileSync33(flatPath, "utf-8") });
18620
18926
  }
18621
18927
  }
@@ -18820,7 +19126,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
18820
19126
  persona: state.persona
18821
19127
  });
18822
19128
  let projectAppSkillFilter = null;
18823
- if (existsSync41(".runwork.json")) {
19129
+ if (existsSync42(".runwork.json")) {
18824
19130
  try {
18825
19131
  const config = JSON.parse(readFileSync33(".runwork.json", "utf-8"));
18826
19132
  if (config.appName) {
@@ -19059,7 +19365,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19059
19365
  }
19060
19366
  for (const adapter2 of adapters) {
19061
19367
  if (adapter2 instanceof CodexAdapter) {
19062
- const runworkDir = join35(homedir17(), ".runwork");
19368
+ const runworkDir = join37(homedir17(), ".runwork");
19063
19369
  const result = adapter2.registerDesktopWorkspace(runworkDir, "Runwork");
19064
19370
  if (result === "written") {
19065
19371
  vlog(` [${adapter2.name}] Registered workspace in Codex desktop app`);
@@ -19134,7 +19440,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19134
19440
  delete mergedHashes[del.name];
19135
19441
  }
19136
19442
  state.skillHashes = mergedHashes;
19137
- writeFileSync29(statePath2, JSON.stringify(state, null, 2));
19443
+ writeFileSync30(statePath2, JSON.stringify(state, null, 2));
19138
19444
  try {
19139
19445
  const telemetryNow = new Date().toISOString();
19140
19446
  const telemetry = await collectTelemetryEvents({
@@ -19154,7 +19460,7 @@ async function syncFromState(state, statePath2, credentials, opts) {
19154
19460
  if (telemetry.healthReported) {
19155
19461
  state.lastHealthReportAt = new Date().toISOString();
19156
19462
  }
19157
- writeFileSync29(statePath2, JSON.stringify(state, null, 2));
19463
+ writeFileSync30(statePath2, JSON.stringify(state, null, 2));
19158
19464
  } catch {}
19159
19465
  const failedNote = summary.adaptersFailed > 0 ? ` (${summary.adaptersFailed} failed)` : "";
19160
19466
  if (isVerbose()) {
@@ -19192,8 +19498,8 @@ var syncCommand = new Command24("sync").description("Sync skills bidirectionally
19192
19498
  verbose: !!opts.verbose,
19193
19499
  redetect: !!opts.redetect
19194
19500
  };
19195
- const projectStatePath = join35(process.cwd(), ".runwork", "setup.json");
19196
- const userStatePath = join35(homedir17(), ".runwork", "setup.json");
19501
+ const projectStatePath = join37(process.cwd(), ".runwork", "setup.json");
19502
+ const userStatePath = join37(homedir17(), ".runwork", "setup.json");
19197
19503
  const projectState = loadSetupState(projectStatePath);
19198
19504
  const userState = loadSetupState(userStatePath);
19199
19505
  if (!projectState && !userState) {
@@ -19214,14 +19520,14 @@ Sync complete.`);
19214
19520
  });
19215
19521
 
19216
19522
  // src/utils/setup-state.ts
19217
- import { existsSync as existsSync42, readFileSync as readFileSync34 } from "fs";
19218
- import { join as join36 } from "path";
19523
+ import { existsSync as existsSync43, readFileSync as readFileSync34 } from "fs";
19524
+ import { join as join38 } from "path";
19219
19525
  import { homedir as homedir18 } from "os";
19220
19526
  function loadSetupState2() {
19221
- const projectPath = join36(process.cwd(), ".runwork", "setup.json");
19222
- const userPath = join36(homedir18(), ".runwork", "setup.json");
19527
+ const projectPath = join38(process.cwd(), ".runwork", "setup.json");
19528
+ const userPath = join38(homedir18(), ".runwork", "setup.json");
19223
19529
  for (const p of [projectPath, userPath]) {
19224
- if (existsSync42(p)) {
19530
+ if (existsSync43(p)) {
19225
19531
  try {
19226
19532
  return JSON.parse(readFileSync34(p, "utf-8"));
19227
19533
  } catch {
@@ -19343,9 +19649,9 @@ Configuring all agents (--yes).
19343
19649
  };
19344
19650
  const scopes = scope === "both" ? ["project", "user"] : [scope];
19345
19651
  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));
19652
+ const dir = s === "project" ? ".runwork" : join39(homedir19(), ".runwork");
19653
+ mkdirSync28(dir, { recursive: true });
19654
+ writeFileSync31(join39(dir, "setup.json"), JSON.stringify(state, null, 2));
19349
19655
  }
19350
19656
  if (opts.dryRun) {
19351
19657
  console.log(`
@@ -19361,7 +19667,7 @@ Re-run without --dry-run to sync workspace data.`);
19361
19667
  Syncing workspace data...
19362
19668
  `);
19363
19669
  for (const s of scopes) {
19364
- const statePath2 = s === "project" ? join37(process.cwd(), ".runwork", "setup.json") : join37(homedir19(), ".runwork", "setup.json");
19670
+ const statePath2 = s === "project" ? join39(process.cwd(), ".runwork", "setup.json") : join39(homedir19(), ".runwork", "setup.json");
19365
19671
  await syncFromState(state, statePath2, credentials, {
19366
19672
  dryRun: false,
19367
19673
  pullOnly: true,
@@ -19378,11 +19684,11 @@ Syncing workspace data...
19378
19684
  init_store();
19379
19685
  init_client();
19380
19686
  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";
19687
+ import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
19688
+ import { resolve as resolve3, join as join40 } from "path";
19383
19689
  import { homedir as homedir20 } from "os";
19384
19690
  function loadSetupState3(filePath) {
19385
- if (!existsSync43(filePath))
19691
+ if (!existsSync44(filePath))
19386
19692
  return null;
19387
19693
  try {
19388
19694
  return JSON.parse(readFileSync35(filePath, "utf-8"));
@@ -19401,8 +19707,8 @@ var buildPluginCommand = new Command26("build-plugin").description("Build an ins
19401
19707
  process.exit(1);
19402
19708
  }
19403
19709
  const credentials = requireAuth();
19404
- const projectStatePath = join38(process.cwd(), ".runwork", "setup.json");
19405
- const userStatePath = join38(homedir20(), ".runwork", "setup.json");
19710
+ const projectStatePath = join40(process.cwd(), ".runwork", "setup.json");
19711
+ const userStatePath = join40(homedir20(), ".runwork", "setup.json");
19406
19712
  const state = loadSetupState3(projectStatePath) ?? loadSetupState3(userStatePath);
19407
19713
  if (!state) {
19408
19714
  console.error("No setup state found. Run `runwork setup` first.");
@@ -19492,12 +19798,12 @@ var buildPluginCommand = new Command26("build-plugin").description("Build an ins
19492
19798
 
19493
19799
  // src/commands/uninstall.ts
19494
19800
  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";
19801
+ import { existsSync as existsSync45, readFileSync as readFileSync36, rmSync as rmSync12, unlinkSync as unlinkSync7 } from "fs";
19802
+ import { join as join41 } from "path";
19497
19803
  import { homedir as homedir21 } from "os";
19498
19804
  init_prompt();
19499
19805
  function loadSetupState4(filePath) {
19500
- if (!existsSync44(filePath))
19806
+ if (!existsSync45(filePath))
19501
19807
  return null;
19502
19808
  try {
19503
19809
  return JSON.parse(readFileSync36(filePath, "utf-8"));
@@ -19506,8 +19812,8 @@ function loadSetupState4(filePath) {
19506
19812
  }
19507
19813
  }
19508
19814
  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");
19815
+ const projectStatePath = join41(process.cwd(), ".runwork", "setup.json");
19816
+ const userStatePath = join41(homedir21(), ".runwork", "setup.json");
19511
19817
  const projectState = loadSetupState4(projectStatePath);
19512
19818
  const userState = loadSetupState4(userStatePath);
19513
19819
  if (!projectState && !userState) {
@@ -19587,10 +19893,10 @@ This will remove all Runwork configuration from your local agents:
19587
19893
  }
19588
19894
  }
19589
19895
  }
19590
- const stateDir = label === "project" ? join39(process.cwd(), ".runwork") : join39(homedir21(), ".runwork");
19896
+ const stateDir = label === "project" ? join41(process.cwd(), ".runwork") : join41(homedir21(), ".runwork");
19591
19897
  if (opts.keepAuth && label === "user") {
19592
- const setupFile = join39(stateDir, "setup.json");
19593
- if (existsSync44(setupFile)) {
19898
+ const setupFile = join41(stateDir, "setup.json");
19899
+ if (existsSync45(setupFile)) {
19594
19900
  try {
19595
19901
  unlinkSync7(setupFile);
19596
19902
  console.log(` Removed ${setupFile} (kept credentials)`);
@@ -19599,7 +19905,7 @@ This will remove all Runwork configuration from your local agents:
19599
19905
  errors++;
19600
19906
  }
19601
19907
  }
19602
- } else if (existsSync44(stateDir)) {
19908
+ } else if (existsSync45(stateDir)) {
19603
19909
  try {
19604
19910
  rmSync12(stateDir, { recursive: true, force: true });
19605
19911
  console.log(` Removed ${stateDir}`);
@@ -19751,12 +20057,12 @@ Examples:
19751
20057
 
19752
20058
  Authentication uses your stored Runwork credentials; the API key never needs
19753
20059
  to be read or pasted manually. Prefer a dedicated command when one exists
19754
- (runwork apps/members/schedules/...).`).action(async (method, path2, opts, command) => {
20060
+ (runwork apps/members/schedules/...).`).action(async (method, path4, opts, command) => {
19755
20061
  const useJson = shouldOutputJson(command.optsWithGlobals().json);
19756
20062
  const credentials = requireAuth();
19757
20063
  const client = new ApiClient(credentials);
19758
20064
  let finalMethod = method;
19759
- let finalPath = path2;
20065
+ let finalPath = path4;
19760
20066
  const headers = {};
19761
20067
  let body;
19762
20068
  const query = opts.query;
@@ -19833,8 +20139,8 @@ init_subprocess();
19833
20139
  init_store();
19834
20140
  init_client();
19835
20141
  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";
20142
+ import { existsSync as existsSync46, readFileSync as readFileSync38 } from "fs";
20143
+ import { join as join42, sep as sep4 } from "path";
19838
20144
  import { homedir as homedir22, platform as osPlatform2, arch as osArch } from "os";
19839
20145
  init_http();
19840
20146
  init_preflight();
@@ -19866,8 +20172,8 @@ function buildContext() {
19866
20172
  const credentials = getCredentials();
19867
20173
  const client = credentials ? new ApiClient(credentials) : null;
19868
20174
  let config = null;
19869
- const configPath = join40(process.cwd(), ".runwork.json");
19870
- if (existsSync45(configPath)) {
20175
+ const configPath = join42(process.cwd(), ".runwork.json");
20176
+ if (existsSync46(configPath)) {
19871
20177
  try {
19872
20178
  config = JSON.parse(readFileSync38(configPath, "utf-8"));
19873
20179
  } catch {}
@@ -19971,8 +20277,8 @@ async function checkCliArtifactReachable() {
19971
20277
  async function checkCliInstallLocation() {
19972
20278
  const isWindows2 = osPlatform2() === "win32";
19973
20279
  const home = homedir22();
19974
- const canonicalDir = join40(home, ".runwork", "bin");
19975
- const canonicalBinary = isWindows2 ? join40(canonicalDir, "runwork.exe") : join40(canonicalDir, "runwork");
20280
+ const canonicalDir = join42(home, ".runwork", "bin");
20281
+ const canonicalBinary = isWindows2 ? join42(canonicalDir, "runwork.exe") : join42(canonicalDir, "runwork");
19976
20282
  const candidates = [process.execPath, process.argv[1] || ""].filter(Boolean);
19977
20283
  const runsFromCanonical = candidates.some((p) => normalizePath(p) === normalizePath(canonicalBinary));
19978
20284
  if (runsFromCanonical) {
@@ -19982,7 +20288,7 @@ async function checkCliInstallLocation() {
19982
20288
  message: `canonical (${canonicalBinary})`
19983
20289
  };
19984
20290
  }
19985
- if (existsSync45(canonicalBinary)) {
20291
+ if (existsSync46(canonicalBinary)) {
19986
20292
  return {
19987
20293
  name: "cli-install-location",
19988
20294
  status: "warn",
@@ -20104,8 +20410,8 @@ async function checkGitCredentialHelper(ctx) {
20104
20410
  };
20105
20411
  }
20106
20412
  async function checkProjectConfig(ctx) {
20107
- const configPath = join40(ctx.cwd, ".runwork.json");
20108
- if (!existsSync45(configPath)) {
20413
+ const configPath = join42(ctx.cwd, ".runwork.json");
20414
+ if (!existsSync46(configPath)) {
20109
20415
  if (!ctx.credentials) {
20110
20416
  return { name: "project-config", status: "skip", message: "no project (not logged in)" };
20111
20417
  }
@@ -20167,7 +20473,7 @@ async function checkGitRemote(ctx) {
20167
20473
  if (!ctx.config) {
20168
20474
  return { name: "git-remote", status: "skip", message: "skipped (no project)" };
20169
20475
  }
20170
- if (!existsSync45(join40(ctx.cwd, ".git"))) {
20476
+ if (!existsSync46(join42(ctx.cwd, ".git"))) {
20171
20477
  return {
20172
20478
  name: "git-remote",
20173
20479
  status: "fail",
@@ -20221,10 +20527,10 @@ async function checkDeployFreshness(ctx) {
20221
20527
  return { name: "deploy-freshness", status: "skip", message: "local HEAD unknown" };
20222
20528
  }
20223
20529
  function loadSetupState5() {
20224
- const projectPath = join40(process.cwd(), ".runwork", "setup.json");
20225
- const userPath = join40(homedir22(), ".runwork", "setup.json");
20530
+ const projectPath = join42(process.cwd(), ".runwork", "setup.json");
20531
+ const userPath = join42(homedir22(), ".runwork", "setup.json");
20226
20532
  for (const p of [projectPath, userPath]) {
20227
- if (existsSync45(p)) {
20533
+ if (existsSync46(p)) {
20228
20534
  try {
20229
20535
  return JSON.parse(readFileSync38(p, "utf-8"));
20230
20536
  } catch {
@@ -20241,8 +20547,8 @@ async function checkCodexNetwork() {
20241
20547
  if (!state || !state.configuredAgents.includes("codex")) {
20242
20548
  return { name, status: "skip", message: "Codex not configured for Runwork" };
20243
20549
  }
20244
- const configPath = join40(homedir22(), ".codex", "config.toml");
20245
- if (!existsSync45(configPath)) {
20550
+ const configPath = join42(homedir22(), ".codex", "config.toml");
20551
+ if (!existsSync46(configPath)) {
20246
20552
  return { name, status: "skip", message: "no Codex config found" };
20247
20553
  }
20248
20554
  let parsed;
@@ -20300,8 +20606,8 @@ async function checkCodexDesktopProject() {
20300
20606
  if (!usesCodex) {
20301
20607
  return { name, status: "skip", message: "Codex not configured for Runwork" };
20302
20608
  }
20303
- const statePath2 = join40(homedir22(), ".codex", ".codex-global-state.json");
20304
- if (!existsSync45(statePath2)) {
20609
+ const statePath2 = join42(homedir22(), ".codex", ".codex-global-state.json");
20610
+ if (!existsSync46(statePath2)) {
20305
20611
  return { name, status: "skip", message: "Codex desktop app not detected" };
20306
20612
  }
20307
20613
  let savedRoots = [];
@@ -20312,7 +20618,7 @@ async function checkCodexDesktopProject() {
20312
20618
  } catch {
20313
20619
  return { name, status: "warn", message: "could not read Codex desktop state" };
20314
20620
  }
20315
- const runworkDir = join40(homedir22(), ".runwork");
20621
+ const runworkDir = join42(homedir22(), ".runwork");
20316
20622
  if (savedRoots.includes(runworkDir)) {
20317
20623
  return { name, status: "pass", message: "Runwork project added to Codex desktop sidebar" };
20318
20624
  }
@@ -20365,7 +20671,7 @@ async function checkAgentSetup() {
20365
20671
  if (!adapter2 || !adapter2.supportsMcpScope("user"))
20366
20672
  continue;
20367
20673
  const mcpConfigPath = getMcpConfigPath2(slug, "user");
20368
- if (mcpConfigPath && existsSync45(mcpConfigPath)) {
20674
+ if (mcpConfigPath && existsSync46(mcpConfigPath)) {
20369
20675
  try {
20370
20676
  const content = readFileSync38(mcpConfigPath, "utf-8");
20371
20677
  const missingMcp = state.mcpServers.filter((name) => !content.includes(name));
@@ -20390,8 +20696,8 @@ async function checkAgentSetup() {
20390
20696
  if (!skillsDir)
20391
20697
  continue;
20392
20698
  const missingSkills = state.skills.filter((name) => {
20393
- const skillPath = join40(skillsDir, name, "SKILL.md");
20394
- return !existsSync45(skillPath);
20699
+ const skillPath = join42(skillsDir, name, "SKILL.md");
20700
+ return !existsSync46(skillPath);
20395
20701
  });
20396
20702
  if (missingSkills.length > 0) {
20397
20703
  details.push(`${missingSkills.length} skill(s) missing from ${slug}`);
@@ -20419,16 +20725,16 @@ function getMcpConfigPath2(slug, scope) {
20419
20725
  const home = homedir22();
20420
20726
  switch (slug) {
20421
20727
  case "claude-code":
20422
- return scope === "project" ? join40(process.cwd(), ".mcp.json") : join40(home, ".claude", "settings.json");
20728
+ return scope === "project" ? join42(process.cwd(), ".mcp.json") : join42(home, ".claude", "settings.json");
20423
20729
  case "cursor":
20424
- return scope === "project" ? join40(process.cwd(), ".cursor", "mcp.json") : join40(home, ".cursor", "mcp.json");
20730
+ return scope === "project" ? join42(process.cwd(), ".cursor", "mcp.json") : join42(home, ".cursor", "mcp.json");
20425
20731
  case "windsurf":
20426
- return scope === "project" ? join40(process.cwd(), ".windsurf", "mcp.json") : join40(home, ".windsurf", "mcp.json");
20732
+ return scope === "project" ? join42(process.cwd(), ".windsurf", "mcp.json") : join42(home, ".windsurf", "mcp.json");
20427
20733
  case "codex":
20428
20734
  case "codex-app":
20429
- return scope === "user" ? join40(home, ".codex", "config.toml") : null;
20735
+ return scope === "user" ? join42(home, ".codex", "config.toml") : null;
20430
20736
  case "gemini":
20431
- return scope === "user" ? join40(home, ".gemini", "settings.json") : null;
20737
+ return scope === "user" ? join42(home, ".gemini", "settings.json") : null;
20432
20738
  default:
20433
20739
  return null;
20434
20740
  }
@@ -20437,12 +20743,12 @@ function getSkillsDir(slug, scope) {
20437
20743
  const home = homedir22();
20438
20744
  switch (slug) {
20439
20745
  case "claude-code":
20440
- return scope === "project" ? join40(process.cwd(), ".claude", "skills") : join40(home, ".claude", "skills");
20746
+ return scope === "project" ? join42(process.cwd(), ".claude", "skills") : join42(home, ".claude", "skills");
20441
20747
  case "codex":
20442
20748
  case "codex-app":
20443
- return scope === "project" ? join40(process.cwd(), ".agents", "skills") : join40(home, ".agents", "skills");
20749
+ return scope === "project" ? join42(process.cwd(), ".agents", "skills") : join42(home, ".agents", "skills");
20444
20750
  case "gemini":
20445
- return scope === "project" ? join40(process.cwd(), ".gemini", "skills") : join40(home, ".gemini", "skills");
20751
+ return scope === "project" ? join42(process.cwd(), ".gemini", "skills") : join42(home, ".gemini", "skills");
20446
20752
  default:
20447
20753
  return null;
20448
20754
  }
@@ -20494,8 +20800,8 @@ async function runAllChecks(options) {
20494
20800
  // src/health/fix.ts
20495
20801
  init_credentials();
20496
20802
  init_remote();
20497
- import { existsSync as existsSync46 } from "fs";
20498
- import { join as join41 } from "path";
20803
+ import { existsSync as existsSync47 } from "fs";
20804
+ import { join as join43 } from "path";
20499
20805
  async function applyDoctorFixes(ctx, failingNames) {
20500
20806
  const failing = new Set(failingNames);
20501
20807
  const outcomes = [];
@@ -20522,7 +20828,7 @@ async function applyDoctorFixes(ctx, failingNames) {
20522
20828
  applied: false,
20523
20829
  message: "no project config -- run inside an app directory"
20524
20830
  });
20525
- } else if (!existsSync46(join41(ctx.cwd, ".git"))) {
20831
+ } else if (!existsSync47(join43(ctx.cwd, ".git"))) {
20526
20832
  outcomes.push({
20527
20833
  name: "git-remote",
20528
20834
  applied: false,
@@ -20541,10 +20847,10 @@ async function applyDoctorFixes(ctx, failingNames) {
20541
20847
  }
20542
20848
 
20543
20849
  // src/agents/runtime-detection.ts
20544
- import { existsSync as existsSync47, readFileSync as readFileSync39, statSync as statSync7, readdirSync as readdirSync13 } from "fs";
20850
+ import { existsSync as existsSync48, readFileSync as readFileSync39, statSync as statSync8, readdirSync as readdirSync13 } from "fs";
20545
20851
  import { homedir as homedir23 } from "os";
20546
- import { join as join42 } from "path";
20547
- var RUNWORK_SESSIONS_DIR = join42(homedir23(), ".runwork", "sessions");
20852
+ import { join as join44 } from "path";
20853
+ var RUNWORK_SESSIONS_DIR = join44(homedir23(), ".runwork", "sessions");
20548
20854
  function detectCurrentAgent() {
20549
20855
  const claudeCodeSessionId = process.env.CLAUDE_CODE_SESSION_ID;
20550
20856
  if (claudeCodeSessionId) {
@@ -20607,11 +20913,11 @@ function detectCurrentAgent() {
20607
20913
  return null;
20608
20914
  }
20609
20915
  function readHookSessionInfo(sessionId) {
20610
- const path2 = join42(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
20611
- if (!existsSync47(path2))
20916
+ const path4 = join44(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
20917
+ if (!existsSync48(path4))
20612
20918
  return null;
20613
20919
  try {
20614
- const raw = readFileSync39(path2, "utf8");
20920
+ const raw = readFileSync39(path4, "utf8");
20615
20921
  const parsed = JSON.parse(raw);
20616
20922
  return parsed;
20617
20923
  } catch {
@@ -20619,8 +20925,8 @@ function readHookSessionInfo(sessionId) {
20619
20925
  }
20620
20926
  }
20621
20927
  function findClaudeCodeSessionFile(sessionId) {
20622
- const root = join42(homedir23(), ".claude", "projects");
20623
- if (!existsSync47(root))
20928
+ const root = join44(homedir23(), ".claude", "projects");
20929
+ if (!existsSync48(root))
20624
20930
  return null;
20625
20931
  let projectDirs;
20626
20932
  try {
@@ -20629,15 +20935,15 @@ function findClaudeCodeSessionFile(sessionId) {
20629
20935
  return null;
20630
20936
  }
20631
20937
  for (const dir of projectDirs) {
20632
- const candidate = join42(root, dir, `${sessionId}.jsonl`);
20633
- if (existsSync47(candidate))
20938
+ const candidate = join44(root, dir, `${sessionId}.jsonl`);
20939
+ if (existsSync48(candidate))
20634
20940
  return candidate;
20635
20941
  }
20636
20942
  return null;
20637
20943
  }
20638
20944
  function findCodexRolloutFile(threadId) {
20639
- const root = join42(homedir23(), ".codex", "sessions");
20640
- if (!existsSync47(root))
20945
+ const root = join44(homedir23(), ".codex", "sessions");
20946
+ if (!existsSync48(root))
20641
20947
  return null;
20642
20948
  const stack = [root];
20643
20949
  while (stack.length > 0) {
@@ -20649,10 +20955,10 @@ function findCodexRolloutFile(threadId) {
20649
20955
  continue;
20650
20956
  }
20651
20957
  for (const entry of entries) {
20652
- const full = join42(dir, entry);
20958
+ const full = join44(dir, entry);
20653
20959
  let s;
20654
20960
  try {
20655
- s = statSync7(full);
20961
+ s = statSync8(full);
20656
20962
  } catch {
20657
20963
  continue;
20658
20964
  }
@@ -20666,8 +20972,8 @@ function findCodexRolloutFile(threadId) {
20666
20972
  return null;
20667
20973
  }
20668
20974
  function findNewestClaudeCodeSession() {
20669
- const root = join42(homedir23(), ".claude", "projects");
20670
- if (!existsSync47(root))
20975
+ const root = join44(homedir23(), ".claude", "projects");
20976
+ if (!existsSync48(root))
20671
20977
  return null;
20672
20978
  let projectDirs;
20673
20979
  try {
@@ -20677,7 +20983,7 @@ function findNewestClaudeCodeSession() {
20677
20983
  }
20678
20984
  let best = null;
20679
20985
  for (const dir of projectDirs) {
20680
- const projectPath = join42(root, dir);
20986
+ const projectPath = join44(root, dir);
20681
20987
  let files;
20682
20988
  try {
20683
20989
  files = readdirSync13(projectPath);
@@ -20687,9 +20993,9 @@ function findNewestClaudeCodeSession() {
20687
20993
  for (const file of files) {
20688
20994
  if (!file.endsWith(".jsonl"))
20689
20995
  continue;
20690
- const full = join42(projectPath, file);
20996
+ const full = join44(projectPath, file);
20691
20997
  try {
20692
- const s = statSync7(full);
20998
+ const s = statSync8(full);
20693
20999
  if (!best || s.mtimeMs > best.mtime) {
20694
21000
  best = {
20695
21001
  sessionId: file.replace(/\.jsonl$/, ""),
@@ -20705,8 +21011,8 @@ function findNewestClaudeCodeSession() {
20705
21011
  return best ? { sessionId: best.sessionId, path: best.path } : null;
20706
21012
  }
20707
21013
  function findNewestCodexRollout() {
20708
- const root = join42(homedir23(), ".codex", "sessions");
20709
- if (!existsSync47(root))
21014
+ const root = join44(homedir23(), ".codex", "sessions");
21015
+ if (!existsSync48(root))
20710
21016
  return null;
20711
21017
  const stack = [root];
20712
21018
  let best = null;
@@ -20719,10 +21025,10 @@ function findNewestCodexRollout() {
20719
21025
  continue;
20720
21026
  }
20721
21027
  for (const entry of entries) {
20722
- const full = join42(dir, entry);
21028
+ const full = join44(dir, entry);
20723
21029
  let s;
20724
21030
  try {
20725
- s = statSync7(full);
21031
+ s = statSync8(full);
20726
21032
  } catch {
20727
21033
  continue;
20728
21034
  }
@@ -20950,7 +21256,7 @@ var doctorCommand = new Command31("doctor").description("Check system health: au
20950
21256
  init_store();
20951
21257
  init_client();
20952
21258
  import { Command as Command32 } from "commander";
20953
- import { readFileSync as readFileSync40, existsSync as existsSync48 } from "fs";
21259
+ import { readFileSync as readFileSync40, existsSync as existsSync49 } from "fs";
20954
21260
  import { createHash as createHash4 } from "crypto";
20955
21261
  function nativeBundleFormatForAgent(slug) {
20956
21262
  if (slug === "claude-code" || slug === "claude-desktop")
@@ -20971,7 +21277,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
20971
21277
  console.error("Error: --transcript-file is required. Pass the path to the LLM-emitted markdown transcript.");
20972
21278
  process.exit(1);
20973
21279
  }
20974
- if (!existsSync48(opts.transcriptFile)) {
21280
+ if (!existsSync49(opts.transcriptFile)) {
20975
21281
  console.error(`Error: transcript file does not exist: ${opts.transcriptFile}`);
20976
21282
  process.exit(1);
20977
21283
  }
@@ -21005,12 +21311,12 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
21005
21311
  const sourceAgent = opts.sourceAgent ?? detected?.slug ?? "generic";
21006
21312
  let nativeFilePath = null;
21007
21313
  if (opts.nativeFile) {
21008
- if (!existsSync48(opts.nativeFile)) {
21314
+ if (!existsSync49(opts.nativeFile)) {
21009
21315
  console.error(`Error: --native-file path does not exist: ${opts.nativeFile}`);
21010
21316
  process.exit(1);
21011
21317
  }
21012
21318
  nativeFilePath = opts.nativeFile;
21013
- } else if (detected?.sessionFilePath && existsSync48(detected.sessionFilePath)) {
21319
+ } else if (detected?.sessionFilePath && existsSync49(detected.sessionFilePath)) {
21014
21320
  nativeFilePath = detected.sessionFilePath;
21015
21321
  }
21016
21322
  if (nativeFilePath) {
@@ -21139,9 +21445,9 @@ Shared conversations (${scope}, ${total}):
21139
21445
  init_store();
21140
21446
  init_client();
21141
21447
  import { Command as Command35 } from "commander";
21142
- import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync28, realpathSync } from "fs";
21448
+ import { writeFileSync as writeFileSync32, mkdirSync as mkdirSync29, realpathSync } from "fs";
21143
21449
  import { homedir as homedir24 } from "os";
21144
- import { join as join43 } from "path";
21450
+ import { join as join45 } from "path";
21145
21451
  import { spawn as spawn5 } from "child_process";
21146
21452
  function encodeClaudeCodeCwd(cwd) {
21147
21453
  let canonical;
@@ -21178,10 +21484,10 @@ function extractCodexUuid(rolloutContent) {
21178
21484
  }
21179
21485
  function placeClaudeJsonl(uuid, content, recipientCwd) {
21180
21486
  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);
21487
+ const projectDir = join45(homedir24(), ".claude", "projects", encoded);
21488
+ mkdirSync29(projectDir, { recursive: true });
21489
+ const placedAt = join45(projectDir, `${uuid}.jsonl`);
21490
+ writeFileSync32(placedAt, content);
21185
21491
  return { placedAt, runFromCwd: recipientCwd };
21186
21492
  }
21187
21493
  function placeCodexRollout(uuid, content) {
@@ -21189,11 +21495,11 @@ function placeCodexRollout(uuid, content) {
21189
21495
  const yyyy = String(now.getUTCFullYear());
21190
21496
  const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
21191
21497
  const dd = String(now.getUTCDate()).padStart(2, "0");
21192
- const dir = join43(homedir24(), ".codex", "sessions", yyyy, mm, dd);
21193
- mkdirSync28(dir, { recursive: true });
21498
+ const dir = join45(homedir24(), ".codex", "sessions", yyyy, mm, dd);
21499
+ mkdirSync29(dir, { recursive: true });
21194
21500
  const ts = now.toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
21195
- const placedAt = join43(dir, `rollout-${ts}-${uuid}.jsonl`);
21196
- writeFileSync31(placedAt, content);
21501
+ const placedAt = join45(dir, `rollout-${ts}-${uuid}.jsonl`);
21502
+ writeFileSync32(placedAt, content);
21197
21503
  return { placedAt };
21198
21504
  }
21199
21505
  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.0",
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)",