saros-proxy 1.0.0 → 1.1.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/README.md CHANGED
@@ -176,11 +176,11 @@ Saros tracks which keys are currently in use. A key handling a streaming request
176
176
 
177
177
  ### Prompt Install(for the lazy ones)
178
178
 
179
- Don't feel like reading through everything? Copy this prompt and paste it to your AI assistant. It'll read [`LLM_INSTRUCTIONS.md`](LLM_INSTRUCTIONS.md) and guide you through setup — no keys shared in chat.
179
+ Don't feel like reading through everything? Copy this prompt and paste it to your AI assistant. It'll read [`docs/LLM_INSTRUCTIONS.md`](docs/LLM_INSTRUCTIONS.md) and guide you through setup — no keys shared in chat.
180
180
 
181
181
  ```
182
182
  Install Saros Proxy for my opencode. (https://github.com/vitorvilaca3011/saros-proxy)
183
- Follow the instructions on LLM_INSTRUCTIONS.md.
183
+ Follow the instructions on docs/LLM_INSTRUCTIONS.md.
184
184
  ```
185
185
 
186
186
  ---
@@ -481,14 +481,21 @@ into the "no passphrase source" boot error — a locked keyring is not reported
481
481
  as an empty store.
482
482
 
483
483
  **systemd-creds recipe** (keeps the passphrase out of the unit file and the
484
- environment of the shell):
484
+ environment of the shell). This is a **system** unit recipe — run the encryption
485
+ as root, since the host key lives in `/var/lib/systemd/credential.secret`:
485
486
 
486
487
  ```bash
487
- # One-time: encrypt stdin into a host+user-bound credential.
488
- systemd-creds encrypt --name=saros-passphrase --with-key=host+user \
488
+ # One-time, as root: encrypt stdin into a host-bound credential.
489
+ # (--with-key=auto picks tpm2+host when the TPM is available, host otherwise.
490
+ # "host+user" is not a valid key type, and --user only exists from v256.)
491
+ systemd-creds encrypt --name=saros-passphrase --with-key=auto \
489
492
  /dev/stdin /etc/saros/passphrase.cred
490
493
  ```
491
494
 
495
+ For the `systemd --user` unit created by `saros-proxy autostart install`, use
496
+ `Environment=`/`EnvironmentFile=` instead: user credentials need
497
+ `systemd-creds --user`, which only exists from systemd v256 (this host runs 255).
498
+
492
499
  ```ini
493
500
  # /etc/systemd/system/saros-proxy.service
494
501
  [Service]
@@ -591,16 +598,48 @@ saros-proxy probe
591
598
  # Show per-key quota usage, token totals and most-used models
592
599
  saros-proxy usage
593
600
 
594
- # Install autostart (Windows: VBS script or Registry)
595
- saros-proxy autostart install [--port <port>] [--method vbs|registry|auto]
601
+ # Install autostart (Linux: systemd --user; Windows: VBS script or Registry)
602
+ saros-proxy autostart install [--port <port>] [--method systemd|vbs|registry|auto]
596
603
 
597
604
  # Uninstall autostart
598
- saros-proxy autostart uninstall [--method vbs|registry|auto]
605
+ saros-proxy autostart uninstall [--method systemd|vbs|registry|auto]
599
606
 
600
607
  # Check autostart status
601
- saros-proxy autostart status [--method vbs|registry|auto]
608
+ saros-proxy autostart status [--method systemd|vbs|registry|auto]
609
+ ```
610
+
611
+ On Linux the default is a `systemd --user` unit at
612
+ `~/.config/systemd/user/saros-proxy.service` (honouring `$XDG_CONFIG_HOME`), enabled
613
+ with `systemctl --user enable` and restarted with `systemctl --user restart`. On
614
+ Windows the default is AV-aware (`auto`): Registry when third-party antivirus is
615
+ detected, otherwise the Startup-folder VBS.
616
+
617
+ Manage the unit with systemd, not with the CLI: `saros-proxy stop` exits non-zero
618
+ while the service still answers `/health`, because the CLI does not own the unit's
619
+ process.
620
+
621
+ ```bash
622
+ systemctl --user start|stop|restart|status saros-proxy.service
623
+ journalctl --user -u saros-proxy -f
624
+ ```
625
+
626
+ The unit runs `serve` in the foreground: without a TTY it cannot prompt for a
627
+ passphrase, and the user manager does not inherit the environment of the shell
628
+ that ran `install`. If `config.yaml` holds `enc:v1:` envelopes, give the unit a
629
+ source through a drop-in (`systemctl --user edit saros-proxy.service`):
630
+
631
+ ```ini
632
+ [Service]
633
+ Environment=SAROS_PASSPHRASE=your-passphrase
602
634
  ```
603
635
 
636
+ `EnvironmentFile=-%h/.config/saros/env` (mode 0600) keeps the value out of the
637
+ unit file. A credential is stronger, but `Environment=` can only carry the
638
+ credential *path* (`%d/<name>`), never its content — see the
639
+ [systemd-creds recipe](#api-key-encryption), which wraps `serve` in
640
+ `sh -c 'SAROS_PASSPHRASE="$(cat "$CREDENTIALS_DIRECTORY/<name>")" exec …'`.
641
+ `systemd-creds` only gained a `--user` mode in v256.
642
+
604
643
  The `start` command automatically syncs model definitions to all enabled harnesses (see [Multi-Harness Integration](#multi-harness-integration-pi-oh-my-pi--dsh)).
605
644
 
606
645
  ### Model Sync Commands
@@ -752,7 +791,7 @@ Behavior:
752
791
  - Sync never creates a harness config: harnesses whose config file is missing are skipped.
753
792
  - Only `providers["saros-proxy"].models` is replaced; all other providers, fields, and settings are preserved, and a `<file>.backup` is created before the first write.
754
793
 
755
- The model list written to each harness comes from the live provider catalogs (opencode-go) enriched with models.dev metadata, merged with any CommandCode-only models — falling back to bundled models when offline — so every harness stays current alongside OpenCode.
794
+ The model list written to each harness comes from the live provider catalogs (opencode-go) enriched with models.dev metadata, merged with any CommandCode-only models — falling back to the bundled `assets/models.json` when offline — so every harness stays current alongside OpenCode.
756
795
 
757
796
  > **Why a static model list?** The harnesses use a static `models` list on purpose. `pi` has no `/v1/models` discovery for custom providers, and `oh-my-pi`'s discovery cannot recover reasoning/context/output metadata for provider model IDs. `dsh` replaces only `providers["saros-proxy"].models` in its patch layer (`cordis.patch.yml`), which dsh rewrites at every boot — a static, explicitly-managed list is the only reliable source. Dynamic discovery would silently break thinking-level (`:max`/`:high`) role configs.
758
797
 
@@ -866,6 +905,18 @@ npm run build
866
905
 
867
906
  Output goes to `dist/`.
868
907
 
908
+ ### Refresh the bundled model catalog
909
+
910
+ `assets/models.json` is generated — do not edit it by hand. The generator merges models.dev metadata with the live opencode-go and CommandCode catalogs: a model that left upstream leaves the bundle, a model the upstream serves but models.dev does not list still enters with the live name and context window, and a field already in the file survives when models.dev omits it.
911
+
912
+ ```bash
913
+ npm run models:refresh -- --dry-run # print the diff, write nothing
914
+ npm run models:refresh # rewrite assets/models.json
915
+ npm run models:refresh -- --allow-shrink # accept removing more than half of the models
916
+ ```
917
+
918
+ A failed fetch — or a 2xx with an empty catalog — aborts before the file is read, and a merge that would remove more than half of the current models aborts unless `--allow-shrink` is given. The write goes through a temp file and an atomic rename, so a crash never leaves a truncated catalog.
919
+
869
920
  ### Project structure
870
921
 
871
922
  ```
@@ -879,7 +930,8 @@ src/
879
930
  providers/ — Multi-provider key abstraction (KeyProvider, adapters, identifyKey)
880
931
  models-fetcher.ts — Upstream model list fetching + caching
881
932
  models-sync.ts — Auto-sync models from upstream to opencode config
882
- models-catalog.ts — Single source of truth: loads bundled models.json
933
+ models-catalog.ts — Single source of truth: loads assets/models.json
934
+ models-refresh.ts — Generates that catalog (npm run models:refresh)
883
935
  cli/
884
936
  setup.ts — Interactive setup wizard
885
937
  daemon.ts — Background process management