Commit Graph

12 Commits

Author SHA1 Message Date
Aletheia
7c61ecb410 fix: pattern lifecycle — indefinite durations, escalate hold contract, monotonic clocks
Ports the Android relay engine's pattern semantics (its 2026-06/2026-07
fix batches) to both Python relay clients:

- duration <= 0 on pulse/wave now runs the pattern until an explicit
  stop, matching how plain commands treat duration=0. Previously the
  loop condition was already false at start, so the pattern silently
  did nothing.
- escalate now honours its documented hold contract: hold_seconds <= 0
  suspends at peak until cancelled, > 0 holds then stops. Both paths
  run through a finally that stops the device, so an error mid-ramp can
  no longer leave hardware running at the last intensity it reached.
  (The naive finally alone would stop the device the moment the ramp
  finished — the same regression the Android app shipped and fixed.)
- Pattern timing uses time.monotonic() instead of time.time(): an NTP
  wall-clock jump could stretch, truncate, or instantly end a pattern.
- relay_client.py now keys pattern tasks by device (one pattern per
  device, as in the Android engine) instead of device:pattern, which
  let a wave and a pulse fight over the same actuator.
- Duplicate same-model devices get suffixed short names (lush, lush_2)
  instead of silently replacing each other.
- Dropped the unsolicited device_list push after auth — the server
  requests a scan on connect and the scan handler answers it; the
  double-send raced session registration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:14:32 +02:00
Aletheia
07e5f9c38c refactor: neutral engineering terminology in tool schemas and device profiles
Ported from the Android edition (its 'reworded device and tool schemas
in neutral terminology' change):

- Tool descriptions and devices.json now describe hardware in neutral
  actuator/engineering terms. Content filters on some LLM platforms
  refused to call tools whose schemas contained explicit anatomical
  language; the reworded schemas work across providers.
- list_devices now surfaces capability descriptions next to each output
  channel (e.g. 'vibrate (two independent eccentric-mass actuators…)')
  so the model learns what each channel does from the profile itself.
- All output/pattern tools now declare required=["device"]; pattern
  schema defaults adjusted to match the Android edition (intensity 0.5,
  duration 60).
- Dual-motor device profiles (Edge, Dolce) document feature_index usage.
- Fixed a stray ')' in nora's rotate capability (typo in the Android
  copy of devices.json).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:11:49 +02:00
Aletheia
136920b717 feat: feature_index — target individual motors on multi-actuator devices
Ported from the Android edition and completed for the Python relays
(the Android repo only implemented the phone side in Kotlin):

- models.py / mcp_tools.py: optional feature_index on every output and
  pattern tool, passed through to the phone relay.
- relay_client.py: routes targeted writes through buttplug-py's
  per-feature API (device.features[i].run_output) and validates the
  index up front so a bad one fails the ack with the valid indices
  listed, instead of dying silently inside a pattern task.
- termux_relay_v3.py: ScalarCmd entries filtered to the requested
  actuator index, same fallback semantics as the Android relay engine.

Lets Claude drive e.g. a Dolce's internal and external motors
independently (feature_index 0 / 1) instead of always both together.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:11:01 +02:00
Aletheia
263e6e9b75 fix: OAuth token endpoint multipart support + governor_enabled bool round-trip
Ported from the Android edition's server:

- Add python-multipart: the OAuth endpoints parse credentials with
  request.form(), and Starlette needs this package when a client POSTs
  the token request as multipart/form-data. Without it those requests
  500'd ('the small auth bug').
- governor_enabled now round-trips SQLite's 0/1 as JSON true/false on
  read and normalises any truthy input to 0/1 on write. Strict clients
  (kotlinx-serialization) reject anything else.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:06:55 +02:00
Aletheia
e987a48689 fix: MCP protocol compliance — ACK notifications with 202, negotiate protocolVersion
Ported from the Android edition's server:

- JSON-RPC notifications (requests without an id, e.g.
  notifications/initialized) now get the bare HTTP 202 the MCP spec
  requires instead of a malformed JSON-RPC error response, which strict
  clients rejected.
- initialize echoes the client's requested protocolVersion when it is a
  version we support (2024-11-05 / 2025-03-26 / 2025-06-18) instead of
  always claiming 2025-03-26.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:06:27 +02:00
Aletheia
6a8bc353c5 feat: OAuth 2.0 support, server-side safety governor, multi-user auth mode
Publishes server work that shipped in the Android edition but never made
it to this repo:

- Full OAuth 2.0 flow (discovery metadata, dynamic client registration,
  authorize + token endpoints) so claude.ai remote connectors and the
  Android app can authenticate per-user instead of relying on the
  sole-phone fallback.
- Safety governor: server-side heat model (intensity x time) with
  automatic cooldown, per-user overrides via GET/POST /safety/config,
  and governor state piggybacked on heartbeat pings so relay clients
  can display it.
- SB_REQUIRE_MCP_AUTH env flag for multi-user deployments (disables the
  unauthenticated sole-phone fallback).
- requirements-phone.txt and .env.example documenting the new knobs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:05:45 +02:00
Aletheia
f8a9245f90 chore: repo hygiene — gitignore, LF normalization, drop compiled bytecode and deploy tarball
The March upload accidentally included server/__pycache__/*.pyc (stale
compiled bytecode) and a prebuilt deploy tarball. The README already
instructs users to build their own bundle, so neither belongs in git.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 20:04:52 +02:00
Aletheia
dcc73f7d7b Add donation link and project credits to README 2026-04-14 18:55:39 +02:00
Aletheia
9a0d9dd172 Enhance README with project details and ethics
Added project overview, ethics, and security information to README.
2026-04-14 17:34:58 +02:00
Aletheia
b006c6c6b9 Add security warning and legitimate download links
Added a security warning to the README to inform users about potential malware forks and provide legitimate download links.
2026-04-06 20:06:21 +02:00
Aletheia
25678779a4 Add files via upload 2026-03-14 19:42:51 +01:00
Aletheia
142e83d512 Add files via upload 2026-03-14 19:40:48 +01:00