mirror of
https://github.com/AletheiaVox/signal_bridge_remote.git
synced 2026-10-07 03:18:17 +08:00
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>
This commit is contained in:
@@ -3,113 +3,113 @@
|
|||||||
"short_name": "ferri",
|
"short_name": "ferri",
|
||||||
"match_strings": ["Ferri"],
|
"match_strings": ["Ferri"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "external clitoral vibration"
|
"vibrate": "compact eccentric-mass actuator, high response at low duty cycle"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Small wearable. Intense even at low settings."
|
"notes": "Small form factor. High effective output at low values; recommend starting below 0.3."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "lush",
|
"short_name": "lush",
|
||||||
"match_strings": ["Lush"],
|
"match_strings": ["Lush"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "internal egg vibration"
|
"vibrate": "single eccentric-mass actuator, low-frequency dominant"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Insertable egg. Strong deep vibration."
|
"notes": "Compact ovoid form factor. High output efficiency at low command levels."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "gravity",
|
"short_name": "gravity",
|
||||||
"match_strings": ["Gravity"],
|
"match_strings": ["Gravity"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "shaft vibration",
|
"vibrate": "eccentric-mass actuator along main axis",
|
||||||
"oscillate": "thrusting motion"
|
"oscillate": "linear reciprocating actuator; stroke rate scales with intensity"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Vibration + thrusting. Use 0.05+ intensity for slow strokes."
|
"notes": "Dual-mode device. Oscillate requires intensity >= 0.05 to engage; low values map to slow cycle rate."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "enigma",
|
"short_name": "enigma",
|
||||||
"match_strings": ["Enigma"],
|
"match_strings": ["Enigma"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "G-spot thumping stimulation",
|
"vibrate": "high-amplitude pulsed actuator (impact-style, not continuous waveform)",
|
||||||
"rotate": "clitoral sonic pulse"
|
"rotate": "sonic-frequency acoustic actuator (note: maps to acoustic output, NOT mechanical rotation)"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.4,
|
"intensity_floor": 0.4,
|
||||||
"notes": "Dual stimulation. 'rotate' = sonic pulse, NOT rotation. Needs 40%+ to feel."
|
"notes": "Two independent actuators. Threshold response: effective activation threshold ≈0.4. Rotate channel is acoustic, not rotational."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "max",
|
"short_name": "max",
|
||||||
"match_strings": ["Max"],
|
"match_strings": ["Max"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "internal vibration",
|
"vibrate": "eccentric-mass actuator",
|
||||||
"constrict": "air pump compression"
|
"constrict": "pneumatic compression actuator; intensity maps to chamber pressure"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Vibration + air pump constriction. Constrict controls squeeze pressure."
|
"notes": "Two independent actuators. Constrict is air-pump driven; intensity = compression force."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "nora",
|
"short_name": "nora",
|
||||||
"match_strings": ["Nora"],
|
"match_strings": ["Nora"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "internal vibration",
|
"vibrate": "eccentric-mass actuator",
|
||||||
"rotate": "internal rotation"
|
"rotate": "rotational actuator"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Vibration + actual physical rotation (unlike Enigma)."
|
"notes": "Two independent actuators. Rotate is mechanical, not acoustic."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "edge",
|
"short_name": "edge",
|
||||||
"match_strings": ["Edge"],
|
"match_strings": ["Edge"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "dual motor vibration"
|
"vibrate": "two independent eccentric-mass actuators; address individually via feature_index"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Prostate massager. Two independent vibration motors."
|
"notes": "Dual-actuator device. Use feature_index 0 or 1 to drive motors separately."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "hush",
|
"short_name": "hush",
|
||||||
"match_strings": ["Hush"],
|
"match_strings": ["Hush"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "vibration"
|
"vibrate": "single eccentric-mass actuator"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Vibrating plug. Simple single-motor vibration."
|
"notes": "Single-actuator device, no quirks."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "domi",
|
"short_name": "domi",
|
||||||
"match_strings": ["Domi"],
|
"match_strings": ["Domi"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "powerful wand vibration"
|
"vibrate": "high-output eccentric-mass actuator, broad-spectrum"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Mini wand. Very powerful. Start low."
|
"notes": "High maximum output relative to other devices in this set. Typical operating range: 0.05–0.30."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "osci",
|
"short_name": "osci",
|
||||||
"match_strings": ["Osci"],
|
"match_strings": ["Osci"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"oscillate": "oscillating stimulation"
|
"oscillate": "linear reciprocating actuator (no vibrate channel)"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Oscillating G-spot stimulator. Uses oscillate, not vibrate."
|
"notes": "Single-channel device. Responds only to oscillate, not vibrate."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "dolce",
|
"short_name": "dolce",
|
||||||
"match_strings": ["Dolce"],
|
"match_strings": ["Dolce"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "dual vibration"
|
"vibrate": "two independent eccentric-mass actuators; address individually via feature_index"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Couples' vibrator. Dual motors."
|
"notes": "Dual-actuator device. Use feature_index 0 or 1 to drive motors separately."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"short_name": "flexer",
|
"short_name": "flexer",
|
||||||
"match_strings": ["Flexer"],
|
"match_strings": ["Flexer"],
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"vibrate": "vibration",
|
"vibrate": "eccentric-mass actuator",
|
||||||
"oscillate": "come-hither motion"
|
"oscillate": "articulated curling actuator (pivots rather than reciprocates linearly)"
|
||||||
},
|
},
|
||||||
"intensity_floor": 0.0,
|
"intensity_floor": 0.0,
|
||||||
"notes": "Vibration + finger-like come-hither oscillation pattern."
|
"notes": "Two independent actuators. Oscillate uses curling articulation, not linear stroke."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ All tools that Claude can call to control devices. Each tool:
|
|||||||
3. Routes it through the session registry to the user's phone
|
3. Routes it through the session registry to the user's phone
|
||||||
4. Returns the result to Claude
|
4. Returns the result to Claude
|
||||||
|
|
||||||
Expanded to support ALL Buttplug output types:
|
Expanded to support ALL output types:
|
||||||
vibrate, rotate, oscillate, constrict, temperature, led, position, spray
|
vibrate, rotate, oscillate, constrict, temperature, led, position, spray
|
||||||
|
|
||||||
And sensor input types:
|
And sensor input types:
|
||||||
@@ -103,7 +103,7 @@ async def _send(command: dict, intensity: float = 0.0) -> str:
|
|||||||
|
|
||||||
@_register_tool(
|
@_register_tool(
|
||||||
"list_devices",
|
"list_devices",
|
||||||
"List all connected devices with their capabilities, intensity floors, and notes.",
|
"List all connected devices and their supported outputs, operating ranges, and metadata.",
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
async def list_devices(**kwargs) -> str:
|
async def list_devices(**kwargs) -> str:
|
||||||
@@ -139,7 +139,11 @@ async def list_devices(**kwargs) -> str:
|
|||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
for d in devices:
|
for d in devices:
|
||||||
caps = ", ".join(d.get("capabilities", {}).keys())
|
caps_dict = d.get("capabilities", {})
|
||||||
|
# Surface capability values when present so the model knows what each
|
||||||
|
# output channel actually does; fall back to bare keys for terse entries.
|
||||||
|
caps_parts = [f"{k} ({v})" if v else k for k, v in caps_dict.items()]
|
||||||
|
caps = ", ".join(caps_parts)
|
||||||
notes = d.get("notes", "")
|
notes = d.get("notes", "")
|
||||||
floor = d.get("intensity_floor", 0)
|
floor = d.get("intensity_floor", 0)
|
||||||
lines.append(
|
lines.append(
|
||||||
@@ -148,7 +152,7 @@ async def list_devices(**kwargs) -> str:
|
|||||||
+ (f" | {notes}" if notes else "")
|
+ (f" | {notes}" if notes else "")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Append governor state so Claude knows the session budget
|
# Append governor state so AI knows the session budget
|
||||||
gov = governor.get_state(user_id)
|
gov = governor.get_state(user_id)
|
||||||
heat = gov["heat_pct"]
|
heat = gov["heat_pct"]
|
||||||
if gov["in_cooldown"]:
|
if gov["in_cooldown"]:
|
||||||
@@ -177,7 +181,7 @@ async def scan_devices(**kwargs) -> str:
|
|||||||
_OUTPUT_PARAMS = {
|
_OUTPUT_PARAMS = {
|
||||||
"device": {
|
"device": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Device short name (e.g. 'ferri', 'lush', 'gravity') or 'all'",
|
"description": "Device short name or 'all'",
|
||||||
"default": "all",
|
"default": "all",
|
||||||
},
|
},
|
||||||
"intensity": {
|
"intensity": {
|
||||||
@@ -222,30 +226,35 @@ def _make_output_handler(output_type: OutputType):
|
|||||||
# Standard outputs (available on most devices)
|
# Standard outputs (available on most devices)
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"vibrate",
|
"vibrate",
|
||||||
"Send vibration to a device. Most common output type.",
|
"Send vibration to a device. Most common output type. "
|
||||||
|
"For dual-motor devices (Dolce, Edge), use feature_index to target a "
|
||||||
|
"specific motor (e.g. Dolce: 0 = internal, 1 = external).",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.VIBRATE))
|
)(_make_output_handler(OutputType.VIBRATE))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"rotate",
|
"rotate",
|
||||||
"Send rotation/sonic pulse output. Device-specific — some devices use this "
|
"Control rotational or oscillatory high-frequency actuator output. "
|
||||||
"for sonic clitoral stimulation rather than physical rotation.",
|
"Interpretation depends on device firmware.",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.ROTATE))
|
)(_make_output_handler(OutputType.ROTATE))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"oscillate",
|
"oscillate",
|
||||||
"Send oscillation/thrusting output. Device-specific — typically linear "
|
"Control linear reciprocating actuator output. Intensity controls stroke amplitude/speed "
|
||||||
"thrusting motion.",
|
"depending on hardware.",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.OSCILLATE))
|
)(_make_output_handler(OutputType.OSCILLATE))
|
||||||
|
|
||||||
# Extended outputs (device-specific, may not be available on all hardware)
|
# Extended outputs (device-specific, may not be available on all hardware)
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"constrict",
|
"constrict",
|
||||||
"Send constriction/compression output. Device-specific — available on "
|
"Send constriction/compression output. Device-specific.",
|
||||||
"devices with squeeze or compression mechanisms.",
|
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.CONSTRICT))
|
)(_make_output_handler(OutputType.CONSTRICT))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
@@ -253,12 +262,14 @@ _register_tool(
|
|||||||
"Set temperature output. Device-specific — available on devices with "
|
"Set temperature output. Device-specific — available on devices with "
|
||||||
"heating or cooling elements. Intensity maps to temperature range.",
|
"heating or cooling elements. Intensity maps to temperature range.",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.TEMPERATURE))
|
)(_make_output_handler(OutputType.TEMPERATURE))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"led",
|
"led",
|
||||||
"Control LED light output. Device-specific — intensity controls brightness.",
|
"Control LED light output. Device-specific — intensity controls brightness.",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.LED))
|
)(_make_output_handler(OutputType.LED))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
@@ -266,12 +277,14 @@ _register_tool(
|
|||||||
"Set linear position. Device-specific — intensity maps to position "
|
"Set linear position. Device-specific — intensity maps to position "
|
||||||
"along the device's range of motion (0.0 = retracted, 1.0 = extended).",
|
"along the device's range of motion (0.0 = retracted, 1.0 = extended).",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.POSITION))
|
)(_make_output_handler(OutputType.POSITION))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"spray",
|
"spray",
|
||||||
"Trigger spray/liquid output. Device-specific.",
|
"Trigger spray/liquid output. Device-specific.",
|
||||||
_OUTPUT_PARAMS,
|
_OUTPUT_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_output_handler(OutputType.SPRAY))
|
)(_make_output_handler(OutputType.SPRAY))
|
||||||
|
|
||||||
|
|
||||||
@@ -313,13 +326,13 @@ _PATTERN_PARAMS = {
|
|||||||
},
|
},
|
||||||
"intensity": {
|
"intensity": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"description": "Peak intensity (0.0–1.0)",
|
"description": "Set intensity (0.0–1.0)",
|
||||||
"default": 0.6,
|
"default": 0.5,
|
||||||
},
|
},
|
||||||
"duration": {
|
"duration": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"description": "Duration in seconds",
|
"description": "Duration in seconds",
|
||||||
"default": 10,
|
"default": 60,
|
||||||
},
|
},
|
||||||
"feature_index": {
|
"feature_index": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@@ -360,18 +373,20 @@ _register_tool(
|
|||||||
"Rhythmic on/off pattern. 0.5s on at intensity, 0.3s off, repeating. "
|
"Rhythmic on/off pattern. 0.5s on at intensity, 0.3s off, repeating. "
|
||||||
"Works with any output type (default: vibrate).",
|
"Works with any output type (default: vibrate).",
|
||||||
_PATTERN_PARAMS,
|
_PATTERN_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_pattern_handler("pulse"))
|
)(_make_pattern_handler("pulse"))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"wave",
|
"wave",
|
||||||
"Smooth sine-wave intensity modulation. Rises and falls continuously. "
|
"Smooth continuous sine-wave amplitude modulation. "
|
||||||
"Works with any output type (default: vibrate).",
|
"Works with any output type (default: vibrate).",
|
||||||
_PATTERN_PARAMS,
|
_PATTERN_PARAMS,
|
||||||
|
required=["device"],
|
||||||
)(_make_pattern_handler("wave"))
|
)(_make_pattern_handler("wave"))
|
||||||
|
|
||||||
_register_tool(
|
_register_tool(
|
||||||
"escalate",
|
"escalate",
|
||||||
"Gradual ramp from 0% to peak intensity over the duration, then hold at peak. "
|
"Apply linear interpolation from current output level to target level over duration; optionally maintain target after transition. "
|
||||||
"Use hold_seconds to auto-stop after holding (0 = hold indefinitely until stop command). "
|
"Use hold_seconds to auto-stop after holding (0 = hold indefinitely until stop command). "
|
||||||
"Works with any output type (default: vibrate).",
|
"Works with any output type (default: vibrate).",
|
||||||
{k: v for k, v in _PATTERN_PARAMS.items() if k != "intensity"}
|
{k: v for k, v in _PATTERN_PARAMS.items() if k != "intensity"}
|
||||||
@@ -383,6 +398,7 @@ _register_tool(
|
|||||||
"default": 0,
|
"default": 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
required=["device"],
|
||||||
)(_make_pattern_handler("escalate"))
|
)(_make_pattern_handler("escalate"))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user