replicas-cli 0.2.120 → 0.2.122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  GITHUB_TRIGGER,
4
+ MEDIA_KIND,
5
+ MEDIA_KINDS,
4
6
  REPLICAS_CONFIG_FILENAMES,
5
7
  SANDBOX_PATHS,
6
8
  deleteConfig,
@@ -8,6 +10,7 @@ import {
8
10
  getIdeCommand,
9
11
  getOrganizationId,
10
12
  getValidToken,
13
+ getWorkspaceDashboardUrl,
11
14
  isAgentMode,
12
15
  isAuthenticated,
13
16
  parseAgentEvents,
@@ -16,7 +19,8 @@ import {
16
19
  setIdeCommand,
17
20
  setOrganizationId,
18
21
  writeConfig
19
- } from "./chunk-4WSV5CLV.mjs";
22
+ } from "./chunk-BY7XUH2G.mjs";
23
+ import "./chunk-FFDYI4OH.mjs";
20
24
 
21
25
  // src/index.ts
22
26
  import "dotenv/config";
@@ -87,8 +91,8 @@ async function orgAuthenticatedFetch(url, options) {
87
91
  }
88
92
  const headers = {
89
93
  "Authorization": `Bearer ${token}`,
90
- "Replicas-Org-Id": organizationId,
91
94
  "Content-Type": "application/json",
95
+ "Replicas-Org-Id": organizationId,
92
96
  ...options?.headers || {}
93
97
  };
94
98
  const absoluteUrl = `${MONOLITH_URL}${url}`;
@@ -2304,21 +2308,24 @@ import chalk17 from "chalk";
2304
2308
  // src/lib/agent-api.ts
2305
2309
  var MONOLITH_URL3 = process.env.MONOLITH_URL || process.env.REPLICAS_MONOLITH_URL || "https://api.replicas.dev";
2306
2310
  var ENGINE_PORT = process.env.REPLICAS_ENGINE_PORT || "3737";
2307
- async function agentFetch(path4, options) {
2311
+ async function agentFetch(path5, options) {
2308
2312
  const config2 = readAgentConfig();
2309
2313
  if (!config2) {
2310
2314
  throw new Error("Agent mode config not found");
2311
2315
  }
2316
+ const isFormData = options?.body instanceof FormData;
2312
2317
  const headers = {
2313
2318
  "Authorization": `Bearer ${config2.engine_secret}`,
2314
2319
  "X-Workspace-Id": config2.workspace_id,
2315
- "Content-Type": "application/json",
2320
+ // FormData sets its own multipart Content-Type with boundary.
2321
+ ...isFormData ? {} : { "Content-Type": "application/json" },
2316
2322
  ...options?.headers || {}
2317
2323
  };
2318
- const response = await fetch(`${MONOLITH_URL3}${path4}`, {
2324
+ const body = options?.body === void 0 ? void 0 : isFormData ? options.body : JSON.stringify(options.body);
2325
+ const response = await fetch(`${MONOLITH_URL3}${path5}`, {
2319
2326
  ...options,
2320
2327
  headers,
2321
- body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0
2328
+ body
2322
2329
  });
2323
2330
  if (!response.ok) {
2324
2331
  const error = await response.json().catch(() => ({ error: "Request failed" }));
@@ -2326,7 +2333,7 @@ async function agentFetch(path4, options) {
2326
2333
  }
2327
2334
  return response.json();
2328
2335
  }
2329
- async function engineFetch(path4, options) {
2336
+ async function engineFetch(path5, options) {
2330
2337
  const config2 = readAgentConfig();
2331
2338
  if (!config2) {
2332
2339
  throw new Error("Agent mode config not found");
@@ -2336,7 +2343,7 @@ async function engineFetch(path4, options) {
2336
2343
  "Content-Type": "application/json",
2337
2344
  ...options?.headers || {}
2338
2345
  };
2339
- const response = await fetch(`http://localhost:${ENGINE_PORT}${path4}`, {
2346
+ const response = await fetch(`http://localhost:${ENGINE_PORT}${path5}`, {
2340
2347
  ...options,
2341
2348
  headers,
2342
2349
  body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0
@@ -2405,6 +2412,76 @@ async function previewAddCommand(workspaceId, options) {
2405
2412
  console.log(chalk17.green(`Preview created: ${result.preview.publicUrl}`));
2406
2413
  }
2407
2414
 
2415
+ // src/commands/media.ts
2416
+ import fs3 from "fs";
2417
+ import path4 from "path";
2418
+ var MONOLITH_URL4 = process.env.MONOLITH_URL || process.env.REPLICAS_MONOLITH_URL || "https://api.replicas.dev";
2419
+ var EXT_INFO = {
2420
+ png: { kind: MEDIA_KIND.IMAGE, contentType: "image/png" },
2421
+ jpg: { kind: MEDIA_KIND.IMAGE, contentType: "image/jpeg" },
2422
+ jpeg: { kind: MEDIA_KIND.IMAGE, contentType: "image/jpeg" },
2423
+ webp: { kind: MEDIA_KIND.IMAGE, contentType: "image/webp" },
2424
+ svg: { kind: MEDIA_KIND.IMAGE, contentType: "image/svg+xml" },
2425
+ mp4: { kind: MEDIA_KIND.VIDEO, contentType: "video/mp4" },
2426
+ webm: { kind: MEDIA_KIND.VIDEO, contentType: "video/webm" },
2427
+ mp3: { kind: MEDIA_KIND.AUDIO, contentType: "audio/mpeg" },
2428
+ wav: { kind: MEDIA_KIND.AUDIO, contentType: "audio/wav" }
2429
+ };
2430
+ function resolveKind(ext, override) {
2431
+ if (override) {
2432
+ if (!MEDIA_KINDS.includes(override)) {
2433
+ throw new Error(`Invalid kind '${override}'. Must be one of: ${MEDIA_KINDS.join(", ")}`);
2434
+ }
2435
+ return override;
2436
+ }
2437
+ const inferred = EXT_INFO[ext]?.kind;
2438
+ if (!inferred) {
2439
+ throw new Error(`Cannot infer kind from extension '.${ext}'. Pass --kind explicitly.`);
2440
+ }
2441
+ return inferred;
2442
+ }
2443
+ async function mediaUploadCommand(filePath, options) {
2444
+ const absPath = path4.resolve(filePath);
2445
+ if (!fs3.existsSync(absPath)) {
2446
+ throw new Error(`File not found: ${absPath}`);
2447
+ }
2448
+ const stat = fs3.statSync(absPath);
2449
+ if (!stat.isFile()) {
2450
+ throw new Error(`Not a file: ${absPath}`);
2451
+ }
2452
+ if (stat.size === 0) {
2453
+ throw new Error("File is empty");
2454
+ }
2455
+ const fileName = path4.basename(absPath);
2456
+ const ext = path4.extname(absPath).slice(1).toLowerCase();
2457
+ const kind = resolveKind(ext, options.kind);
2458
+ const contentType = EXT_INFO[ext]?.contentType ?? "application/octet-stream";
2459
+ const form = new FormData();
2460
+ form.append("file", new Blob([fs3.readFileSync(absPath)], { type: contentType }), fileName);
2461
+ form.append("kind", kind);
2462
+ if (options.sessionId) form.append("session_id", options.sessionId);
2463
+ const { media } = await agentFetch("/v1/engine/media", {
2464
+ method: "POST",
2465
+ body: form
2466
+ });
2467
+ console.log(`![${fileName}](${MONOLITH_URL4}/v1/media/${media.id})`);
2468
+ const config2 = readAgentConfig();
2469
+ if (config2?.workspace_id) {
2470
+ console.log(`View in Replicas: ${getWorkspaceDashboardUrl(config2.workspace_id, { mode: "media" })}`);
2471
+ }
2472
+ }
2473
+ async function mediaListCommand(options) {
2474
+ const qs = new URLSearchParams();
2475
+ if (options.kind) qs.set("kind", options.kind);
2476
+ if (options.limit) qs.set("limit", options.limit);
2477
+ if (options.page) qs.set("page", options.page);
2478
+ const query = qs.toString() ? `?${qs.toString()}` : "";
2479
+ const { media } = await agentFetch(`/v1/engine/media${query}`);
2480
+ for (const m of media) {
2481
+ console.log(`${MONOLITH_URL4}/v1/media/${m.id} ${m.kind} ${m.size} ${m.created_at}`);
2482
+ }
2483
+ }
2484
+
2408
2485
  // src/commands/interactive.ts
2409
2486
  import chalk18 from "chalk";
2410
2487
  async function interactiveCommand() {
@@ -2420,12 +2497,12 @@ async function interactiveCommand() {
2420
2497
  );
2421
2498
  }
2422
2499
  console.log(chalk18.gray("Starting interactive mode..."));
2423
- const { launchInteractive } = await import("./interactive-YYNEZKZQ.mjs");
2500
+ const { launchInteractive } = await import("./interactive-OHZFZVXH.mjs");
2424
2501
  await launchInteractive();
2425
2502
  }
2426
2503
 
2427
2504
  // src/index.ts
2428
- var CLI_VERSION = "0.2.120";
2505
+ var CLI_VERSION = "0.2.122";
2429
2506
  var program = new Command();
2430
2507
  program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
2431
2508
  program.command("login").description("Authenticate with your Replicas account").action(async () => {
@@ -2838,12 +2915,36 @@ if (isAgentMode()) {
2838
2915
  });
2839
2916
  }
2840
2917
  if (isAgentMode()) {
2841
- const previewCmd = program.commands.find((cmd) => cmd.name() === "preview");
2918
+ const media = program.command("media").description("Share workspace media (screenshots, videos, audio) inline in chat");
2919
+ media.command("upload <file>").description("Upload a screenshot, video, or audio file. Prints a markdown embed for the assistant reply.").option("-k, --kind <kind>", "Media kind: image, video, or audio (inferred from extension if omitted)").option("-s, --session-id <id>", "Session ID to associate the asset with").action(async (file, options) => {
2920
+ try {
2921
+ await mediaUploadCommand(file, options);
2922
+ } catch (error) {
2923
+ if (error instanceof Error) {
2924
+ console.error(chalk19.red(`
2925
+ \u2717 ${error.message}
2926
+ `));
2927
+ }
2928
+ process.exit(1);
2929
+ }
2930
+ });
2931
+ media.command("list").description("List media uploaded for this workspace").option("-k, --kind <kind>", "Filter by kind: image, video, or audio").option("-l, --limit <n>", "Page size (default 50, max 200)").option("-p, --page <n>", "Page number (default 1)").action(async (options) => {
2932
+ try {
2933
+ await mediaListCommand(options);
2934
+ } catch (error) {
2935
+ if (error instanceof Error) {
2936
+ console.error(chalk19.red(`
2937
+ \u2717 ${error.message}
2938
+ `));
2939
+ }
2940
+ process.exit(1);
2941
+ }
2942
+ });
2943
+ const allowed = /* @__PURE__ */ new Set(["preview", "media"]);
2944
+ const kept = program.commands.filter((cmd) => allowed.has(cmd.name()));
2842
2945
  const cmds = program.commands;
2843
2946
  cmds.length = 0;
2844
- if (previewCmd) {
2845
- cmds.push(previewCmd);
2846
- }
2947
+ cmds.push(...kept);
2847
2948
  }
2848
2949
  var versionCheckPromise = checkForUpdates(CLI_VERSION);
2849
2950
  program.parse();
@@ -12,7 +12,8 @@ import {
12
12
  isAgentBackendEvent,
13
13
  parseAgentEvents,
14
14
  parseUserMessage
15
- } from "./chunk-4WSV5CLV.mjs";
15
+ } from "./chunk-BY7XUH2G.mjs";
16
+ import "./chunk-FFDYI4OH.mjs";
16
17
 
17
18
  // src/interactive/index.tsx
18
19
  import { createCliRenderer } from "@opentui/core";