reallink-cli 0.1.14 → 0.1.16

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.
@@ -1,5 +1,5 @@
1
1
  use anyhow::Result;
2
- use clap::{ArgAction, Args, Subcommand};
2
+ use clap::{ArgAction, Args, Subcommand, ValueEnum};
3
3
  use serde::{Deserialize, Serialize};
4
4
  use std::path::PathBuf;
5
5
 
@@ -74,6 +74,15 @@ pub(crate) enum LinkCommands {
74
74
  #[command(subcommand)]
75
75
  command: LinkPluginCommands,
76
76
  },
77
+ /// Register a local source folder for a project
78
+ Source(LinkSourceArgs),
79
+ /// Connect to Reallink and bridge local source to agents
80
+ Connect(LinkConnectArgs),
81
+ /// Manage P2P signaling sessions for direct CLI-to-CLI transports
82
+ P2p {
83
+ #[command(subcommand)]
84
+ command: LinkP2PCommands,
85
+ },
77
86
  }
78
87
 
79
88
  #[derive(Subcommand)]
@@ -82,6 +91,15 @@ pub(crate) enum LinkPluginCommands {
82
91
  List(LinkPluginListArgs),
83
92
  }
84
93
 
94
+ #[derive(Subcommand)]
95
+ pub(crate) enum LinkP2PCommands {
96
+ Create(LinkP2PCreateArgs),
97
+ List(LinkP2PListArgs),
98
+ Get(LinkP2PGetArgs),
99
+ Wait(LinkP2PWaitArgs),
100
+ Signal(LinkP2PSignalArgs),
101
+ }
102
+
85
103
  #[derive(Args)]
86
104
  pub(crate) struct LinkUnrealArgs {
87
105
  #[arg(long, help = "Remote Reallink project id to bind")]
@@ -247,6 +265,200 @@ pub(crate) struct LinkPluginListArgs {
247
265
  pub index_path: String,
248
266
  }
249
267
 
268
+ // ---------------------------------------------------------------------------
269
+ // Source link args
270
+ // ---------------------------------------------------------------------------
271
+
272
+ #[derive(Args)]
273
+ pub(crate) struct LinkSourceArgs {
274
+ #[arg(long, help = "Project ID to bind the source folder to")]
275
+ pub project_id: String,
276
+ #[arg(long, help = "Local directory path containing source files")]
277
+ pub path: PathBuf,
278
+ #[arg(
279
+ long,
280
+ default_value = "project",
281
+ help = "Label for this folder (project, engine, etc.)"
282
+ )]
283
+ pub label: String,
284
+ #[arg(long)]
285
+ pub base_url: Option<String>,
286
+ }
287
+
288
+ #[derive(Args)]
289
+ pub(crate) struct LinkConnectArgs {
290
+ #[arg(long, help = "Project ID to connect. Uses default if omitted")]
291
+ pub project_id: Option<String>,
292
+ #[arg(
293
+ long,
294
+ help = "Stable workspace identifier for this linked client session"
295
+ )]
296
+ pub workspace_id: Option<String>,
297
+ #[arg(long, help = "Push file index + key source files to R2 on connect")]
298
+ pub sync: bool,
299
+ #[arg(
300
+ long,
301
+ default_value = "websocket",
302
+ help = "Transport used by this linked client session"
303
+ )]
304
+ pub transport: String,
305
+ #[arg(long, help = "Connect service URL override")]
306
+ pub connect_url: Option<String>,
307
+ #[arg(long)]
308
+ pub base_url: Option<String>,
309
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
310
+ pub access_token: Option<String>,
311
+ }
312
+
313
+ #[derive(Clone, Debug, ValueEnum)]
314
+ pub(crate) enum LinkP2PRole {
315
+ Agent,
316
+ Client,
317
+ }
318
+
319
+ impl LinkP2PRole {
320
+ pub(crate) fn as_api_str(&self) -> &'static str {
321
+ match self {
322
+ Self::Agent => "agent",
323
+ Self::Client => "client",
324
+ }
325
+ }
326
+ }
327
+
328
+ #[derive(Clone, Debug, ValueEnum)]
329
+ pub(crate) enum LinkP2PSignalType {
330
+ Offer,
331
+ Answer,
332
+ Candidate,
333
+ Ready,
334
+ }
335
+
336
+ impl LinkP2PSignalType {
337
+ pub(crate) fn as_api_str(&self) -> &'static str {
338
+ match self {
339
+ Self::Offer => "offer",
340
+ Self::Answer => "answer",
341
+ Self::Candidate => "candidate",
342
+ Self::Ready => "ready",
343
+ }
344
+ }
345
+ }
346
+
347
+ #[derive(Args)]
348
+ pub(crate) struct LinkP2PCreateArgs {
349
+ #[arg(long, help = "Project ID to attach the P2P session to")]
350
+ pub project_id: String,
351
+ #[arg(long, help = "Stable workspace identifier for this P2P session")]
352
+ pub workspace_id: Option<String>,
353
+ #[arg(
354
+ long,
355
+ help = "Optional source clientId already registered under the workspace"
356
+ )]
357
+ pub client_id: Option<String>,
358
+ #[arg(long, help = "Optional peer clientId expected to join this session")]
359
+ pub peer_client_id: Option<String>,
360
+ #[arg(long, help = "Session TTL in seconds")]
361
+ pub ttl_seconds: Option<u64>,
362
+ #[arg(
363
+ long,
364
+ help = "Inline JSON object or @path/to/file.json with additional metadata"
365
+ )]
366
+ pub metadata: Option<String>,
367
+ #[arg(long)]
368
+ pub base_url: Option<String>,
369
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
370
+ pub access_token: Option<String>,
371
+ }
372
+
373
+ #[derive(Args)]
374
+ pub(crate) struct LinkP2PGetArgs {
375
+ #[arg(long, help = "Project ID owning the P2P session")]
376
+ pub project_id: String,
377
+ #[arg(long, help = "P2P session identifier")]
378
+ pub session_id: String,
379
+ #[arg(long)]
380
+ pub base_url: Option<String>,
381
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
382
+ pub access_token: Option<String>,
383
+ }
384
+
385
+ #[derive(Args)]
386
+ pub(crate) struct LinkP2PListArgs {
387
+ #[arg(long, help = "Project ID owning the P2P sessions")]
388
+ pub project_id: String,
389
+ #[arg(long)]
390
+ pub workspace_id: Option<String>,
391
+ #[arg(long)]
392
+ pub client_id: Option<String>,
393
+ #[arg(long)]
394
+ pub status: Option<String>,
395
+ #[arg(long, default_value_t = 50)]
396
+ pub limit: u32,
397
+ #[arg(long)]
398
+ pub base_url: Option<String>,
399
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
400
+ pub access_token: Option<String>,
401
+ }
402
+
403
+ #[derive(Args)]
404
+ pub(crate) struct LinkP2PWaitArgs {
405
+ #[arg(long, help = "Project ID owning the P2P session")]
406
+ pub project_id: String,
407
+ #[arg(long, help = "P2P session identifier")]
408
+ pub session_id: String,
409
+ #[arg(long, default_value = "ready")]
410
+ pub status: String,
411
+ #[arg(long, default_value_t = 30_000)]
412
+ pub timeout_ms: u64,
413
+ #[arg(long, default_value_t = 1_000)]
414
+ pub poll_interval_ms: u64,
415
+ #[arg(long)]
416
+ pub base_url: Option<String>,
417
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
418
+ pub access_token: Option<String>,
419
+ }
420
+
421
+ #[derive(Args)]
422
+ pub(crate) struct LinkP2PSignalArgs {
423
+ #[arg(long, help = "Project ID owning the P2P session")]
424
+ pub project_id: String,
425
+ #[arg(long, help = "P2P session identifier")]
426
+ pub session_id: String,
427
+ #[arg(long, value_enum)]
428
+ pub role: LinkP2PRole,
429
+ #[arg(long = "signal-type", value_enum)]
430
+ pub signal_type: LinkP2PSignalType,
431
+ #[arg(
432
+ long,
433
+ help = "Inline JSON object or @path/to/file.json carrying the signal payload"
434
+ )]
435
+ pub payload: String,
436
+ #[arg(long, help = "Idempotency key for this signal")]
437
+ pub signal_id: Option<String>,
438
+ #[arg(long, help = "Optional registered clientId originating this signal")]
439
+ pub from_client_id: Option<String>,
440
+ #[arg(long)]
441
+ pub base_url: Option<String>,
442
+ #[arg(long, help = "Bearer token override for agent/API-token usage")]
443
+ pub access_token: Option<String>,
444
+ }
445
+
446
+ #[derive(Debug, Serialize, Deserialize, Clone)]
447
+ #[serde(rename_all = "camelCase")]
448
+ pub(crate) struct SourceLinkRecord {
449
+ pub project_id: String,
450
+ pub folder_path: String,
451
+ pub folder_label: String,
452
+ pub created_at_epoch_ms: u128,
453
+ }
454
+
455
+ #[derive(Debug, Serialize, Deserialize, Clone, Default)]
456
+ #[serde(rename_all = "camelCase")]
457
+ pub(crate) struct SourceLinksConfig {
458
+ pub version: u32,
459
+ pub links: Vec<SourceLinkRecord>,
460
+ }
461
+
250
462
  pub(crate) async fn dispatch(client: &reqwest::Client, command: LinkCommands) -> Result<()> {
251
463
  match command {
252
464
  LinkCommands::Unreal(args) => crate::link_unreal_command(client, args).await?,
@@ -258,9 +470,20 @@ pub(crate) async fn dispatch(client: &reqwest::Client, command: LinkCommands) ->
258
470
  LinkCommands::Open(args) => crate::link_open_command(args).await?,
259
471
  LinkCommands::Run(args) => crate::link_run_command(args).await?,
260
472
  LinkCommands::Plugin { command } => match command {
261
- LinkPluginCommands::Install(args) => crate::link_plugin_install_command(client, args).await?,
473
+ LinkPluginCommands::Install(args) => {
474
+ crate::link_plugin_install_command(client, args).await?
475
+ }
262
476
  LinkPluginCommands::List(args) => crate::link_plugin_list_command(client, args).await?,
263
477
  },
478
+ LinkCommands::Source(args) => crate::link_source_command(client, args).await?,
479
+ LinkCommands::Connect(args) => crate::link_connect_command(client, args).await?,
480
+ LinkCommands::P2p { command } => match command {
481
+ LinkP2PCommands::Create(args) => crate::link_p2p_create_command(client, args).await?,
482
+ LinkP2PCommands::List(args) => crate::link_p2p_list_command(client, args).await?,
483
+ LinkP2PCommands::Get(args) => crate::link_p2p_get_command(client, args).await?,
484
+ LinkP2PCommands::Wait(args) => crate::link_p2p_wait_command(client, args).await?,
485
+ LinkP2PCommands::Signal(args) => crate::link_p2p_signal_command(client, args).await?,
486
+ },
264
487
  }
265
488
  Ok(())
266
489
  }
@@ -25,7 +25,7 @@ if (process.env.REALLINK_SKIP_BUILD === "1") {
25
25
  process.exit(0);
26
26
  }
27
27
 
28
- if (hasReleaseBinary() || fs.existsSync(prebuiltBinaryPath)) {
28
+ if (process.env.REALLINK_FORCE_BUILD !== "1" && (hasReleaseBinary() || fs.existsSync(prebuiltBinaryPath))) {
29
29
  process.exit(0);
30
30
  }
31
31
 
Binary file