lody 0.67.2 → 0.68.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.
package/dist/index.js CHANGED
@@ -4188,7 +4188,7 @@ let __tla = Promise.all([
4188
4188
  }
4189
4189
  }
4190
4190
  const name$1 = "lody";
4191
- const version$3 = "0.67.2";
4191
+ const version$3 = "0.68.0";
4192
4192
  const description$1 = "Lody Agent CLI tool for managing remote command execution";
4193
4193
  const type$2 = "module";
4194
4194
  const main$4 = "dist/index.js";
@@ -4534,6 +4534,274 @@ let __tla = Promise.all([
4534
4534
  return void 0;
4535
4535
  };
4536
4536
  const isBuiltinAgentType = (agentType) => agentType === "claude" || agentType === "codex";
4537
+ const CODEX_STATIC_MODES = [
4538
+ {
4539
+ id: "read-only",
4540
+ name: "Read-only",
4541
+ description: "Requires approval to edit files and run commands."
4542
+ },
4543
+ {
4544
+ id: "agent",
4545
+ name: "Agent",
4546
+ description: "Read and edit files, and run commands."
4547
+ },
4548
+ {
4549
+ id: "agent-full-access",
4550
+ name: "Agent (full access)",
4551
+ description: "Codex can edit files outside this workspace and run commands with network access. Exercise caution when using."
4552
+ }
4553
+ ];
4554
+ const CODEX_STATIC_MODELS = [
4555
+ {
4556
+ modelId: "gpt-5.5",
4557
+ name: "gpt-5.5",
4558
+ description: "Latest frontier Codex model"
4559
+ },
4560
+ {
4561
+ modelId: "gpt-5.4",
4562
+ name: "gpt-5.4",
4563
+ description: "Frontier Codex model"
4564
+ },
4565
+ {
4566
+ modelId: "gpt-5.4-mini",
4567
+ name: "gpt-5.4-mini",
4568
+ description: "Smaller, faster Codex model"
4569
+ }
4570
+ ];
4571
+ const CODEX_REASONING_OPTIONS = [
4572
+ {
4573
+ value: "low",
4574
+ name: "low",
4575
+ description: "Fastest responses"
4576
+ },
4577
+ {
4578
+ value: "medium",
4579
+ name: "medium",
4580
+ description: "Balanced reasoning"
4581
+ },
4582
+ {
4583
+ value: "high",
4584
+ name: "high",
4585
+ description: "More reasoning for difficult tasks"
4586
+ },
4587
+ {
4588
+ value: "xhigh",
4589
+ name: "xhigh",
4590
+ description: "Extra reasoning for complex tasks"
4591
+ }
4592
+ ];
4593
+ const CODEX_STATIC_CONFIG_OPTIONS = [
4594
+ {
4595
+ id: "mode",
4596
+ name: "Mode",
4597
+ description: "Approval and sandboxing preset for the session",
4598
+ category: "mode",
4599
+ type: "select",
4600
+ currentValue: "agent",
4601
+ options: CODEX_STATIC_MODES.map((mode2) => ({
4602
+ value: mode2.id,
4603
+ name: mode2.name,
4604
+ description: mode2.description ?? void 0
4605
+ }))
4606
+ },
4607
+ {
4608
+ id: "model",
4609
+ name: "Model",
4610
+ description: "Model Codex uses for the session",
4611
+ category: "model",
4612
+ type: "select",
4613
+ currentValue: "gpt-5.5",
4614
+ options: CODEX_STATIC_MODELS.map((model) => ({
4615
+ value: model.modelId,
4616
+ name: model.name,
4617
+ description: model.description ?? void 0
4618
+ }))
4619
+ },
4620
+ {
4621
+ id: "reasoning_effort",
4622
+ name: "Reasoning effort",
4623
+ description: "How much reasoning effort the model should use",
4624
+ category: "thought_level",
4625
+ type: "select",
4626
+ currentValue: "medium",
4627
+ options: CODEX_REASONING_OPTIONS
4628
+ },
4629
+ {
4630
+ id: "fast-mode",
4631
+ name: "Fast mode",
4632
+ description: "1.5x speed, increased usage",
4633
+ category: "fast-mode",
4634
+ type: "select",
4635
+ currentValue: "off",
4636
+ options: [
4637
+ {
4638
+ value: "off",
4639
+ name: "Off",
4640
+ description: "Default speed, normal usage"
4641
+ },
4642
+ {
4643
+ value: "on",
4644
+ name: "On",
4645
+ description: "1.5x speed, increased usage"
4646
+ }
4647
+ ]
4648
+ },
4649
+ {
4650
+ id: "plan-mode",
4651
+ name: "Plan mode",
4652
+ description: "Plan without modifying files; switch off to implement the approved plan",
4653
+ category: "plan-mode",
4654
+ type: "select",
4655
+ currentValue: "off",
4656
+ options: [
4657
+ {
4658
+ value: "off",
4659
+ name: "Off",
4660
+ description: "Implement changes normally"
4661
+ },
4662
+ {
4663
+ value: "on",
4664
+ name: "On",
4665
+ description: "Plan without modifying files; switch off to implement the approved plan"
4666
+ }
4667
+ ]
4668
+ }
4669
+ ];
4670
+ const CLAUDE_STATIC_MODES = [
4671
+ {
4672
+ id: "auto",
4673
+ name: "Auto",
4674
+ description: "Use a model classifier to approve/deny permission prompts"
4675
+ },
4676
+ {
4677
+ id: "default",
4678
+ name: "Default",
4679
+ description: "Standard behavior, prompts for dangerous operations"
4680
+ },
4681
+ {
4682
+ id: "acceptEdits",
4683
+ name: "Accept Edits",
4684
+ description: "Auto-accept file edit operations"
4685
+ },
4686
+ {
4687
+ id: "plan",
4688
+ name: "Plan Mode",
4689
+ description: "Planning mode, no actual tool execution"
4690
+ },
4691
+ {
4692
+ id: "dontAsk",
4693
+ name: "Don't Ask",
4694
+ description: "Don't prompt for permissions, deny if not pre-approved"
4695
+ }
4696
+ ];
4697
+ const CLAUDE_STATIC_MODELS = [
4698
+ {
4699
+ modelId: "default",
4700
+ name: "Default",
4701
+ description: "Claude Code default model"
4702
+ },
4703
+ {
4704
+ modelId: "opus",
4705
+ name: "Opus",
4706
+ description: "Claude Opus"
4707
+ },
4708
+ {
4709
+ modelId: "sonnet",
4710
+ name: "Sonnet",
4711
+ description: "Claude Sonnet"
4712
+ },
4713
+ {
4714
+ modelId: "haiku",
4715
+ name: "Haiku",
4716
+ description: "Claude Haiku"
4717
+ }
4718
+ ];
4719
+ const CLAUDE_STATIC_CONFIG_OPTIONS = [
4720
+ {
4721
+ id: "mode",
4722
+ name: "Mode",
4723
+ description: "Session permission mode",
4724
+ category: "mode",
4725
+ type: "select",
4726
+ currentValue: "default",
4727
+ options: CLAUDE_STATIC_MODES.map((mode2) => ({
4728
+ value: mode2.id,
4729
+ name: mode2.name,
4730
+ description: mode2.description ?? void 0
4731
+ }))
4732
+ },
4733
+ {
4734
+ id: "model",
4735
+ name: "Model",
4736
+ description: "AI model to use",
4737
+ category: "model",
4738
+ type: "select",
4739
+ currentValue: "default",
4740
+ options: CLAUDE_STATIC_MODELS.map((model) => ({
4741
+ value: model.modelId,
4742
+ name: model.name,
4743
+ description: model.description ?? void 0
4744
+ }))
4745
+ },
4746
+ {
4747
+ id: "effort",
4748
+ name: "Effort",
4749
+ description: "Available effort levels for this model",
4750
+ category: "thought_level",
4751
+ type: "select",
4752
+ currentValue: "default",
4753
+ options: [
4754
+ {
4755
+ value: "default",
4756
+ name: "Default"
4757
+ },
4758
+ {
4759
+ value: "low",
4760
+ name: "Low"
4761
+ },
4762
+ {
4763
+ value: "medium",
4764
+ name: "Medium"
4765
+ },
4766
+ {
4767
+ value: "high",
4768
+ name: "High"
4769
+ }
4770
+ ]
4771
+ }
4772
+ ];
4773
+ const cloneConfigOption = (option2) => ({
4774
+ ...option2,
4775
+ options: option2.options.map((value) => ({
4776
+ ...value
4777
+ }))
4778
+ });
4779
+ const cloneStaticCapabilities = (capabilities) => ({
4780
+ modes: capabilities.modes.map((mode2) => ({
4781
+ ...mode2
4782
+ })),
4783
+ models: capabilities.models.map((model) => ({
4784
+ ...model
4785
+ })),
4786
+ configOptions: capabilities.configOptions.map(cloneConfigOption)
4787
+ });
4788
+ const getStaticBuiltinAcpCapabilities = (cliType, agentType, runtimeOverrides) => {
4789
+ if (cliType !== "builtin" || !agentType || !isBuiltinAgentType(agentType)) {
4790
+ return void 0;
4791
+ }
4792
+ if (hasBuiltinRuntimeOverrideValues(runtimeOverrides)) {
4793
+ return void 0;
4794
+ }
4795
+ return cloneStaticCapabilities(agentType === "claude" ? {
4796
+ modes: CLAUDE_STATIC_MODES,
4797
+ models: CLAUDE_STATIC_MODELS,
4798
+ configOptions: CLAUDE_STATIC_CONFIG_OPTIONS
4799
+ } : {
4800
+ modes: CODEX_STATIC_MODES,
4801
+ models: CODEX_STATIC_MODELS,
4802
+ configOptions: CODEX_STATIC_CONFIG_OPTIONS
4803
+ });
4804
+ };
4537
4805
  const leastPermissionModeRank = (value, name2) => {
4538
4806
  const normalized = `${value} ${name2}`.toLowerCase().replace(/[\s_-]+/g, "-");
4539
4807
  if (normalized.includes("read-only") || normalized.includes("readonly")) return 0;
@@ -12100,12 +12368,12 @@ Task description:
12100
12368
  {
12101
12369
  id: "auggie",
12102
12370
  name: "Auggie CLI",
12103
- version: "0.31.0",
12371
+ version: "0.32.0",
12104
12372
  description: "Augment Code's powerful software agent, backed by industry-leading context engine",
12105
12373
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/auggie.svg",
12106
12374
  distribution: {
12107
12375
  npx: {
12108
- package: "@augmentcode/auggie@0.31.0",
12376
+ package: "@augmentcode/auggie@0.32.0",
12109
12377
  args: [
12110
12378
  "--acp"
12111
12379
  ],
@@ -12130,12 +12398,12 @@ Task description:
12130
12398
  {
12131
12399
  id: "cline",
12132
12400
  name: "Cline",
12133
- version: "3.0.34",
12401
+ version: "3.0.38",
12134
12402
  description: "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
12135
12403
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/cline.svg",
12136
12404
  distribution: {
12137
12405
  npx: {
12138
- package: "cline@3.0.34",
12406
+ package: "cline@3.0.38",
12139
12407
  args: [
12140
12408
  "--acp"
12141
12409
  ]
@@ -12292,7 +12560,7 @@ Task description:
12292
12560
  {
12293
12561
  id: "cursor",
12294
12562
  name: "Cursor",
12295
- version: "2026.06.26",
12563
+ version: "2026.07.01",
12296
12564
  description: "Cursor's coding agent",
12297
12565
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/cursor.svg",
12298
12566
  distribution: {
@@ -12322,48 +12590,48 @@ Task description:
12322
12590
  {
12323
12591
  id: "devin",
12324
12592
  name: "Devin",
12325
- version: "2026.8.18",
12593
+ version: "3000.1.27",
12326
12594
  description: "Devin CLI coding agent by Cognition",
12327
12595
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/devin.svg",
12328
12596
  distribution: {
12329
12597
  binary: {
12330
12598
  "darwin-aarch64": {
12331
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-aarch64-apple-darwin.tar.gz",
12599
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-aarch64-apple-darwin.tar.gz",
12332
12600
  cmd: "./bin/devin",
12333
12601
  args: [
12334
12602
  "acp"
12335
12603
  ]
12336
12604
  },
12337
12605
  "darwin-x86_64": {
12338
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-x86_64-apple-darwin.tar.gz",
12606
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-x86_64-apple-darwin.tar.gz",
12339
12607
  cmd: "./bin/devin",
12340
12608
  args: [
12341
12609
  "acp"
12342
12610
  ]
12343
12611
  },
12344
12612
  "linux-aarch64": {
12345
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-aarch64-unknown-linux.tar.gz",
12613
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-aarch64-unknown-linux.tar.gz",
12346
12614
  cmd: "./bin/devin",
12347
12615
  args: [
12348
12616
  "acp"
12349
12617
  ]
12350
12618
  },
12351
12619
  "linux-x86_64": {
12352
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-x86_64-unknown-linux.tar.gz",
12620
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-x86_64-unknown-linux.tar.gz",
12353
12621
  cmd: "./bin/devin",
12354
12622
  args: [
12355
12623
  "acp"
12356
12624
  ]
12357
12625
  },
12358
12626
  "windows-aarch64": {
12359
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-aarch64-pc-windows.zip",
12627
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-aarch64-pc-windows.zip",
12360
12628
  cmd: "./bin\\devin.exe",
12361
12629
  args: [
12362
12630
  "acp"
12363
12631
  ]
12364
12632
  },
12365
12633
  "windows-x86_64": {
12366
- archive: "https://static.devin.ai/cli/2026.8.18/devin-2026.8.18-x86_64-pc-windows.zip",
12634
+ archive: "https://static.devin.ai/cli/3000.1.27/devin-3000.1.27-x86_64-pc-windows.zip",
12367
12635
  cmd: "./bin\\devin.exe",
12368
12636
  args: [
12369
12637
  "acp"
@@ -12375,12 +12643,12 @@ Task description:
12375
12643
  {
12376
12644
  id: "dimcode",
12377
12645
  name: "DimCode",
12378
- version: "0.2.12",
12646
+ version: "0.2.21",
12379
12647
  description: "A coding agent that puts leading models at your command.",
12380
12648
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/dimcode.svg",
12381
12649
  distribution: {
12382
12650
  npx: {
12383
- package: "dimcode@0.2.12",
12651
+ package: "dimcode@0.2.21",
12384
12652
  args: [
12385
12653
  "acp"
12386
12654
  ]
@@ -12390,12 +12658,12 @@ Task description:
12390
12658
  {
12391
12659
  id: "dirac",
12392
12660
  name: "Dirac",
12393
- version: "0.4.12",
12661
+ version: "0.4.13",
12394
12662
  description: "Reduces API costs by more than 50%, produces better and faster work. Uses Hash anchored parallel edits, AST manipulation and a whole lot of neat optimizations. Fully Open Source.",
12395
12663
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/dirac.svg",
12396
12664
  distribution: {
12397
12665
  npx: {
12398
- package: "dirac-cli@0.4.12",
12666
+ package: "dirac-cli@0.4.13",
12399
12667
  args: [
12400
12668
  "--acp"
12401
12669
  ]
@@ -12405,12 +12673,12 @@ Task description:
12405
12673
  {
12406
12674
  id: "factory-droid",
12407
12675
  name: "Factory Droid",
12408
- version: "0.159.1",
12676
+ version: "0.164.1",
12409
12677
  description: "Factory Droid - AI coding agent powered by Factory AI",
12410
12678
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/factory-droid.svg",
12411
12679
  distribution: {
12412
12680
  npx: {
12413
- package: "droid@0.159.1",
12681
+ package: "droid@0.164.1",
12414
12682
  args: [
12415
12683
  "exec",
12416
12684
  "--output-format",
@@ -12426,12 +12694,12 @@ Task description:
12426
12694
  {
12427
12695
  id: "fast-agent",
12428
12696
  name: "fast-agent",
12429
- version: "0.8.0",
12697
+ version: "0.9.2",
12430
12698
  description: "Code and build agents with comprehensive multi-provider support",
12431
12699
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/fast-agent.svg",
12432
12700
  distribution: {
12433
12701
  uvx: {
12434
- package: "fast-agent-acp==0.8.0",
12702
+ package: "fast-agent-acp==0.9.2",
12435
12703
  args: [
12436
12704
  "-x"
12437
12705
  ]
@@ -12456,12 +12724,12 @@ Task description:
12456
12724
  {
12457
12725
  id: "github-copilot-cli",
12458
12726
  name: "GitHub Copilot",
12459
- version: "1.0.65",
12727
+ version: "1.0.68",
12460
12728
  description: "GitHub's AI pair programmer",
12461
12729
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/github-copilot-cli.svg",
12462
12730
  distribution: {
12463
12731
  npx: {
12464
- package: "@github/copilot@1.0.65",
12732
+ package: "@github/copilot@1.0.68",
12465
12733
  args: [
12466
12734
  "--acp"
12467
12735
  ]
@@ -12483,7 +12751,7 @@ Task description:
12483
12751
  {
12484
12752
  id: "goose",
12485
12753
  name: "goose",
12486
- version: "1.39.0",
12754
+ version: "1.41.0",
12487
12755
  description: "A local, extensible, open source AI agent that automates engineering tasks",
12488
12756
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/goose.svg",
12489
12757
  distribution: {
@@ -12501,12 +12769,12 @@ Task description:
12501
12769
  {
12502
12770
  id: "grok-build",
12503
12771
  name: "Grok Build",
12504
- version: "0.2.75",
12772
+ version: "0.2.89",
12505
12773
  description: "xAI's coding agent and CLI",
12506
12774
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/grok-build.svg",
12507
12775
  distribution: {
12508
12776
  npx: {
12509
- package: "@xai-official/grok@0.2.75",
12777
+ package: "@xai-official/grok@0.2.89",
12510
12778
  args: [
12511
12779
  "agent",
12512
12780
  "stdio"
@@ -12514,10 +12782,61 @@ Task description:
12514
12782
  }
12515
12783
  }
12516
12784
  },
12785
+ {
12786
+ id: "harn",
12787
+ name: "Harn",
12788
+ version: "0.10.0",
12789
+ description: "Harn runs .harn agent pipelines as a native ACP coding agent over stdio.",
12790
+ icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/harn.svg",
12791
+ distribution: {
12792
+ binary: {
12793
+ "darwin-aarch64": {
12794
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.0/harn-aarch64-apple-darwin.tar.gz",
12795
+ cmd: "./harn",
12796
+ args: [
12797
+ "serve",
12798
+ "acp"
12799
+ ]
12800
+ },
12801
+ "darwin-x86_64": {
12802
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.0/harn-x86_64-apple-darwin.tar.gz",
12803
+ cmd: "./harn",
12804
+ args: [
12805
+ "serve",
12806
+ "acp"
12807
+ ]
12808
+ },
12809
+ "linux-aarch64": {
12810
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.0/harn-aarch64-unknown-linux-gnu.tar.gz",
12811
+ cmd: "./harn",
12812
+ args: [
12813
+ "serve",
12814
+ "acp"
12815
+ ]
12816
+ },
12817
+ "linux-x86_64": {
12818
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.0/harn-x86_64-unknown-linux-gnu.tar.gz",
12819
+ cmd: "./harn",
12820
+ args: [
12821
+ "serve",
12822
+ "acp"
12823
+ ]
12824
+ },
12825
+ "windows-x86_64": {
12826
+ archive: "https://github.com/burin-labs/harn/releases/download/v0.10.0/harn-x86_64-pc-windows-msvc.zip",
12827
+ cmd: "harn.exe",
12828
+ args: [
12829
+ "serve",
12830
+ "acp"
12831
+ ]
12832
+ }
12833
+ }
12834
+ }
12835
+ },
12517
12836
  {
12518
12837
  id: "junie",
12519
12838
  name: "Junie",
12520
- version: "2045.46.0",
12839
+ version: "2144.7.0",
12521
12840
  description: "AI Coding Agent by JetBrains",
12522
12841
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/junie.svg",
12523
12842
  distribution: {
@@ -12535,47 +12854,47 @@ Task description:
12535
12854
  {
12536
12855
  id: "kilo",
12537
12856
  name: "Kilo",
12538
- version: "7.3.54",
12857
+ version: "7.4.1",
12539
12858
  description: "The open source coding agent",
12540
12859
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/kilo.svg",
12541
12860
  distribution: {
12542
12861
  npx: {
12543
- package: "@kilocode/cli@7.3.54",
12862
+ package: "@kilocode/cli@7.4.1",
12544
12863
  args: [
12545
12864
  "acp"
12546
12865
  ]
12547
12866
  },
12548
12867
  binary: {
12549
12868
  "darwin-aarch64": {
12550
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.54/kilo-darwin-arm64.zip",
12869
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/kilo-darwin-arm64.zip",
12551
12870
  cmd: "./kilo",
12552
12871
  args: [
12553
12872
  "acp"
12554
12873
  ]
12555
12874
  },
12556
12875
  "darwin-x86_64": {
12557
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.54/kilo-darwin-x64.zip",
12876
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/kilo-darwin-x64.zip",
12558
12877
  cmd: "./kilo",
12559
12878
  args: [
12560
12879
  "acp"
12561
12880
  ]
12562
12881
  },
12563
12882
  "linux-aarch64": {
12564
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.54/kilo-linux-arm64.tar.gz",
12883
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/kilo-linux-arm64.tar.gz",
12565
12884
  cmd: "./kilo",
12566
12885
  args: [
12567
12886
  "acp"
12568
12887
  ]
12569
12888
  },
12570
12889
  "linux-x86_64": {
12571
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.54/kilo-linux-x64.tar.gz",
12890
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/kilo-linux-x64.tar.gz",
12572
12891
  cmd: "./kilo",
12573
12892
  args: [
12574
12893
  "acp"
12575
12894
  ]
12576
12895
  },
12577
12896
  "windows-x86_64": {
12578
- archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.3.54/kilo-windows-x64.zip",
12897
+ archive: "https://github.com/Kilo-Org/kilocode/releases/download/v7.4.1/kilo-windows-x64.zip",
12579
12898
  cmd: "./kilo.exe",
12580
12899
  args: [
12581
12900
  "acp"
@@ -12641,7 +12960,7 @@ Task description:
12641
12960
  {
12642
12961
  id: "mistral-vibe",
12643
12962
  name: "Mistral Vibe",
12644
- version: "2.18.2",
12963
+ version: "2.19.0",
12645
12964
  description: "Mistral's open-source coding assistant",
12646
12965
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/mistral-vibe.svg",
12647
12966
  distribution: {
@@ -12657,12 +12976,12 @@ Task description:
12657
12976
  {
12658
12977
  id: "nova",
12659
12978
  name: "Nova",
12660
- version: "1.1.21",
12979
+ version: "1.1.24",
12661
12980
  description: "Nova by Compass AI - a fully-fledged software engineer at your command",
12662
12981
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/nova.svg",
12663
12982
  distribution: {
12664
12983
  npx: {
12665
- package: "@compass-ai/nova@1.1.21",
12984
+ package: "@compass-ai/nova@1.1.24",
12666
12985
  args: [
12667
12986
  "acp"
12668
12987
  ]
@@ -12672,7 +12991,7 @@ Task description:
12672
12991
  {
12673
12992
  id: "opencode",
12674
12993
  name: "OpenCode",
12675
- version: "1.17.11",
12994
+ version: "1.17.14",
12676
12995
  description: "The open source coding agent",
12677
12996
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/opencode.svg",
12678
12997
  distribution: {
@@ -12702,48 +13021,48 @@ Task description:
12702
13021
  {
12703
13022
  id: "poolside",
12704
13023
  name: "Poolside",
12705
- version: "1.0.7",
13024
+ version: "1.0.8",
12706
13025
  description: "Poolside's coding agent",
12707
13026
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/poolside.svg",
12708
13027
  distribution: {
12709
13028
  binary: {
12710
13029
  "darwin-aarch64": {
12711
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-darwin-arm64.tar.gz",
13030
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-darwin-arm64.tar.gz",
12712
13031
  cmd: "./pool-darwin-arm64",
12713
13032
  args: [
12714
13033
  "acp"
12715
13034
  ]
12716
13035
  },
12717
13036
  "darwin-x86_64": {
12718
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-darwin-amd64.tar.gz",
13037
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-darwin-amd64.tar.gz",
12719
13038
  cmd: "./pool-darwin-amd64",
12720
13039
  args: [
12721
13040
  "acp"
12722
13041
  ]
12723
13042
  },
12724
13043
  "linux-aarch64": {
12725
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-linux-arm64.tar.gz",
13044
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-linux-arm64.tar.gz",
12726
13045
  cmd: "./pool-linux-arm64",
12727
13046
  args: [
12728
13047
  "acp"
12729
13048
  ]
12730
13049
  },
12731
13050
  "linux-x86_64": {
12732
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-linux-amd64.tar.gz",
13051
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-linux-amd64.tar.gz",
12733
13052
  cmd: "./pool-linux-amd64",
12734
13053
  args: [
12735
13054
  "acp"
12736
13055
  ]
12737
13056
  },
12738
13057
  "windows-aarch64": {
12739
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-windows-arm64.tar.gz",
13058
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-windows-arm64.tar.gz",
12740
13059
  cmd: "./pool-windows-arm64.exe",
12741
13060
  args: [
12742
13061
  "acp"
12743
13062
  ]
12744
13063
  },
12745
13064
  "windows-x86_64": {
12746
- archive: "https://downloads.poolside.ai/pool/v1.0.7/pool-windows-amd64.tar.gz",
13065
+ archive: "https://downloads.poolside.ai/pool/v1.0.8/pool-windows-amd64.tar.gz",
12747
13066
  cmd: "./pool-windows-amd64.exe",
12748
13067
  args: [
12749
13068
  "acp"
@@ -12770,12 +13089,12 @@ Task description:
12770
13089
  {
12771
13090
  id: "qwen-code",
12772
13091
  name: "Qwen Code",
12773
- version: "0.19.3",
13092
+ version: "0.19.6",
12774
13093
  description: "Alibaba's Qwen coding assistant",
12775
13094
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/qwen-code.svg",
12776
13095
  distribution: {
12777
13096
  npx: {
12778
- package: "@qwen-code/qwen-code@0.19.3",
13097
+ package: "@qwen-code/qwen-code@0.19.6",
12779
13098
  args: [
12780
13099
  "--acp",
12781
13100
  "--experimental-skills"
@@ -12800,36 +13119,36 @@ Task description:
12800
13119
  {
12801
13120
  id: "sigit",
12802
13121
  name: "siGit Code",
12803
- version: "1.2.2",
13122
+ version: "1.3.2",
12804
13123
  description: "Local-first coding agent. Runs entirely on your machine with optional on-device LLM inference via Onde.",
12805
13124
  icon: "https://cdn.agentclientprotocol.com/registry/v1/latest/sigit.svg",
12806
13125
  distribution: {
12807
13126
  npx: {
12808
- package: "@smbcloud/sigit@1.2.2"
13127
+ package: "@smbcloud/sigit@1.3.2"
12809
13128
  },
12810
13129
  binary: {
12811
13130
  "darwin-aarch64": {
12812
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-macos-arm64.tar.gz",
13131
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-macos-arm64.tar.gz",
12813
13132
  cmd: "./sigit"
12814
13133
  },
12815
13134
  "darwin-x86_64": {
12816
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-macos-amd64.tar.gz",
13135
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-macos-amd64.tar.gz",
12817
13136
  cmd: "./sigit"
12818
13137
  },
12819
13138
  "linux-aarch64": {
12820
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-linux-arm64",
13139
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-linux-arm64",
12821
13140
  cmd: "./sigit-linux-arm64"
12822
13141
  },
12823
13142
  "linux-x86_64": {
12824
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-linux-amd64",
13143
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-linux-amd64",
12825
13144
  cmd: "./sigit-linux-amd64"
12826
13145
  },
12827
13146
  "windows-aarch64": {
12828
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-win-arm64.exe",
13147
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-win-arm64.exe",
12829
13148
  cmd: "./sigit-win-arm64.exe"
12830
13149
  },
12831
13150
  "windows-x86_64": {
12832
- archive: "https://github.com/getsigit/sigit/releases/download/v1.2.2/sigit-win-amd64.exe",
13151
+ archive: "https://github.com/getsigit/sigit/releases/download/v1.3.2/sigit-win-amd64.exe",
12833
13152
  cmd: "./sigit-win-amd64.exe"
12834
13153
  }
12835
13154
  }
@@ -78904,6 +79223,252 @@ ${this.stack.split("\n").slice(1).join("\n")}` : this.toString();
78904
79223
  }
78905
79224
  }
78906
79225
  }
79226
+ const isRecoverableMachineFlockRoomStatus = (status) => status === "disconnected" || status === "error";
79227
+ class MachineFlockSyncCoordinator {
79228
+ repo;
79229
+ workspaceId;
79230
+ logger;
79231
+ random;
79232
+ retryBaseDelayMs;
79233
+ retryMaxDelayMs;
79234
+ states = /* @__PURE__ */ new Map();
79235
+ cleanedUp = false;
79236
+ constructor(options) {
79237
+ this.repo = options.repo;
79238
+ this.workspaceId = options.workspaceId;
79239
+ this.logger = options.logger;
79240
+ this.random = options.random ?? Math.random;
79241
+ this.retryBaseDelayMs = options.retryBaseDelayMs;
79242
+ this.retryMaxDelayMs = options.retryMaxDelayMs;
79243
+ }
79244
+ ensureJoined(machineId, options = {}) {
79245
+ const state2 = this.getState(machineId);
79246
+ return this.ensureStateJoined(state2, options.reason ?? "ensure-joined");
79247
+ }
79248
+ markDirty(machineId, options = {}) {
79249
+ if (this.cleanedUp) {
79250
+ return;
79251
+ }
79252
+ const state2 = this.getState(machineId);
79253
+ state2.dirty = true;
79254
+ state2.dirtyVersion += 1;
79255
+ if (options.resetBackoff) {
79256
+ state2.retryAttempt = 0;
79257
+ }
79258
+ const reason = options.reason ?? "dirty";
79259
+ void this.ensureStateJoined(state2, `dirty:${reason}`).catch((error2) => {
79260
+ this.logger.debug(`[${this.workspaceId}] Machine Flock room join failed before background sync (machine=${machineId} reason=${reason}): ${formatErrorMessage(error2)}`);
79261
+ });
79262
+ void this.syncNow(machineId, {
79263
+ ...options,
79264
+ reason,
79265
+ scheduleRetry: options.scheduleRetry ?? true
79266
+ });
79267
+ }
79268
+ async syncNow(machineId, options = {}) {
79269
+ if (this.cleanedUp) {
79270
+ return false;
79271
+ }
79272
+ const state2 = this.getState(machineId);
79273
+ if (state2.activeSync) {
79274
+ return await state2.activeSync;
79275
+ }
79276
+ state2.activeSync = this.syncStateNow(state2, options).finally(() => {
79277
+ state2.activeSync = null;
79278
+ });
79279
+ return await state2.activeSync;
79280
+ }
79281
+ retryDirtyNow(reason) {
79282
+ if (this.cleanedUp) {
79283
+ return;
79284
+ }
79285
+ for (const state2 of this.states.values()) {
79286
+ if (!state2.dirty) {
79287
+ continue;
79288
+ }
79289
+ this.clearRetryTimer(state2);
79290
+ state2.retryAttempt = 0;
79291
+ void this.syncNow(state2.machineId, {
79292
+ reason,
79293
+ scheduleRetry: true,
79294
+ resetBackoff: true
79295
+ });
79296
+ }
79297
+ }
79298
+ async cleanUp() {
79299
+ this.cleanedUp = true;
79300
+ const pendingOperations = [];
79301
+ for (const state2 of this.states.values()) {
79302
+ this.clearRetryTimer(state2);
79303
+ if (state2.activeSync) {
79304
+ pendingOperations.push(state2.activeSync);
79305
+ }
79306
+ if (state2.joinPromise) {
79307
+ pendingOperations.push(state2.joinPromise);
79308
+ }
79309
+ this.releaseRoomSubscription(state2);
79310
+ }
79311
+ await Promise.allSettled(pendingOperations);
79312
+ this.states.clear();
79313
+ }
79314
+ async syncStateNow(state2, options) {
79315
+ const reason = options.reason ?? "sync-now";
79316
+ if (options.resetBackoff) {
79317
+ state2.retryAttempt = 0;
79318
+ }
79319
+ this.clearRetryTimer(state2);
79320
+ try {
79321
+ await this.ensureStateJoined(state2, `sync:${reason}`);
79322
+ } catch (error2) {
79323
+ this.logger.debug(`[${this.workspaceId}] Machine Flock room join failed before sync (machine=${state2.machineId} reason=${reason}): ${formatErrorMessage(error2)}`);
79324
+ }
79325
+ const syncVersion = state2.dirtyVersion;
79326
+ const timeoutMs = options.timeoutMs ?? readTimeoutEnv("LODY_LORO_SYNC_MACHINE_FLOCK_TIMEOUT_MS", 8e3);
79327
+ const timeoutMessage = `Timeout waiting for machine Flock doc sync (doc=${state2.docId})`;
79328
+ try {
79329
+ const handle = await this.repo.openFlockDoc(state2.docId);
79330
+ await withTimeout$3(handle.syncOnce(), timeoutMs, timeoutMessage);
79331
+ if (state2.dirtyVersion === syncVersion) {
79332
+ state2.dirty = false;
79333
+ state2.retryAttempt = 0;
79334
+ } else if (state2.dirty) {
79335
+ this.scheduleRetry(state2, `${reason}:new-writes`, true);
79336
+ }
79337
+ this.logger.debug(`[${this.workspaceId}] Machine Flock doc synced (machine=${state2.machineId} reason=${reason})`);
79338
+ return true;
79339
+ } catch (error2) {
79340
+ this.logger.debug(`[${this.workspaceId}] Machine Flock doc sync was not confirmed before continuing (machine=${state2.machineId} reason=${reason}): ${formatErrorMessage(error2)}`);
79341
+ if (options.scheduleRetry ?? true) {
79342
+ state2.dirty = true;
79343
+ this.scheduleRetry(state2, reason, false);
79344
+ }
79345
+ return false;
79346
+ }
79347
+ }
79348
+ async ensureStateJoined(state2, reason) {
79349
+ if (this.cleanedUp) {
79350
+ return;
79351
+ }
79352
+ if (state2.roomSub) {
79353
+ if (!isRecoverableMachineFlockRoomStatus(state2.roomSub.status)) {
79354
+ return;
79355
+ }
79356
+ this.releaseRoomSubscription(state2, state2.roomSub);
79357
+ }
79358
+ if (state2.joinPromise) {
79359
+ return await state2.joinPromise;
79360
+ }
79361
+ state2.joinPromise = (async () => {
79362
+ const handle = await this.repo.openFlockDoc(state2.docId);
79363
+ const sub = await handle.joinRoom();
79364
+ if (this.cleanedUp) {
79365
+ sub.unsubscribe();
79366
+ return;
79367
+ }
79368
+ state2.roomSub = sub;
79369
+ state2.detachRoomStatusListener = sub.onStatusChange((status) => {
79370
+ this.handleRoomStatusChange(state2, sub, status);
79371
+ });
79372
+ this.handleRoomStatusChange(state2, sub, sub.status);
79373
+ if (state2.roomSub !== sub) {
79374
+ return;
79375
+ }
79376
+ void sub.firstSyncedWithRemote.then(() => {
79377
+ if (this.cleanedUp || state2.roomSub !== sub) {
79378
+ return;
79379
+ }
79380
+ this.logger.debug(`[${this.workspaceId}] Machine Flock room first sync completed (machine=${state2.machineId} reason=${reason})`);
79381
+ }, (error2) => {
79382
+ if (this.cleanedUp || state2.roomSub !== sub) {
79383
+ return;
79384
+ }
79385
+ this.logger.debug(`[${this.workspaceId}] Machine Flock room first sync failed (machine=${state2.machineId} reason=${reason}): ${formatErrorMessage(error2)}`);
79386
+ });
79387
+ })();
79388
+ try {
79389
+ await state2.joinPromise;
79390
+ } finally {
79391
+ state2.joinPromise = null;
79392
+ }
79393
+ }
79394
+ handleRoomStatusChange(state2, sub, status) {
79395
+ if (this.cleanedUp || state2.roomSub !== sub) {
79396
+ return;
79397
+ }
79398
+ if (!isRecoverableMachineFlockRoomStatus(status)) {
79399
+ return;
79400
+ }
79401
+ this.logger.debug(`[${this.workspaceId}] Machine Flock room became ${status}; will rejoin before the next sync (machine=${state2.machineId})`);
79402
+ this.releaseRoomSubscription(state2, sub);
79403
+ if (state2.dirty) {
79404
+ this.scheduleRetry(state2, `room-${status}`, false);
79405
+ }
79406
+ }
79407
+ releaseRoomSubscription(state2, sub = state2.roomSub) {
79408
+ if (!sub || state2.roomSub !== sub) {
79409
+ return;
79410
+ }
79411
+ state2.detachRoomStatusListener?.();
79412
+ state2.detachRoomStatusListener = null;
79413
+ state2.roomSub = null;
79414
+ sub.unsubscribe();
79415
+ }
79416
+ scheduleRetry(state2, reason, resetBackoff) {
79417
+ if (this.cleanedUp || !state2.dirty) {
79418
+ return;
79419
+ }
79420
+ if (resetBackoff) {
79421
+ state2.retryAttempt = 0;
79422
+ }
79423
+ if (state2.retryTimer) {
79424
+ return;
79425
+ }
79426
+ const delayMs = computeLoroReconnectDelayMs(state2.retryAttempt, {
79427
+ baseDelayMs: this.retryBaseDelayMs ?? readTimeoutEnv("LODY_LORO_MACHINE_FLOCK_RETRY_BASE_DELAY_MS", 1e3),
79428
+ maxDelayMs: this.retryMaxDelayMs ?? readTimeoutEnv("LODY_LORO_MACHINE_FLOCK_RETRY_MAX_DELAY_MS", 6e4),
79429
+ random: this.random
79430
+ });
79431
+ state2.retryAttempt += 1;
79432
+ state2.retryTimer = setTimeout(() => {
79433
+ state2.retryTimer = null;
79434
+ if (this.cleanedUp || !state2.dirty) {
79435
+ return;
79436
+ }
79437
+ void this.syncNow(state2.machineId, {
79438
+ reason: `retry:${reason}`,
79439
+ scheduleRetry: true
79440
+ });
79441
+ }, delayMs);
79442
+ this.logger.debug(`[${this.workspaceId}] Scheduled Machine Flock doc sync retry in ${delayMs}ms (machine=${state2.machineId} reason=${reason})`);
79443
+ }
79444
+ clearRetryTimer(state2) {
79445
+ if (!state2.retryTimer) {
79446
+ return;
79447
+ }
79448
+ clearTimeout(state2.retryTimer);
79449
+ state2.retryTimer = null;
79450
+ }
79451
+ getState(machineId) {
79452
+ const existing = this.states.get(machineId);
79453
+ if (existing) {
79454
+ return existing;
79455
+ }
79456
+ const state2 = {
79457
+ machineId,
79458
+ docId: getMachineFlockDocId(this.workspaceId, machineId),
79459
+ dirty: false,
79460
+ dirtyVersion: 0,
79461
+ retryAttempt: 0,
79462
+ retryTimer: null,
79463
+ activeSync: null,
79464
+ joinPromise: null,
79465
+ roomSub: null,
79466
+ detachRoomStatusListener: null
79467
+ };
79468
+ this.states.set(machineId, state2);
79469
+ return state2;
79470
+ }
79471
+ }
78907
79472
  const SENSITIVE_QUERY_KEYS = /* @__PURE__ */ new Set([
78908
79473
  "token",
78909
79474
  "access_token",
@@ -98466,7 +99031,7 @@ ${value}`;
98466
99031
  ]);
98467
99032
  return mergeAgentConfigs(loroRepoMetaConfigs, machineFlockConfigs);
98468
99033
  }
98469
- async function upsertMachineAgentConfig(repo, workspaceId, config2) {
99034
+ async function upsertMachineAgentConfig(repo, workspaceId, config2, options = {}) {
98470
99035
  const handle = await repo.openFlockDoc(getMachineFlockDocId(workspaceId, config2.machineId));
98471
99036
  const changed = writeMachineFlockRowToFlock(handle.flock, {
98472
99037
  key: machineFlockKeys.agentConfig(config2.id),
@@ -98477,10 +99042,16 @@ ${value}`;
98477
99042
  return;
98478
99043
  }
98479
99044
  await repo.flush();
98480
- await handle.syncOnce().catch(() => void 0);
99045
+ if (options.sync) {
99046
+ options.sync.markMachineFlockDocDirty(config2.machineId, {
99047
+ reason: options.reason ?? "agent-config-upsert"
99048
+ });
99049
+ } else {
99050
+ await handle.syncOnce().catch(() => void 0);
99051
+ }
98481
99052
  await deleteLoroRepoMetaAgentConfigIfPresent(repo, config2.id);
98482
99053
  }
98483
- async function deleteMachineAgentConfig(repo, workspaceId, config2) {
99054
+ async function deleteMachineAgentConfig(repo, workspaceId, config2, options = {}) {
98484
99055
  const handle = await repo.openFlockDoc(getMachineFlockDocId(workspaceId, config2.machineId));
98485
99056
  const changed = deleteMachineFlockRowFromFlock(handle.flock, machineFlockKeys.agentConfig(config2.id));
98486
99057
  if (!changed) {
@@ -98488,7 +99059,13 @@ ${value}`;
98488
99059
  return;
98489
99060
  }
98490
99061
  await repo.flush();
98491
- await handle.syncOnce().catch(() => void 0);
99062
+ if (options.sync) {
99063
+ options.sync.markMachineFlockDocDirty(config2.machineId, {
99064
+ reason: options.reason ?? "agent-config-delete"
99065
+ });
99066
+ } else {
99067
+ await handle.syncOnce().catch(() => void 0);
99068
+ }
98492
99069
  await deleteLoroRepoMetaAgentConfigIfPresent(repo, config2.id);
98493
99070
  }
98494
99071
  async function listMachineAgentConfigs(repo, workspaceId, machineIds) {
@@ -98684,11 +99261,21 @@ ${value}`;
98684
99261
  this.initialMetaSyncCompleted = true;
98685
99262
  }
98686
99263
  });
99264
+ this.machineFlockSync = new MachineFlockSyncCoordinator({
99265
+ repo,
99266
+ workspaceId,
99267
+ logger: logger2
99268
+ });
99269
+ this.detachMachineFlockMetaRoomSyncedListener = this.connectionRecovery.onMetaRoomSynced((reason) => {
99270
+ this.machineFlockSync.retryDirtyNow(`meta-room-synced:${reason}`);
99271
+ });
98687
99272
  }
98688
99273
  sessions = /* @__PURE__ */ new Map();
98689
99274
  machine = null;
98690
99275
  machineExistenceWatcher = null;
98691
99276
  connectionRecovery;
99277
+ machineFlockSync;
99278
+ detachMachineFlockMetaRoomSyncedListener = null;
98692
99279
  initialMetaSyncCompleted = false;
98693
99280
  initialMetaSyncPromise;
98694
99281
  presenceRuntime;
@@ -98875,6 +99462,70 @@ ${value}`;
98875
99462
  async waitUntilMetaSynced(options = {}) {
98876
99463
  return await this.connectionRecovery.waitUntilMetaSynced(options);
98877
99464
  }
99465
+ async syncMetaOrThrow(options = {}) {
99466
+ const reason = options.reason ?? "explicit-sync";
99467
+ const timeoutMs = options.timeoutMs ?? readTimeoutEnv("LODY_LORO_SYNC_META_TIMEOUT_MS", 2e4);
99468
+ const timeoutMessage = `Timeout waiting for workspace metadata sync (workspace=${this.workspaceId})`;
99469
+ try {
99470
+ await withTimeout$3(this.repo.sync({
99471
+ scope: "meta"
99472
+ }), timeoutMs, timeoutMessage);
99473
+ this.initialMetaSyncCompleted = true;
99474
+ } catch (error2) {
99475
+ throw new Error(`Workspace metadata sync failed (${reason}): ${formatErrorMessage(error2)}`, {
99476
+ cause: error2
99477
+ });
99478
+ }
99479
+ }
99480
+ async syncDocOrThrow(docId, options = {}) {
99481
+ const reason = options.reason ?? "explicit-sync";
99482
+ const timeoutMs = options.timeoutMs ?? readTimeoutEnv("LODY_LORO_SYNC_DOC_TIMEOUT_MS", 8e3);
99483
+ const timeoutMessage = `Timeout waiting for document sync (doc=${docId})`;
99484
+ try {
99485
+ await withTimeout$3(this.repo.sync({
99486
+ scope: "doc",
99487
+ docIds: [
99488
+ docId
99489
+ ]
99490
+ }), timeoutMs, timeoutMessage);
99491
+ } catch (error2) {
99492
+ throw new Error(`Document sync failed for ${docId} (${reason}): ${formatErrorMessage(error2)}`, {
99493
+ cause: error2
99494
+ });
99495
+ }
99496
+ }
99497
+ async syncFlockDocOrThrow(flockDocId, options = {}) {
99498
+ const reason = options.reason ?? "explicit-sync";
99499
+ const timeoutMs = options.timeoutMs ?? readTimeoutEnv("LODY_LORO_SYNC_MACHINE_FLOCK_TIMEOUT_MS", 8e3);
99500
+ const timeoutMessage = `Timeout waiting for Flock document sync (doc=${flockDocId})`;
99501
+ try {
99502
+ await withTimeout$3(this.repo.sync({
99503
+ scope: "doc",
99504
+ flockDocIds: [
99505
+ flockDocId
99506
+ ]
99507
+ }), timeoutMs, timeoutMessage);
99508
+ } catch (error2) {
99509
+ throw new Error(`Flock document sync failed for ${flockDocId} (${reason}): ${formatErrorMessage(error2)}`, {
99510
+ cause: error2
99511
+ });
99512
+ }
99513
+ }
99514
+ async syncMachineFlockDoc(machineId, options = {}) {
99515
+ return await this.machineFlockSync.syncNow(machineId, {
99516
+ ...options,
99517
+ reason: options.reason ?? "explicit-sync",
99518
+ scheduleRetry: options.scheduleRetry ?? true
99519
+ });
99520
+ }
99521
+ markMachineFlockDocDirty(machineId, options = {}) {
99522
+ this.machineFlockSync.markDirty(machineId, options);
99523
+ }
99524
+ ensureMachineFlockDocJoined(machineId, options = {}) {
99525
+ void this.machineFlockSync.ensureJoined(machineId, options).catch((error2) => {
99526
+ this.logger.debug(`[${this.workspaceId}] Failed to join Machine Flock room (machine=${machineId} reason=${options.reason ?? "ensure-joined"}): ${formatErrorMessage(error2)}`);
99527
+ });
99528
+ }
98878
99529
  async destroyRepo(options) {
98879
99530
  const repoDestroyPromise = this.repo.destroy();
98880
99531
  if (!options.fast) {
@@ -98987,6 +99638,9 @@ ${value}`;
98987
99638
  cliType,
98988
99639
  agentType,
98989
99640
  env: {}
99641
+ }, {
99642
+ sync: this,
99643
+ reason: "agent-config-upsert"
98990
99644
  });
98991
99645
  return agentConfigId;
98992
99646
  }
@@ -98994,7 +99648,7 @@ ${value}`;
98994
99648
  }
98995
99649
  async registerMachine(machineId, machine) {
98996
99650
  if (!this.machine) {
98997
- this.machine = new MachineDocument(this.repo, this.workspaceId, machineId);
99651
+ this.machine = this.createMachineDocument(machineId);
98998
99652
  await this.machine.init();
98999
99653
  }
99000
99654
  await this.machine.setMetaState({
@@ -99005,25 +99659,32 @@ ${value}`;
99005
99659
  }
99006
99660
  async updateRateLimits(machineId, cliType, limits) {
99007
99661
  if (!this.machine) {
99008
- this.machine = new MachineDocument(this.repo, this.workspaceId, machineId);
99662
+ this.machine = this.createMachineDocument(machineId);
99009
99663
  await this.machine.init();
99010
99664
  }
99011
99665
  await this.machine.updateRateLimits(cliType, limits);
99012
99666
  }
99013
99667
  async updateAcpCapabilities(machineId, cliType, agentType, modes, models, configOptions, availableCommands, sourceVersion) {
99014
99668
  if (!this.machine) {
99015
- this.machine = new MachineDocument(this.repo, this.workspaceId, machineId);
99669
+ this.machine = this.createMachineDocument(machineId);
99016
99670
  await this.machine.init();
99017
99671
  }
99018
99672
  await this.machine.updateAcpCapabilities(cliType, agentType, modes, models, configOptions, availableCommands, sourceVersion);
99019
99673
  }
99020
99674
  async getAcpCapabilities(machineId, cliType, agentType) {
99021
99675
  if (!this.machine) {
99022
- this.machine = new MachineDocument(this.repo, this.workspaceId, machineId);
99676
+ this.machine = this.createMachineDocument(machineId);
99023
99677
  await this.machine.init();
99024
99678
  }
99025
99679
  return this.machine.getAcpCapabilities(cliType, agentType);
99026
99680
  }
99681
+ createMachineDocument(machineId) {
99682
+ return new MachineDocument(this.repo, this.workspaceId, machineId, (reason) => {
99683
+ this.markMachineFlockDocDirty(machineId, {
99684
+ reason
99685
+ });
99686
+ });
99687
+ }
99027
99688
  async restoreMachineDocument(machineId) {
99028
99689
  const machineRoomId = getMachineRoomId(machineId);
99029
99690
  await this.repo.restoreDoc(machineRoomId);
@@ -99053,6 +99714,9 @@ ${value}`;
99053
99714
  } catch (error2) {
99054
99715
  this.logger.debug(`[${this.workspaceId}] Failed to stop Loro presence runtime: ${formatErrorMessage(error2)}`);
99055
99716
  }
99717
+ this.detachMachineFlockMetaRoomSyncedListener?.();
99718
+ this.detachMachineFlockMetaRoomSyncedListener = null;
99719
+ await this.machineFlockSync.cleanUp();
99056
99720
  await this.connectionRecovery.cleanUp();
99057
99721
  for (const [sessionId, pending2] of this.pendingSessionDocs) {
99058
99722
  try {
@@ -99937,10 +100601,11 @@ ${value}`;
99937
100601
  return meta.meta;
99938
100602
  };
99939
100603
  class MachineDocument {
99940
- constructor(repo, workspaceId, machineId) {
100604
+ constructor(repo, workspaceId, machineId, markMachineFlockDirty) {
99941
100605
  this.repo = repo;
99942
100606
  this.workspaceId = workspaceId;
99943
100607
  this.machineId = machineId;
100608
+ this.markMachineFlockDirty = markMachineFlockDirty;
99944
100609
  this.roomId = getMachineRoomId(this.machineId);
99945
100610
  }
99946
100611
  roomId;
@@ -99980,7 +100645,11 @@ ${value}`;
99980
100645
  });
99981
100646
  if (changed) {
99982
100647
  await this.repo.flush();
99983
- await handle.syncOnce().catch(() => void 0);
100648
+ if (this.markMachineFlockDirty) {
100649
+ this.markMachineFlockDirty("rate-limit-update");
100650
+ } else {
100651
+ await handle.syncOnce().catch(() => void 0);
100652
+ }
99984
100653
  }
99985
100654
  });
99986
100655
  }
@@ -100013,7 +100682,11 @@ ${value}`;
100013
100682
  });
100014
100683
  if (changed) {
100015
100684
  await this.repo.flush();
100016
- await handle.syncOnce().catch(() => void 0);
100685
+ if (this.markMachineFlockDirty) {
100686
+ this.markMachineFlockDirty("acp-capability-update");
100687
+ } else {
100688
+ await handle.syncOnce().catch(() => void 0);
100689
+ }
100017
100690
  }
100018
100691
  }
100019
100692
  async getAcpCapabilities(cliType, agentType) {
@@ -102105,7 +102778,9 @@ The file is not available yet and could not be downloaded; ask the user to resen
102105
102778
  return remoteName;
102106
102779
  }
102107
102780
  async function probeGitHubRemoteAtRootPath(rootPath) {
102108
- await assertGitRepository(rootPath);
102781
+ if (!await isGitRepository(rootPath)) {
102782
+ return null;
102783
+ }
102109
102784
  const remotes = await listGitRemotes(rootPath);
102110
102785
  if (remotes.length === 0) return null;
102111
102786
  const currentBranchRemote = await resolveCurrentBranchRemote(rootPath, remotes);
@@ -117714,18 +118389,6 @@ ${fallbackStderrTail}` : errorMessage;
117714
118389
  function shouldScrubClaudeAuthEnv(cliType, agentType) {
117715
118390
  return cliType === "builtin" && agentType === "claude" || cliType === "registry" && agentType === "claude-p";
117716
118391
  }
117717
- async function getStaticBuiltinAcpCapabilities(agentType) {
117718
- if (!isBuiltinAgentType(agentType)) {
117719
- return void 0;
117720
- }
117721
- const baseline = agentType === "claude" ? (await import("./chunks/baseline-config-CcYq1mUH.js")).getClaudeBaselineConfig() : (await import("./chunks/baseline-config-BPa_f3S0.js")).getCodexBaselineConfig();
117722
- const configOptions = normalizeConfigOptions(baseline.configOptions);
117723
- return {
117724
- modes: baseline.modes,
117725
- models: baseline.models,
117726
- configOptions
117727
- };
117728
- }
117729
118392
  function isSelectGroup$1(item) {
117730
118393
  return typeof item === "object" && item !== null && "group" in item;
117731
118394
  }
@@ -117803,7 +118466,7 @@ ${fallbackStderrTail}` : errorMessage;
117803
118466
  async function fetchAcpCapabilities(cliType, agentType, logger2, env2, customAcp, runtimeOverrides, options = {}) {
117804
118467
  const allowStaticBuiltinCapabilities = options.allowStaticBuiltinCapabilities ?? true;
117805
118468
  if (allowStaticBuiltinCapabilities && cliType === "builtin" && !hasBuiltinRuntimeOverrideValues(runtimeOverrides)) {
117806
- const staticCapabilities = await getStaticBuiltinAcpCapabilities(agentType);
118469
+ const staticCapabilities = getStaticBuiltinAcpCapabilities(cliType, agentType, runtimeOverrides);
117807
118470
  if (staticCapabilities) {
117808
118471
  logger2.debug(`[acp-capabilities] Using static builtin capabilities (agentType=${agentType})`);
117809
118472
  return staticCapabilities;
@@ -121326,7 +121989,7 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
121326
121989
  ...flockLocalProjects
121327
121990
  };
121328
121991
  }
121329
- async function upsertMachineLocalProject(repo, workspaceId, machineId, project, nowMs2 = getServerNow()) {
121992
+ async function upsertMachineLocalProject(repo, workspaceId, machineId, project, nowMs2 = getServerNow(), options = {}) {
121330
121993
  const handle = await repo.openFlockDoc(getMachineFlockDocId(workspaceId, machineId));
121331
121994
  const changed = writeMachineFlockRowToFlock(handle.flock, {
121332
121995
  key: machineFlockKeys.localProject(project.id),
@@ -121336,14 +121999,26 @@ The postId is ${normalizedFeedbackPostId}. Use the feedback-progress-reporter sk
121336
121999
  return;
121337
122000
  }
121338
122001
  await repo.flush();
121339
- await handle.syncOnce();
122002
+ if (options.sync) {
122003
+ options.sync.markMachineFlockDocDirty(machineId, {
122004
+ reason: options.reason ?? "local-project-upsert"
122005
+ });
122006
+ } else {
122007
+ await handle.syncOnce().catch(() => void 0);
122008
+ }
121340
122009
  }
121341
- async function removeMachineLocalProject(repo, workspaceId, machineId, localProjectId, nowMs2 = getServerNow()) {
122010
+ async function removeMachineLocalProject(repo, workspaceId, machineId, localProjectId, nowMs2 = getServerNow(), options = {}) {
121342
122011
  const handle = await repo.openFlockDoc(getMachineFlockDocId(workspaceId, machineId));
121343
122012
  const changed = deleteMachineFlockRowFromFlock(handle.flock, machineFlockKeys.localProject(localProjectId), nowMs2);
121344
122013
  if (changed) {
121345
122014
  await repo.flush();
121346
- await handle.syncOnce().catch(() => void 0);
122015
+ if (options.sync) {
122016
+ options.sync.markMachineFlockDocDirty(machineId, {
122017
+ reason: options.reason ?? "local-project-remove"
122018
+ });
122019
+ } else {
122020
+ await handle.syncOnce().catch(() => void 0);
122021
+ }
121347
122022
  }
121348
122023
  const machineRoomId = getMachineRoomId(machineId);
121349
122024
  const current2 = await repo.getDocMeta(machineRoomId);
@@ -133763,7 +134438,10 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
133763
134438
  ]))
133764
134439
  }
133765
134440
  }
133766
- }, lastListedAt);
134441
+ }, lastListedAt, {
134442
+ sync: this.manager,
134443
+ reason: "local-project-history-sync"
134444
+ });
133767
134445
  });
133768
134446
  return catalog;
133769
134447
  }
@@ -139146,7 +139824,10 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
139146
139824
  rootPath: entry.rootPath,
139147
139825
  createdAtMs: previous?.createdAtMs ?? nowMs2,
139148
139826
  lastOpenedAtMs: nowMs2
139149
- }, nowMs2);
139827
+ }, nowMs2, {
139828
+ sync: this.workspaceDocument,
139829
+ reason: "local-project-add"
139830
+ });
139150
139831
  }
139151
139832
  async authorizeLocalProjectRoot(args2) {
139152
139833
  const access = await canUseMachineForCliToken({
@@ -148183,6 +148864,8 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
148183
148864
  await next2;
148184
148865
  }
148185
148866
  }
148867
+ const BUILTIN_AGENT_CONFIG_INITIAL_RETRY_DELAY_MS = 1e4;
148868
+ const BUILTIN_AGENT_CONFIG_MAX_RETRY_DELAY_MS = 5 * 6e4;
148186
148869
  class Lody {
148187
148870
  constructor(options, documentManager) {
148188
148871
  this.options = options;
@@ -148223,6 +148906,9 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
148223
148906
  runtime;
148224
148907
  supportRegistryAgentTypes;
148225
148908
  cleanedUp = false;
148909
+ builtinAgentConfigRetryTimer;
148910
+ pendingBuiltinAgentConfigRetryCliTypes = /* @__PURE__ */ new Set();
148911
+ builtinAgentConfigRetryAttempt = 0;
148226
148912
  static async create(options) {
148227
148913
  const manager = await LoroDocumentManager.create(options.workspaceId, options.userId, () => options.token, options.logger);
148228
148914
  return new Lody(options, manager);
@@ -148230,25 +148916,49 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
148230
148916
  async start() {
148231
148917
  void getLoginShellEnv();
148232
148918
  await this.runtime.initialize();
148919
+ this.documentManager.ensureMachineFlockDocJoined(this.machineId, {
148920
+ reason: "lody-start"
148921
+ });
148233
148922
  }
148234
148923
  async registerAgent(cliTypes) {
148235
148924
  await this.runtime.initialize();
148236
148925
  if (this.documentManager.hasCompletedInitialMetaSync()) {
148237
- await this.ensureBuiltinAgentConfigs(cliTypes);
148926
+ await this.ensureBuiltinAgentConfigsOrRetry(cliTypes);
148238
148927
  } else {
148239
148928
  this.logger.debug(`[agent-config] Initial meta sync is not complete for workspace ${this.workspaceId}; deferring builtin agent registration`);
148240
148929
  void this.documentManager.waitForInitialMetaSync().then(async (completed) => {
148241
148930
  if (!completed || this.cleanedUp) {
148242
148931
  return;
148243
148932
  }
148244
- await this.ensureBuiltinAgentConfigs(cliTypes);
148933
+ await this.ensureBuiltinAgentConfigsOrRetry(cliTypes);
148245
148934
  }).catch((error2) => {
148246
148935
  this.logger.debug(`[agent-config] Deferred builtin agent registration failed: ${formatErrorMessage(error2)}`);
148247
148936
  });
148248
148937
  }
148249
148938
  void this.refreshBuiltinCapabilities(cliTypes);
148250
148939
  }
148940
+ async ensureBuiltinAgentConfigsOrRetry(cliTypes) {
148941
+ if (this.cleanedUp) {
148942
+ return;
148943
+ }
148944
+ const completed = await this.ensureBuiltinAgentConfigs(cliTypes);
148945
+ if (!completed) {
148946
+ this.scheduleBuiltinAgentConfigRetry(cliTypes);
148947
+ return;
148948
+ }
148949
+ this.builtinAgentConfigRetryAttempt = 0;
148950
+ }
148251
148951
  async ensureBuiltinAgentConfigs(cliTypes) {
148952
+ if (cliTypes.length === 0) {
148953
+ return true;
148954
+ }
148955
+ const syncedMachineFlock = await this.documentManager.syncMachineFlockDoc(this.machineId, {
148956
+ reason: "builtin-agent-registration"
148957
+ });
148958
+ if (!syncedMachineFlock) {
148959
+ this.logger.debug(`[agent-config] Machine Flock sync is not complete for workspace ${this.workspaceId} machine ${this.machineId}; skipping builtin agent registration for this attempt`);
148960
+ return false;
148961
+ }
148252
148962
  const builtinDisplayName = {
148253
148963
  claude: "Claude Code",
148254
148964
  codex: "Codex"
@@ -148259,6 +148969,40 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
148259
148969
  await this.documentManager.createAgentConfig("builtin", cliType, this.machineId, builtinDisplayName[cliType]);
148260
148970
  }
148261
148971
  }
148972
+ return true;
148973
+ }
148974
+ scheduleBuiltinAgentConfigRetry(cliTypes) {
148975
+ if (cliTypes.length === 0 || this.cleanedUp) {
148976
+ return;
148977
+ }
148978
+ for (const cliType of cliTypes) {
148979
+ this.pendingBuiltinAgentConfigRetryCliTypes.add(cliType);
148980
+ }
148981
+ if (this.builtinAgentConfigRetryTimer) {
148982
+ return;
148983
+ }
148984
+ const delayMs = this.nextBuiltinAgentConfigRetryDelayMs();
148985
+ this.logger.debug(`[agent-config] Scheduling builtin agent registration retry in ${delayMs}ms for workspace ${this.workspaceId} machine ${this.machineId}`);
148986
+ this.builtinAgentConfigRetryTimer = setTimeout(() => {
148987
+ this.builtinAgentConfigRetryTimer = void 0;
148988
+ if (this.cleanedUp) {
148989
+ this.pendingBuiltinAgentConfigRetryCliTypes.clear();
148990
+ return;
148991
+ }
148992
+ const retryCliTypes = [
148993
+ ...this.pendingBuiltinAgentConfigRetryCliTypes
148994
+ ];
148995
+ this.pendingBuiltinAgentConfigRetryCliTypes.clear();
148996
+ void this.ensureBuiltinAgentConfigsOrRetry(retryCliTypes).catch((error2) => {
148997
+ this.logger.debug(`[agent-config] Retried builtin agent registration failed: ${formatErrorMessage(error2)}`);
148998
+ });
148999
+ }, delayMs);
149000
+ this.builtinAgentConfigRetryTimer.unref?.();
149001
+ }
149002
+ nextBuiltinAgentConfigRetryDelayMs() {
149003
+ const multiplier = 2 ** Math.min(this.builtinAgentConfigRetryAttempt, 5);
149004
+ this.builtinAgentConfigRetryAttempt += 1;
149005
+ return Math.min(BUILTIN_AGENT_CONFIG_INITIAL_RETRY_DELAY_MS * multiplier, BUILTIN_AGENT_CONFIG_MAX_RETRY_DELAY_MS);
148262
149006
  }
148263
149007
  async refreshBuiltinCapabilities(cliTypes) {
148264
149008
  for (const cliType of cliTypes) {
@@ -148289,6 +149033,12 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
148289
149033
  }
148290
149034
  cleanup = async () => {
148291
149035
  this.cleanedUp = true;
149036
+ if (this.builtinAgentConfigRetryTimer) {
149037
+ clearTimeout(this.builtinAgentConfigRetryTimer);
149038
+ this.builtinAgentConfigRetryTimer = void 0;
149039
+ }
149040
+ this.pendingBuiltinAgentConfigRetryCliTypes.clear();
149041
+ this.builtinAgentConfigRetryAttempt = 0;
148292
149042
  return await this.runtime.cleanup();
148293
149043
  };
148294
149044
  async dispatchLocalControl(message) {
@@ -150498,10 +151248,16 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
150498
151248
  rootPath: entry.rootPath,
150499
151249
  createdAtMs: previous?.createdAtMs ?? nowMs2,
150500
151250
  lastOpenedAtMs: nowMs2
150501
- }, nowMs2);
151251
+ }, nowMs2, {
151252
+ sync: runtime.lody.documentManager,
151253
+ reason: "local-project-add"
151254
+ });
150502
151255
  }
150503
151256
  async removeProjectMetaInWorkspace(runtime, localProjectId) {
150504
- await removeMachineLocalProject(runtime.lody.documentManager.repo, runtime.workspace.id, this.machineId, localProjectId);
151257
+ await removeMachineLocalProject(runtime.lody.documentManager.repo, runtime.workspace.id, this.machineId, localProjectId, void 0, {
151258
+ sync: runtime.lody.documentManager,
151259
+ reason: "local-project-delete"
151260
+ });
150505
151261
  }
150506
151262
  async listProjectsByWorkspace() {
150507
151263
  const groups = [];
@@ -177371,6 +178127,29 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
177371
178127
  throw new Error(`Workspace metadata changes were not confirmed by Loro Streams (${reason}). Retry the command after checking network connectivity.`);
177372
178128
  }
177373
178129
  }
178130
+ function buildOfflineHint(error2) {
178131
+ return new Error(`${formatErrorMessage(error2)} Use --offline to read the local cache without syncing.`, {
178132
+ cause: error2
178133
+ });
178134
+ }
178135
+ async function syncWorkspaceMetaForRead(manager, reason) {
178136
+ try {
178137
+ await manager.syncMetaOrThrow({
178138
+ reason
178139
+ });
178140
+ } catch (error2) {
178141
+ throw buildOfflineHint(error2);
178142
+ }
178143
+ }
178144
+ async function syncDocForRead(manager, docId, reason) {
178145
+ try {
178146
+ await manager.syncDocOrThrow(docId, {
178147
+ reason
178148
+ });
178149
+ } catch (error2) {
178150
+ throw buildOfflineHint(error2);
178151
+ }
178152
+ }
177374
178153
  async function listAliveRoomIds(manager, predicate) {
177375
178154
  const scanner = manager.repo.getMeta();
177376
178155
  if (!scanner) {
@@ -177549,16 +178328,19 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
177549
178328
  await action();
177550
178329
  await exitOneShotCommand(0);
177551
178330
  } catch (error2) {
178331
+ const commandError = error2 && typeof error2 === "object" ? error2 : void 0;
177552
178332
  const message = formatErrorMessage(error2);
177553
- if (options.json || options.jsonl) {
177554
- printJson({
177555
- ok: false,
177556
- error: message
177557
- });
177558
- } else {
177559
- getLogger(loggerName).error(message);
178333
+ if (commandError?.suppressCommandErrorOutput !== true) {
178334
+ if (options.json || options.jsonl) {
178335
+ printJson({
178336
+ ok: false,
178337
+ error: message
178338
+ });
178339
+ } else {
178340
+ getLogger(loggerName).error(message);
178341
+ }
177560
178342
  }
177561
- await exitOneShotCommand(1);
178343
+ await exitOneShotCommand(commandError?.exitCode ?? 1);
177562
178344
  }
177563
178345
  }
177564
178346
  var debug_1;
@@ -180288,16 +181070,28 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
180288
181070
  configOptionValues
180289
181071
  };
180290
181072
  }
180291
- const agentConfigListCommand = new Command("list").description("List agent configs in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--json", "Print JSON output").option("--debug", "Enable debug output").action(async (options) => {
181073
+ const agentConfigListCommand = new Command("list").description("List agent configs in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--machine <idOrName>", "Only include configs for one machine").option("--json", "Print JSON output").option("--debug", "Enable debug output").action(async (options) => {
180292
181074
  await runOneShotCommand("agent-config", options, async () => {
180293
181075
  const auth = getAuthContextOrThrow$1("agent-config");
180294
181076
  const workspace = await resolveWorkspaceOrThrow$1(auth, options.workspace);
180295
181077
  await withWorkspaceManager$1(auth, workspace, "agent-config", async (manager) => {
180296
- const configs = await listAgentConfigsForWorkspace$1(manager, workspace.id);
181078
+ const machineSelector = normalizeCliValue(options.machine);
181079
+ let machineId;
181080
+ if (machineSelector) {
181081
+ const machine = resolveMachineOrThrow(await listMachineMetasForWorkspace(manager), {
181082
+ selector: machineSelector,
181083
+ authMachineId: auth.machineId
181084
+ });
181085
+ machineId = machine.id;
181086
+ }
181087
+ const configs = (await listAgentConfigsForWorkspace$1(manager, workspace.id)).filter((config2) => machineId === void 0 || config2.machineId === machineId);
180297
181088
  if (options.json) {
180298
181089
  printJson({
180299
181090
  ok: true,
180300
181091
  workspaceId: workspace.id,
181092
+ ...machineId ? {
181093
+ machineId
181094
+ } : {},
180301
181095
  agentConfigs: configs.map(toAgentConfigOutput)
180302
181096
  });
180303
181097
  return;
@@ -180754,13 +181548,21 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
180754
181548
  }
180755
181549
  throw new Error(`Agent config not found: ${normalizedSelector}. Candidates: ${formatAgentConfigCandidates(configs)}`);
180756
181550
  }
181551
+ function resolveCreateAgentSelector(options) {
181552
+ const agent2 = normalizeCliValue(options.agent);
181553
+ const agentConfig = normalizeCliValue(options.agentConfig);
181554
+ if (agent2 && agentConfig && agent2 !== agentConfig) {
181555
+ throw new Error("Pass either --agent or --agent-config, not both.");
181556
+ }
181557
+ return agentConfig ?? agent2;
181558
+ }
180757
181559
  function buildAgentPrompt(prompt2, agentPrompt = "") {
180758
181560
  return [
180759
181561
  agentPrompt,
180760
181562
  prompt2
180761
181563
  ].filter((part) => part?.trim()).join("\n\n");
180762
181564
  }
180763
- function parsePositiveIntOption(value) {
181565
+ function parsePositiveIntOption$1(value) {
180764
181566
  const parsed = Number.parseInt(value, 10);
180765
181567
  if (!Number.isFinite(parsed) || parsed <= 0) {
180766
181568
  throw new Error(`Invalid numeric value: ${value}`);
@@ -180847,6 +181649,9 @@ ${page}${helpTipBottom}${choiceDescription}${ansiEscapes.cursorHide}`;
180847
181649
  return entries.map((entry) => `[${entry.role}] ${entry.timestamp} ${entry.id}
180848
181650
  ${entry.text}`).join("\n\n");
180849
181651
  }
181652
+ function renderAssistantTurnCompletion(content) {
181653
+ return extractTranscriptText(content, "assistant") ?? "No visible assistant reply found.";
181654
+ }
180850
181655
  async function readStdinText() {
180851
181656
  const chunks = [];
180852
181657
  return await new Promise((resolve2, reject) => {
@@ -181147,15 +181952,22 @@ ${entry.text}`).join("\n\n");
181147
181952
  const effectiveSelector = normalizeCliValue(selector) ?? normalizeCliValue(process.env.LODY_WORKSPACE_ID);
181148
181953
  return selectWorkspaceSummary(workspaces, effectiveSelector);
181149
181954
  }
181150
- async function resolveWorkspaceForSessionOrThrow(auth, sessionId, selector) {
181955
+ async function resolveWorkspaceForSessionOrThrow(auth, sessionId, options) {
181151
181956
  const workspaces = await listWorkspacesForToken(auth.token);
181957
+ const selector = typeof options === "string" ? options : options?.workspace;
181958
+ const shouldSync = typeof options === "object" && options.offline !== true;
181959
+ const syncReason = typeof options === "object" ? options.reason : void 0;
181152
181960
  const effectiveSelector = normalizeCliValue(selector) ?? normalizeCliValue(process.env.LODY_WORKSPACE_ID);
181961
+ const sessionExistsInWorkspace = async (workspace) => await withWorkspaceManager(auth, workspace, async (manager) => {
181962
+ if (shouldSync) {
181963
+ await syncWorkspaceMetaForRead(manager, syncReason ?? `session.resolve:${sessionId}:${workspace.id}`);
181964
+ }
181965
+ const raw2 = await manager.repo.getDocMeta(getSessionRoomId(sessionId));
181966
+ return !!raw2?.meta && !isLoroRepoDocDeleted(raw2);
181967
+ });
181153
181968
  if (effectiveSelector) {
181154
181969
  const workspace = selectWorkspaceSummary(workspaces, effectiveSelector);
181155
- const exists = await withWorkspaceManager(auth, workspace, async (manager) => {
181156
- const raw2 = await manager.repo.getDocMeta(getSessionRoomId(sessionId));
181157
- return !!raw2?.meta && !isLoroRepoDocDeleted(raw2);
181158
- });
181970
+ const exists = await sessionExistsInWorkspace(workspace);
181159
181971
  if (!exists) {
181160
181972
  throw new Error(`Session not found in workspace ${workspace.id}: ${sessionId}`);
181161
181973
  }
@@ -181163,10 +181975,7 @@ ${entry.text}`).join("\n\n");
181163
181975
  }
181164
181976
  if (workspaces.length === 1) {
181165
181977
  const workspace = workspaces[0];
181166
- const exists = await withWorkspaceManager(auth, workspace, async (manager) => {
181167
- const raw2 = await manager.repo.getDocMeta(getSessionRoomId(sessionId));
181168
- return !!raw2?.meta && !isLoroRepoDocDeleted(raw2);
181169
- });
181978
+ const exists = await sessionExistsInWorkspace(workspace);
181170
181979
  if (!exists) {
181171
181980
  throw new Error(`Session not found: ${sessionId}`);
181172
181981
  }
@@ -181174,10 +181983,7 @@ ${entry.text}`).join("\n\n");
181174
181983
  }
181175
181984
  const matches = [];
181176
181985
  for (const workspace of workspaces) {
181177
- const exists = await withWorkspaceManager(auth, workspace, async (manager) => {
181178
- const raw2 = await manager.repo.getDocMeta(getSessionRoomId(sessionId));
181179
- return !!raw2?.meta && !isLoroRepoDocDeleted(raw2);
181180
- });
181986
+ const exists = await sessionExistsInWorkspace(workspace);
181181
181987
  if (exists) {
181182
181988
  matches.push(workspace);
181183
181989
  }
@@ -181190,6 +181996,13 @@ ${entry.text}`).join("\n\n");
181190
181996
  }
181191
181997
  return matches[0];
181192
181998
  }
181999
+ async function syncSessionReadData(manager, sessionId, offline, reason) {
182000
+ if (offline === true) {
182001
+ return;
182002
+ }
182003
+ await syncWorkspaceMetaForRead(manager, `${reason}:meta`);
182004
+ await syncDocForRead(manager, getSessionRoomId(sessionId), `${reason}:doc`);
182005
+ }
181193
182006
  async function resolveSessionMetaOrThrow(manager, sessionId) {
181194
182007
  const raw2 = await manager.repo.getDocMeta(getSessionRoomId(sessionId));
181195
182008
  if (!raw2?.meta || isLoroRepoDocDeleted(raw2)) {
@@ -181524,6 +182337,37 @@ ${entry.text}`).join("\n\n");
181524
182337
  messageQueueCount: docState?.mq?.length ?? 0
181525
182338
  };
181526
182339
  }
182340
+ async function buildSessionStatusResult(workspace, manager, sessionId) {
182341
+ const session = await resolveSessionMetaOrThrow(manager, sessionId);
182342
+ const sessionDoc = await manager.getOrCreateSessionDoc(sessionId);
182343
+ const history = await sessionDoc.getHistory();
182344
+ const assistantTurnId = resolveActiveAssistantTurnId(history);
182345
+ return {
182346
+ workspace,
182347
+ sessionId,
182348
+ status: session.status,
182349
+ machineId: session.machineId,
182350
+ agent: {
182351
+ cliType: session.cliType,
182352
+ agentType: session.agentType,
182353
+ ...session.agentConfigId ? {
182354
+ agentConfigId: session.agentConfigId
182355
+ } : {}
182356
+ },
182357
+ archived: session.isArchived === true,
182358
+ ...assistantTurnId ? {
182359
+ activeTurn: {
182360
+ assistantTurnId,
182361
+ ...session.processingUserMsgId ? {
182362
+ processingUserMsgId: session.processingUserMsgId
182363
+ } : {},
182364
+ ...session.latestUserMsgId ? {
182365
+ latestUserMsgId: session.latestUserMsgId
182366
+ } : {}
182367
+ }
182368
+ } : {}
182369
+ };
182370
+ }
181527
182371
  function printHumanSessionList(sessions) {
181528
182372
  if (sessions.length === 0) {
181529
182373
  console.log("No sessions found.");
@@ -181571,6 +182415,16 @@ ${entry.text}`).join("\n\n");
181571
182415
  console.log(`createdAt: ${session.createdAt}`);
181572
182416
  console.log(`lastHistoryAt: ${result.latestHistoryAt ?? "-"}`);
181573
182417
  }
182418
+ function printHumanSessionStatus(result) {
182419
+ console.log(`id: ${result.sessionId}`);
182420
+ console.log(`workspace: ${result.workspace.slug ?? result.workspace.id}`);
182421
+ console.log(`machine: ${result.machineId}`);
182422
+ console.log(`status: ${result.status?.type ?? "unknown"}`);
182423
+ console.log(`archived: ${result.archived ? "yes" : "no"}`);
182424
+ console.log(`agent: ${result.agent.cliType}/${result.agent.agentType}`);
182425
+ console.log(`agentConfigId: ${result.agent.agentConfigId ?? "-"}`);
182426
+ console.log(`activeTurn: ${result.activeTurn?.assistantTurnId ?? "-"}`);
182427
+ }
181574
182428
  async function runSessionCommand(options, action) {
181575
182429
  if (options.debug) {
181576
182430
  rootLogger.setDebug(true);
@@ -181629,7 +182483,7 @@ ${entry.text}`).join("\n\n");
181629
182483
  process.exit(code2);
181630
182484
  }
181631
182485
  }
181632
- const sessionCreateCommand = new Command("create").description("Create a new session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--agent-config <idOrName>", "Agent config id or name").option("--title <title>", "Session title").option("--repo <owner/repo>", "GitHub repository to attach").option("--local-project <id|name|path>", "Local project id, name, or root path").option("--worktree", "Create an isolated git worktree for --local-project").option("--branch <name>", "Git branch to use for GitHub repos or local git projects").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--env <keyValue>", "Deprecated per-session env override; configure env on the agent config instead", collectListOption, []).option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--timeout <seconds>", "Wait timeout in seconds for structured output", parsePositiveIntOption).option("--debug", "Enable debug output").argument("[prompt]", "Prompt text").action(async (promptArg, options) => {
182486
+ const sessionCreateCommand = new Command("create").description("Create a new session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--agent <idOrName>", "Agent config id or name").option("--agent-config <idOrName>", "Agent config id or name").option("--title <title>", "Session title").option("--repo <owner/repo>", "GitHub repository to attach").option("--local-project <id|name|path>", "Local project id, name, or root path").option("--worktree", "Create an isolated git worktree for --local-project").option("--branch <name>", "Git branch to use for GitHub repos or local git projects").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--env <keyValue>", "Deprecated per-session env override; configure env on the agent config instead", collectListOption, []).option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--wait", "Wait for the assistant turn to complete before exiting").option("--timeout <seconds>", "Wait timeout in seconds for --wait, --json, and --jsonl", parsePositiveIntOption$1).option("--debug", "Enable debug output").argument("[prompt]", "Prompt text").action(async (promptArg, options) => {
181633
182487
  await runSessionCommand(options, async () => {
181634
182488
  const outputMode = resolveStructuredOutputMode(options);
181635
182489
  const createStartMs = Date.now();
@@ -181642,12 +182496,16 @@ ${entry.text}`).join("\n\n");
181642
182496
  const prompt2 = await readPromptText(options, promptArg);
181643
182497
  await ensureLocalRuntimeAvailable(auth.machineId, workspace.id);
181644
182498
  await withWorkspaceManager(auth, workspace, async (manager) => {
181645
- const agentConfig = await resolveAgentConfigOrThrow(manager, workspace.id, options.agentConfig);
182499
+ const agentSelector = resolveCreateAgentSelector(options);
182500
+ const agentConfig = await resolveAgentConfigOrThrow(manager, workspace.id, agentSelector);
181646
182501
  const dispatchConfig = resolveTurnDispatchConfig({
181647
182502
  mode: options.mode,
181648
182503
  model: options.model
181649
182504
  });
181650
- const result = await createSessionResult(auth, workspace, manager, prompt2, options, agentConfig, dispatchConfig, outputMode === "human" ? void 0 : {
182505
+ const result = await createSessionResult(auth, workspace, manager, prompt2, options, agentConfig, dispatchConfig, outputMode === "human" ? options.wait === true ? {
182506
+ outputMode: "json",
182507
+ timeoutMs: resolveStructuredOutputTimeoutMs(options.timeout)
182508
+ } : void 0 : {
181651
182509
  outputMode,
181652
182510
  timeoutMs: resolveStructuredOutputTimeoutMs(options.timeout),
181653
182511
  onEvent: outputMode === "jsonl" ? (event) => printJson(event) : void 0
@@ -181698,13 +182556,29 @@ ${entry.text}`).join("\n\n");
181698
182556
  }
181699
182557
  return;
181700
182558
  }
182559
+ console.log(result.sessionId);
182560
+ if (options.wait === true) {
182561
+ const completionPromise = result.completionPromise;
182562
+ if (!completionPromise) {
182563
+ throw new Error("Missing completion promise for session create --wait output.");
182564
+ }
182565
+ const completedTurn = await completionPromise;
182566
+ captureSessionCommandEvent("session_create_succeeded", {
182567
+ output_mode: outputMode,
182568
+ turn_duration_ms: completedTurn.durationMs
182569
+ }, {
182570
+ distinctId: auth.machineId
182571
+ });
182572
+ console.log("");
182573
+ console.log(renderAssistantTurnCompletion(completedTurn.content));
182574
+ return;
182575
+ }
181701
182576
  captureSessionCommandEvent("session_create_succeeded", {
181702
182577
  output_mode: outputMode,
181703
182578
  turn_duration_ms: Date.now() - createStartMs
181704
182579
  }, {
181705
182580
  distinctId: auth.machineId
181706
182581
  });
181707
- console.log(result.sessionId);
181708
182582
  });
181709
182583
  } catch (error2) {
181710
182584
  captureSessionCommandEvent("session_create_failed", {
@@ -181715,7 +182589,7 @@ ${entry.text}`).join("\n\n");
181715
182589
  }
181716
182590
  });
181717
182591
  });
181718
- const sessionChatCommand = new Command("chat").description("Send a new user prompt to an existing session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--timeout <seconds>", "Wait timeout in seconds for structured output", parsePositiveIntOption).option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").argument("[prompt]", "Prompt text").action(async (sessionIdArg, promptArg, options) => {
182592
+ const sessionChatCommand = new Command("chat").description("Send a new user prompt to an existing session on the current machine").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--mode <modeId>", "ACP mode override").option("--model <modelId>", "ACP model override").option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Read prompt text from file, or - for stdin").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--wait", "Wait for the assistant turn to complete before exiting").option("--timeout <seconds>", "Wait timeout in seconds for --wait, --json, and --jsonl", parsePositiveIntOption$1).option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").argument("[prompt]", "Prompt text").action(async (sessionIdArg, promptArg, options) => {
181719
182593
  await runSessionCommand(options, async () => {
181720
182594
  const outputMode = resolveStructuredOutputMode(options);
181721
182595
  const auth = getAuthContextOrThrow();
@@ -181762,15 +182636,16 @@ ${entry.text}`).join("\n\n");
181762
182636
  configOptionValues: dispatchConfig.configOptionValues,
181763
182637
  resume: session.acpSessionId ?? void 0
181764
182638
  }));
181765
- const completionAbortController = outputMode === "human" ? void 0 : new AbortController();
181766
- const completionPromise = outputMode === "human" ? void 0 : waitForTurnCompletion({
182639
+ const shouldWaitForCompletion = outputMode !== "human" || options.wait === true;
182640
+ const completionAbortController = shouldWaitForCompletion ? new AbortController() : void 0;
182641
+ const completionPromise = shouldWaitForCompletion ? waitForTurnCompletion({
181767
182642
  sessionDoc,
181768
182643
  userTurnId,
181769
- outputMode,
182644
+ outputMode: outputMode === "human" ? "json" : outputMode,
181770
182645
  timeoutMs: resolveStructuredOutputTimeoutMs(options.timeout),
181771
182646
  signal: completionAbortController?.signal,
181772
182647
  onEvent: outputMode === "jsonl" ? (event) => printJson(event) : void 0
181773
- });
182648
+ }) : void 0;
181774
182649
  try {
181775
182650
  await updateSessionActivityTimestampsBestEffort(manager, sessionId);
181776
182651
  await ensureSessionDocSynced(sessionDoc, `session.chat:${sessionId}:${userTurnId}`);
@@ -181811,6 +182686,18 @@ ${entry.text}`).join("\n\n");
181811
182686
  }
181812
182687
  return;
181813
182688
  }
182689
+ if (options.wait === true) {
182690
+ try {
182691
+ if (!completionPromise) {
182692
+ throw new Error("Missing completion promise for session chat --wait output.");
182693
+ }
182694
+ const completedTurn = await completionPromise;
182695
+ console.log(renderAssistantTurnCompletion(completedTurn.content));
182696
+ } catch (error2) {
182697
+ throw buildStructuredWaitError("json", sessionId, userTurnId, error2);
182698
+ }
182699
+ return;
182700
+ }
181814
182701
  console.log(userTurnId);
181815
182702
  });
181816
182703
  });
@@ -181852,11 +182739,14 @@ ${entry.text}`).join("\n\n");
181852
182739
  });
181853
182740
  });
181854
182741
  });
181855
- const sessionListCommand = new Command("list").description("List sessions in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--archived", "Only include archived sessions").option("--all", "Include active and archived sessions").option("--limit <count>", "Maximum number of sessions to print", parsePositiveIntOption).option("--json", "Print JSON output").option("--debug", "Enable debug output").action(async (options) => {
182742
+ const sessionListCommand = new Command("list").description("List sessions in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--archived", "Only include archived sessions").option("--all", "Include active and archived sessions").option("--limit <count>", "Maximum number of sessions to print", parsePositiveIntOption$1).option("--offline", "Read the local cache without syncing first").option("--json", "Print JSON output").option("--debug", "Enable debug output").action(async (options) => {
181856
182743
  await runSessionCommand(options, async () => {
181857
182744
  const auth = getAuthContextOrThrow();
181858
182745
  const workspace = await resolveWorkspaceOrThrow(auth, options.workspace);
181859
182746
  await withWorkspaceManager(auth, workspace, async (manager) => {
182747
+ if (options.offline !== true) {
182748
+ await syncWorkspaceMetaForRead(manager, `session.list:${workspace.id}`);
182749
+ }
181860
182750
  const sessions = sortSessionMetas(filterSessionMetas(await listSessionMetasForWorkspace(manager), {
181861
182751
  archivedOnly: options.archived,
181862
182752
  includeAll: options.all
@@ -181874,7 +182764,7 @@ ${entry.text}`).join("\n\n");
181874
182764
  });
181875
182765
  });
181876
182766
  });
181877
- const sessionHistoryCommand = new Command("history").description("Read visible session transcript history").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--limit <count>", "Maximum number of transcript turns to print", parsePositiveIntOption).option("--all", "Include all transcript turns").option("--reverse", "Print newest transcript turns first").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").action(async (sessionIdArg, options) => {
182767
+ const sessionHistoryCommand = new Command("history").description("Read visible session transcript history").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--limit <count>", "Maximum number of transcript turns to print", parsePositiveIntOption$1).option("--all", "Include all transcript turns").option("--reverse", "Print newest transcript turns first").option("--offline", "Read the local cache without syncing first").option("--json", "Print JSON output").option("--jsonl", "Print JSON Lines output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").action(async (sessionIdArg, options) => {
181878
182768
  await runSessionCommand(options, async () => {
181879
182769
  const outputMode = resolveStructuredOutputMode(options);
181880
182770
  if (options.all && typeof options.limit === "number") {
@@ -181885,8 +182775,13 @@ ${entry.text}`).join("\n\n");
181885
182775
  if (!sessionId) {
181886
182776
  throw new Error("Missing session ID. Pass one explicitly or set LODY_SESSION_ID.");
181887
182777
  }
181888
- const workspace = await resolveWorkspaceForSessionOrThrow(auth, sessionId, options.workspace);
182778
+ const workspace = await resolveWorkspaceForSessionOrThrow(auth, sessionId, {
182779
+ workspace: options.workspace,
182780
+ offline: options.offline,
182781
+ reason: `session.history.resolve:${sessionId}`
182782
+ });
181889
182783
  await withWorkspaceManager(auth, workspace, async (manager) => {
182784
+ await syncSessionReadData(manager, sessionId, options.offline, `session.history:${sessionId}`);
181890
182785
  await resolveSessionMetaOrThrow(manager, sessionId);
181891
182786
  const sessionDoc = await manager.getOrCreateSessionDoc(sessionId);
181892
182787
  const transcript = toSessionTranscriptEntries(await sessionDoc.getHistory());
@@ -181920,15 +182815,20 @@ ${entry.text}`).join("\n\n");
181920
182815
  });
181921
182816
  });
181922
182817
  });
181923
- const sessionShowCommand = new Command("show").description("Show session metadata").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--json", "Print JSON output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").action(async (sessionIdArg, options) => {
182818
+ const sessionShowCommand = new Command("show").description("Show session metadata").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--offline", "Read the local cache without syncing first").option("--json", "Print JSON output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").action(async (sessionIdArg, options) => {
181924
182819
  await runSessionCommand(options, async () => {
181925
182820
  const auth = getAuthContextOrThrow();
181926
182821
  const sessionId = normalizeCliValue(sessionIdArg) ?? normalizeCliValue(process.env.LODY_SESSION_ID);
181927
182822
  if (!sessionId) {
181928
182823
  throw new Error("Missing session ID. Pass one explicitly or set LODY_SESSION_ID.");
181929
182824
  }
181930
- const workspace = await resolveWorkspaceForSessionOrThrow(auth, sessionId, options.workspace);
182825
+ const workspace = await resolveWorkspaceForSessionOrThrow(auth, sessionId, {
182826
+ workspace: options.workspace,
182827
+ offline: options.offline,
182828
+ reason: `session.show.resolve:${sessionId}`
182829
+ });
181931
182830
  await withWorkspaceManager(auth, workspace, async (manager) => {
182831
+ await syncSessionReadData(manager, sessionId, options.offline, `session.show:${sessionId}`);
181932
182832
  const result = await buildSessionShowResult(workspace, manager, sessionId);
181933
182833
  if (options.json) {
181934
182834
  printJson({
@@ -181941,6 +182841,32 @@ ${entry.text}`).join("\n\n");
181941
182841
  });
181942
182842
  });
181943
182843
  });
182844
+ const sessionStatusCommand = new Command("status").description("Show current session status").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--offline", "Read the local cache without syncing first").option("--json", "Print JSON output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").action(async (sessionIdArg, options) => {
182845
+ await runSessionCommand(options, async () => {
182846
+ const auth = getAuthContextOrThrow();
182847
+ const sessionId = normalizeCliValue(sessionIdArg) ?? normalizeCliValue(process.env.LODY_SESSION_ID);
182848
+ if (!sessionId) {
182849
+ throw new Error("Missing session ID. Pass one explicitly or set LODY_SESSION_ID.");
182850
+ }
182851
+ const workspace = await resolveWorkspaceForSessionOrThrow(auth, sessionId, {
182852
+ workspace: options.workspace,
182853
+ offline: options.offline,
182854
+ reason: `session.status.resolve:${sessionId}`
182855
+ });
182856
+ await withWorkspaceManager(auth, workspace, async (manager) => {
182857
+ await syncSessionReadData(manager, sessionId, options.offline, `session.status:${sessionId}`);
182858
+ const result = await buildSessionStatusResult(workspace, manager, sessionId);
182859
+ if (options.json) {
182860
+ printJson({
182861
+ ok: true,
182862
+ ...result
182863
+ });
182864
+ return;
182865
+ }
182866
+ printHumanSessionStatus(result);
182867
+ });
182868
+ });
182869
+ });
181944
182870
  const sessionRenameCommand = new Command("rename").description("Rename a session").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--title <title>", "New session title").option("--json", "Print JSON output").option("--debug", "Enable debug output").argument("[sessionId]", "Session ID; falls back to LODY_SESSION_ID").argument("[title]", "New session title").action(async (sessionIdArg, titleArg, options) => {
181945
182871
  await runSessionCommand(options, async () => {
181946
182872
  const auth = getAuthContextOrThrow();
@@ -182149,7 +183075,270 @@ ${entry.text}`).join("\n\n");
182149
183075
  });
182150
183076
  });
182151
183077
  });
182152
- const sessionCommand = new Command("session").description("Manage sessions without the web UI").addCommand(sessionCreateCommand).addCommand(sessionChatCommand).addCommand(sessionCancelCommand).addCommand(sessionListCommand).addCommand(sessionHistoryCommand).addCommand(sessionShowCommand).addCommand(sessionRenameCommand).addCommand(sessionArchiveCommand).addCommand(sessionRestoreCommand).addCommand(sessionDeleteCommand);
183078
+ const sessionCommand = new Command("session").description("Manage sessions without the web UI").addCommand(sessionCreateCommand).addCommand(sessionChatCommand).addCommand(sessionCancelCommand).addCommand(sessionListCommand).addCommand(sessionHistoryCommand).addCommand(sessionShowCommand).addCommand(sessionStatusCommand).addCommand(sessionRenameCommand).addCommand(sessionArchiveCommand).addCommand(sessionRestoreCommand).addCommand(sessionDeleteCommand);
183079
+ async function mapWithConcurrency(items2, concurrency, worker) {
183080
+ if (items2.length === 0) {
183081
+ return [];
183082
+ }
183083
+ const limit2 = Math.max(1, Math.floor(concurrency));
183084
+ const results = new Array(items2.length);
183085
+ let nextIndex = 0;
183086
+ const runWorker = async () => {
183087
+ while (nextIndex < items2.length) {
183088
+ const currentIndex = nextIndex;
183089
+ nextIndex += 1;
183090
+ results[currentIndex] = await worker(items2[currentIndex], currentIndex);
183091
+ }
183092
+ };
183093
+ await Promise.all(Array.from({
183094
+ length: Math.min(limit2, items2.length)
183095
+ }, () => runWorker()));
183096
+ return results;
183097
+ }
183098
+ const DEFAULT_SYNC_CONCURRENCY = 4;
183099
+ function parsePositiveIntOption(value) {
183100
+ const parsed = Number.parseInt(value, 10);
183101
+ if (!Number.isFinite(parsed) || parsed <= 0) {
183102
+ throw new Error(`Invalid numeric value: ${value}`);
183103
+ }
183104
+ return parsed;
183105
+ }
183106
+ function createWorkspaceSummary(workspaceId) {
183107
+ return {
183108
+ workspaceId,
183109
+ totals: {
183110
+ meta: 0,
183111
+ doc: 0,
183112
+ flock: 0
183113
+ },
183114
+ completed: {
183115
+ meta: 0,
183116
+ doc: 0,
183117
+ flock: 0
183118
+ },
183119
+ failed: {
183120
+ meta: 0,
183121
+ doc: 0,
183122
+ flock: 0
183123
+ },
183124
+ failures: []
183125
+ };
183126
+ }
183127
+ function mergeSummaries(workspaces) {
183128
+ const failures2 = workspaces.flatMap((workspace) => workspace.failures);
183129
+ let total = 0;
183130
+ let completed = 0;
183131
+ let failed = 0;
183132
+ for (const workspace of workspaces) {
183133
+ for (const kind of [
183134
+ "meta",
183135
+ "doc",
183136
+ "flock"
183137
+ ]) {
183138
+ total += workspace.totals[kind];
183139
+ completed += workspace.completed[kind];
183140
+ failed += workspace.failed[kind];
183141
+ }
183142
+ }
183143
+ return {
183144
+ ok: failures2.length === 0,
183145
+ workspaces,
183146
+ total,
183147
+ completed,
183148
+ failed,
183149
+ failures: failures2
183150
+ };
183151
+ }
183152
+ function buildProgressEvent(input2) {
183153
+ return {
183154
+ type: "progress",
183155
+ workspaceId: input2.workspaceId,
183156
+ kind: input2.kind,
183157
+ id: input2.id,
183158
+ total: input2.total,
183159
+ completed: input2.completed,
183160
+ failed: input2.failed,
183161
+ remaining: Math.max(0, input2.total - input2.completed - input2.failed),
183162
+ ok: input2.ok,
183163
+ ...input2.error ? {
183164
+ error: input2.error
183165
+ } : {}
183166
+ };
183167
+ }
183168
+ function printHumanProgress(event) {
183169
+ const status = event.ok ? "synced" : "failed";
183170
+ const failedText = event.failed > 0 ? `, failed ${event.failed}` : "";
183171
+ console.log(`[${event.workspaceId}] ${event.kind} ${event.id}: ${status} (${event.completed}/${event.total}${failedText})`);
183172
+ if (event.error) {
183173
+ console.log(` ${event.error}`);
183174
+ }
183175
+ }
183176
+ function emitProgress(event, outputMode) {
183177
+ if (outputMode === "jsonl") {
183178
+ printJson(event);
183179
+ return;
183180
+ }
183181
+ if (outputMode === "human") {
183182
+ printHumanProgress(event);
183183
+ }
183184
+ }
183185
+ function recordSyncResult(args2) {
183186
+ if (args2.ok) {
183187
+ args2.summary.completed[args2.kind] += 1;
183188
+ } else {
183189
+ args2.summary.failed[args2.kind] += 1;
183190
+ args2.summary.failures.push({
183191
+ workspaceId: args2.summary.workspaceId,
183192
+ kind: args2.kind,
183193
+ id: args2.id,
183194
+ error: args2.error ?? "Sync failed."
183195
+ });
183196
+ }
183197
+ emitProgress(buildProgressEvent({
183198
+ workspaceId: args2.summary.workspaceId,
183199
+ kind: args2.kind,
183200
+ id: args2.id,
183201
+ total: args2.summary.totals[args2.kind],
183202
+ completed: args2.summary.completed[args2.kind],
183203
+ failed: args2.summary.failed[args2.kind],
183204
+ ok: args2.ok,
183205
+ error: args2.error
183206
+ }), args2.outputMode);
183207
+ }
183208
+ async function syncItems(input2) {
183209
+ input2.summary.totals[input2.kind] = input2.ids.length;
183210
+ await mapWithConcurrency(input2.ids, input2.concurrency, async (id2) => {
183211
+ try {
183212
+ await input2.syncOne(id2);
183213
+ recordSyncResult({
183214
+ summary: input2.summary,
183215
+ kind: input2.kind,
183216
+ id: id2,
183217
+ ok: true,
183218
+ outputMode: input2.outputMode
183219
+ });
183220
+ } catch (error2) {
183221
+ recordSyncResult({
183222
+ summary: input2.summary,
183223
+ kind: input2.kind,
183224
+ id: id2,
183225
+ ok: false,
183226
+ error: formatErrorMessage(error2),
183227
+ outputMode: input2.outputMode
183228
+ });
183229
+ }
183230
+ });
183231
+ }
183232
+ async function listMachineFlockDocIds(manager, workspaceId) {
183233
+ const machines = await listAliveDocMetas(manager, isMachineDocRoomId);
183234
+ return machines.map((entry) => getMachineFlockDocId(workspaceId, entry.meta.id)).sort((left2, right2) => left2.localeCompare(right2));
183235
+ }
183236
+ async function syncWorkspace(input2) {
183237
+ const workspaceId = input2.workspace.id;
183238
+ const summary2 = createWorkspaceSummary(input2.workspace.id);
183239
+ await withWorkspaceManager$1(input2.auth, input2.workspace, "sync", async (manager) => {
183240
+ summary2.totals.meta = 1;
183241
+ try {
183242
+ await manager.syncMetaOrThrow({
183243
+ reason: `sync:${workspaceId}:meta`
183244
+ });
183245
+ recordSyncResult({
183246
+ summary: summary2,
183247
+ kind: "meta",
183248
+ id: "meta",
183249
+ ok: true,
183250
+ outputMode: input2.outputMode
183251
+ });
183252
+ } catch (error2) {
183253
+ recordSyncResult({
183254
+ summary: summary2,
183255
+ kind: "meta",
183256
+ id: "meta",
183257
+ ok: false,
183258
+ error: formatErrorMessage(error2),
183259
+ outputMode: input2.outputMode
183260
+ });
183261
+ return;
183262
+ }
183263
+ const docIds = (await listAliveRoomIds(manager, () => true)).sort((left2, right2) => left2.localeCompare(right2));
183264
+ const flockDocIds = await listMachineFlockDocIds(manager, workspaceId);
183265
+ await syncItems({
183266
+ summary: summary2,
183267
+ kind: "doc",
183268
+ ids: docIds,
183269
+ concurrency: input2.concurrency,
183270
+ outputMode: input2.outputMode,
183271
+ syncOne: async (id2) => {
183272
+ await manager.syncDocOrThrow(id2, {
183273
+ reason: `sync:${workspaceId}:doc:${id2}`
183274
+ });
183275
+ }
183276
+ });
183277
+ await syncItems({
183278
+ summary: summary2,
183279
+ kind: "flock",
183280
+ ids: flockDocIds,
183281
+ concurrency: input2.concurrency,
183282
+ outputMode: input2.outputMode,
183283
+ syncOne: async (id2) => {
183284
+ await manager.syncFlockDocOrThrow(id2, {
183285
+ reason: `sync:${workspaceId}:flock:${id2}`
183286
+ });
183287
+ }
183288
+ });
183289
+ });
183290
+ return summary2;
183291
+ }
183292
+ function printHumanSummary(summary2) {
183293
+ console.log(`Finished sync: ${summary2.completed}/${summary2.total} item(s) synced, ${summary2.failed} failed.`);
183294
+ if (summary2.failures.length > 0) {
183295
+ console.log("Failures:");
183296
+ for (const failure of summary2.failures) {
183297
+ console.log(`- [${failure.workspaceId}] ${failure.kind} ${failure.id}: ${failure.error}`);
183298
+ }
183299
+ }
183300
+ }
183301
+ function createAlreadyPrintedError() {
183302
+ return Object.assign(new Error("Sync completed with failures."), {
183303
+ suppressCommandErrorOutput: true,
183304
+ exitCode: 1
183305
+ });
183306
+ }
183307
+ const syncCommand = new Command("sync").description("Sync workspace Loro data to the local cache").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--all-workspace", "Sync all accessible workspaces").option("--concurrency <count>", "Maximum number of documents to sync concurrently", parsePositiveIntOption, DEFAULT_SYNC_CONCURRENCY).option("--json", "Print final JSON summary").option("--jsonl", "Print JSON Lines progress events and final summary").option("--debug", "Enable debug output").action(async (options) => {
183308
+ await runOneShotCommand("sync", options, async () => {
183309
+ const outputMode = resolveStructuredOutputMode$1(options);
183310
+ const auth = getAuthContextOrThrow$1("sync");
183311
+ if (options.allWorkspace && options.workspace) {
183312
+ throw new Error("Pass either --workspace or --all-workspace, not both.");
183313
+ }
183314
+ const workspaces = options.allWorkspace ? await listWorkspacesForToken(auth.token) : [
183315
+ await resolveWorkspaceOrThrow$1(auth, options.workspace)
183316
+ ];
183317
+ const workspaceSummaries = [];
183318
+ for (const workspace of workspaces) {
183319
+ workspaceSummaries.push(await syncWorkspace({
183320
+ auth,
183321
+ workspace,
183322
+ concurrency: options.concurrency ?? DEFAULT_SYNC_CONCURRENCY,
183323
+ outputMode
183324
+ }));
183325
+ }
183326
+ const summary2 = mergeSummaries(workspaceSummaries);
183327
+ if (outputMode === "jsonl") {
183328
+ printJson({
183329
+ type: "summary",
183330
+ ...summary2
183331
+ });
183332
+ } else if (outputMode === "json") {
183333
+ printJson(summary2);
183334
+ } else {
183335
+ printHumanSummary(summary2);
183336
+ }
183337
+ if (!summary2.ok) {
183338
+ throw createAlreadyPrintedError();
183339
+ }
183340
+ });
183341
+ });
182153
183342
  function sortWorkspaceSummaries(workspaces) {
182154
183343
  return [
182155
183344
  ...workspaces
@@ -182291,19 +183480,53 @@ ${entry.text}`).join("\n\n");
182291
183480
  } : {}
182292
183481
  };
182293
183482
  }
182294
- function toMachineJsonEntry(machine, includeAcpCapabilities) {
182295
- if (includeAcpCapabilities) {
182296
- return machine;
183483
+ function toMachineJsonEntry(machine, options) {
183484
+ const withoutOptional = {
183485
+ ...machine
183486
+ };
183487
+ if (!options.includeAcpCapabilities) {
183488
+ delete withoutOptional.acpCapabilities;
182297
183489
  }
182298
- const { acpCapabilities: _acpCapabilities, ...rest } = machine;
182299
- return rest;
183490
+ if (!options.includeAgents) {
183491
+ delete withoutOptional.agentConfigs;
183492
+ }
183493
+ return withoutOptional;
183494
+ }
183495
+ function formatMachineAgents(machine) {
183496
+ const configs = machine.agentConfigs ?? [];
183497
+ if (configs.length === 0) {
183498
+ return "-";
183499
+ }
183500
+ return configs.map((config2) => `${config2.name} (${config2.agentType})`).join(",");
182300
183501
  }
182301
- function printHumanMachineList(machines, currentMachineId) {
183502
+ async function attachAgentConfigsToMachines(repo, workspaceId, machines) {
183503
+ const configs = await listMergedAgentConfigs(repo, workspaceId, machines.map((machine) => machine.id));
183504
+ const configsByMachine = /* @__PURE__ */ new Map();
183505
+ for (const config2 of configs) {
183506
+ const current2 = configsByMachine.get(config2.machineId) ?? [];
183507
+ current2.push(config2);
183508
+ configsByMachine.set(config2.machineId, current2);
183509
+ }
183510
+ for (const values of configsByMachine.values()) {
183511
+ values.sort((left2, right2) => {
183512
+ const nameCompare = left2.name.localeCompare(right2.name);
183513
+ if (nameCompare !== 0) {
183514
+ return nameCompare;
183515
+ }
183516
+ return left2.id.localeCompare(right2.id);
183517
+ });
183518
+ }
183519
+ return machines.map((machine) => ({
183520
+ ...machine,
183521
+ agentConfigs: configsByMachine.get(machine.id) ?? []
183522
+ }));
183523
+ }
183524
+ function printHumanMachineList(machines, currentMachineId, includeAgents) {
182302
183525
  if (machines.length === 0) {
182303
183526
  console.log("No machines found.");
182304
183527
  return;
182305
183528
  }
182306
- console.log(renderTerminalTable([
183529
+ const columns = [
182307
183530
  {
182308
183531
  header: "ID"
182309
183532
  },
@@ -182316,30 +183539,49 @@ ${entry.text}`).join("\n\n");
182316
183539
  {
182317
183540
  header: "CLI"
182318
183541
  }
182319
- ], machines.map((machine) => [
182320
- machine.id,
182321
- machine.id === currentMachineId ? `${machine.name} (current)` : machine.name,
182322
- machine.online ? "online" : "offline",
182323
- formatMachineCli(machine)
182324
- ])));
183542
+ ];
183543
+ if (includeAgents) {
183544
+ columns.push({
183545
+ header: "Agents"
183546
+ });
183547
+ }
183548
+ console.log(renderTerminalTable(columns, machines.map((machine) => {
183549
+ const row = [
183550
+ machine.id,
183551
+ machine.id === currentMachineId ? `${machine.name} (current)` : machine.name,
183552
+ machine.online ? "online" : "offline",
183553
+ formatMachineCli(machine)
183554
+ ];
183555
+ if (includeAgents) {
183556
+ row.push(formatMachineAgents(machine));
183557
+ }
183558
+ return row;
183559
+ })));
182325
183560
  }
182326
- const machineCommand = new Command("machine").description("Inspect registered machines").addCommand(new Command("list").description("List machines in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--online-only", "Only include machines with a recent heartbeat").option("--json", "Print JSON output").option("--include-acp-capabilities", "Include acpCapabilities in JSON output").option("--debug", "Enable debug output").action(async (options) => {
183561
+ const machineCommand = new Command("machine").description("Inspect registered machines").addCommand(new Command("list").description("List machines in a workspace").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--online-only", "Only include machines with a recent heartbeat").option("--json", "Print JSON output").option("--include-acp-capabilities", "Include acpCapabilities in JSON output").option("--include-agents", "Include agent config summaries per machine").option("--debug", "Enable debug output").action(async (options) => {
182327
183562
  await runOneShotCommand("machine", options, async () => {
182328
183563
  const auth = getAuthContextOrThrow$1("machine");
182329
183564
  const workspace = await resolveWorkspaceOrThrow$1(auth, options.workspace);
182330
183565
  await withWorkspaceManager$1(auth, workspace, "machine", async (manager) => {
182331
- const machines = sortMachineMetas((await listAliveDocMetas(manager, isMachineDocRoomId)).map((entry) => entry.meta), auth.machineId).map(toMachineListEntry).filter((machine) => !options.onlineOnly || machine.online);
183566
+ let machines = sortMachineMetas((await listAliveDocMetas(manager, isMachineDocRoomId)).map((entry) => entry.meta), auth.machineId).map(toMachineListEntry).filter((machine) => !options.onlineOnly || machine.online);
183567
+ if (options.includeAgents === true) {
183568
+ machines = await attachAgentConfigsToMachines(manager.repo, workspace.id, machines);
183569
+ }
182332
183570
  if (options.json) {
182333
183571
  const includeAcpCapabilities = options.includeAcpCapabilities === true;
183572
+ const includeAgents = options.includeAgents === true;
182334
183573
  const jsonMachines = await Promise.all(machines.map((machine) => mergeMachineFlockJsonState(manager.repo, workspace.id, machine, includeAcpCapabilities)));
182335
183574
  printJson({
182336
183575
  ok: true,
182337
183576
  workspaceId: workspace.id,
182338
- machines: jsonMachines.map((machine) => toMachineJsonEntry(machine, includeAcpCapabilities))
183577
+ machines: jsonMachines.map((machine) => toMachineJsonEntry(machine, {
183578
+ includeAcpCapabilities,
183579
+ includeAgents
183580
+ }))
182339
183581
  });
182340
183582
  return;
182341
183583
  }
182342
- printHumanMachineList(machines, auth.machineId);
183584
+ printHumanMachineList(machines, auth.machineId, options.includeAgents === true);
182343
183585
  });
182344
183586
  });
182345
183587
  }));
@@ -182521,25 +183763,6 @@ ${entry.text}`).join("\n\n");
182521
183763
  ].sort((left2, right2) => left2.imageId.localeCompare(right2.imageId))
182522
183764
  };
182523
183765
  }
182524
- async function mapWithConcurrency(items2, concurrency, worker) {
182525
- if (items2.length === 0) {
182526
- return [];
182527
- }
182528
- const limit2 = Math.max(1, Math.floor(concurrency));
182529
- const results = new Array(items2.length);
182530
- let nextIndex = 0;
182531
- const runWorker = async () => {
182532
- while (nextIndex < items2.length) {
182533
- const currentIndex = nextIndex;
182534
- nextIndex += 1;
182535
- results[currentIndex] = await worker(items2[currentIndex], currentIndex);
182536
- }
182537
- };
182538
- await Promise.all(Array.from({
182539
- length: Math.min(limit2, items2.length)
182540
- }, () => runWorker()));
182541
- return results;
182542
- }
182543
183766
  const MIME_EXTENSION_MAP = {
182544
183767
  "image/png": ".png",
182545
183768
  "image/jpeg": ".jpg",
@@ -182960,6 +184183,7 @@ ${entry.text}`).join("\n\n");
182960
184183
  warnings
182961
184184
  };
182962
184185
  }
184186
+ const EXPORT_SYNC_CONCURRENCY = 4;
182963
184187
  function buildDefaultOutputDir() {
182964
184188
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
182965
184189
  return path__default$1.resolve(process.cwd(), `lody-export-${timestamp2}`);
@@ -182968,7 +184192,14 @@ ${entry.text}`).join("\n\n");
182968
184192
  const candidate = (workspace.slug?.trim() || workspace.id).trim();
182969
184193
  return candidate.replace(/[\\/]/g, "_");
182970
184194
  }
182971
- const exportCommand = new Command("export").description("Export user-facing workspace session data").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--all-workspace", "Export all accessible workspaces").option("--no-images", "Skip downloading image binaries").option("--debug", "Enable debug output").argument("[outputDir]", "Output directory for export files").action(async (outputDirArg, options) => {
184195
+ async function syncWorkspaceSessionsForExport(manager, workspace) {
184196
+ await syncWorkspaceMetaForRead(manager, `export:${workspace.id}:meta`);
184197
+ const sessions = await listAliveDocMetas(manager, isSessionDocRoomId);
184198
+ await mapWithConcurrency(sessions, EXPORT_SYNC_CONCURRENCY, async (entry) => {
184199
+ await syncDocForRead(manager, getSessionRoomId(entry.meta.id), `export:${workspace.id}:${entry.meta.id}`);
184200
+ });
184201
+ }
184202
+ const exportCommand = new Command("export").description("Export user-facing workspace session data").option("--workspace <idOrSlug>", "Target workspace id or slug").option("--all-workspace", "Export all accessible workspaces").option("--no-images", "Skip downloading image binaries").option("--offline", "Read the local cache without syncing first").option("--debug", "Enable debug output").argument("[outputDir]", "Output directory for export files").action(async (outputDirArg, options) => {
182972
184203
  await runOneShotCommand("export", options, async () => {
182973
184204
  const auth = getAuthContextOrThrow$1("export");
182974
184205
  const outputDir = path__default$1.resolve(outputDirArg ?? buildDefaultOutputDir());
@@ -182983,6 +184214,9 @@ ${entry.text}`).join("\n\n");
182983
184214
  for (const workspace of workspaces) {
182984
184215
  const workspaceOutputDir = path__default$1.join(outputDir, toWorkspaceDirName(workspace));
182985
184216
  const result = await withWorkspaceManager$1(auth, workspace, "export", async (manager) => {
184217
+ if (options.offline !== true) {
184218
+ await syncWorkspaceSessionsForExport(manager, workspace);
184219
+ }
182986
184220
  return await exportWorkspaceData({
182987
184221
  manager,
182988
184222
  workspace,
@@ -183106,7 +184340,7 @@ ${entry.text}`).join("\n\n");
183106
184340
  data = createReviewBundleSnapshot(bundle);
183107
184341
  }
183108
184342
  const { injectReviewSnapshot } = await import("./chunks/index-VoI6Ds2-.js");
183109
- const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-D22YtKnd.js");
184343
+ const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer--K5LcsS4.js");
183110
184344
  const template = await resolveReviewViewerTemplate();
183111
184345
  const html = injectReviewSnapshot(template, data);
183112
184346
  const outputPath = options.output ? path__default$1.resolve(options.output) : defaultHtmlOutputPath(inputPath);
@@ -200435,6 +201669,7 @@ ${lines2.join("\n")}` : ""}${suffix}`);
200435
201669
  program.addCommand(startCommand);
200436
201670
  program.addCommand(projectCommand);
200437
201671
  program.addCommand(sessionCommand);
201672
+ program.addCommand(syncCommand);
200438
201673
  program.addCommand(workspaceCommand);
200439
201674
  program.addCommand(agentConfigCommand);
200440
201675
  program.addCommand(machineCommand);