@oceanswave/openclaw-tescmd 0.3.1
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/LICENSE +21 -0
- package/README.md +183 -0
- package/commands/cli.ts +74 -0
- package/commands/slash.ts +160 -0
- package/config.ts +39 -0
- package/index.ts +107 -0
- package/openclaw.plugin.json +22 -0
- package/package.json +46 -0
- package/platform.ts +361 -0
- package/skill.md +737 -0
- package/telemetry.ts +245 -0
- package/tools/capabilities.ts +341 -0
- package/tools/charge.ts +141 -0
- package/tools/climate.ts +134 -0
- package/tools/navigation.ts +199 -0
- package/tools/security.ts +207 -0
- package/tools/status.ts +47 -0
- package/tools/system.ts +67 -0
- package/tools/triggers.ts +311 -0
- package/tools/trunk.ts +67 -0
- package/tools/vehicle.ts +115 -0
- package/types/openclaw.d.ts +108 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 oceanswave
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# openclaw-tescmd
|
|
2
|
+
|
|
3
|
+
OpenClaw platform plugin for Tesla vehicle control and real-time telemetry via [tescmd](https://github.com/oceanswave/tescmd).
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
This plugin registers the Tesla vehicle platform with the OpenClaw Gateway, enabling AI agents to control Tesla vehicles and consume telemetry through well-documented tools. It bridges the [tescmd](https://github.com/oceanswave/tescmd) node — a Python CLI for the Tesla Fleet API — to the OpenClaw agent ecosystem.
|
|
8
|
+
|
|
9
|
+
**Plugin provides:**
|
|
10
|
+
- **37 agent-callable tools** across vehicle status, charging, climate, security, trunk, navigation, triggers, and system commands
|
|
11
|
+
- **34 whitelisted commands** so the Gateway can dispatch to tescmd nodes
|
|
12
|
+
- **8 slash commands** for quick user actions (`/battery`, `/lock`, `/climate`, etc.)
|
|
13
|
+
- **14 telemetry event types** documented with TypeScript interfaces
|
|
14
|
+
- **Capabilities meta-tool** with workflow recipes, error handling guide, and CLI reference
|
|
15
|
+
- **Node status tool** for connection health checks
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Install from npm:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
openclaw plugins install @oceanswave/openclaw-tescmd
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For development (symlink, editable):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/oceanswave/openclaw-tescmd.git
|
|
29
|
+
cd openclaw-tescmd && bun install && cd ..
|
|
30
|
+
openclaw plugins install -l ./openclaw-tescmd
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Verify:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
openclaw plugins list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
The tescmd node must be running and connected to the Gateway for vehicle commands to work.
|
|
42
|
+
|
|
43
|
+
| Requirement | Required | Purpose |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Python 3.11+ | Yes | Runs the tescmd node |
|
|
46
|
+
| pip | Yes | Installs tescmd (`pip install tescmd`) |
|
|
47
|
+
| Tesla account | Yes | OAuth2 access to the Fleet API |
|
|
48
|
+
| Git | Yes | Key hosting setup |
|
|
49
|
+
| GitHub CLI (`gh`) | Recommended | Auto-creates key hosting via GitHub Pages |
|
|
50
|
+
| Tailscale | Recommended | Public HTTPS for telemetry streaming |
|
|
51
|
+
|
|
52
|
+
### Node Setup
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Install tescmd
|
|
56
|
+
pip install tescmd
|
|
57
|
+
|
|
58
|
+
# First-time setup (interactive wizard)
|
|
59
|
+
tescmd setup
|
|
60
|
+
|
|
61
|
+
# Start the node with OpenClaw bridge
|
|
62
|
+
tescmd serve <VIN> --openclaw <gateway_ws_url> --openclaw-token <token>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Agent Tools
|
|
66
|
+
|
|
67
|
+
### Reading Vehicle State
|
|
68
|
+
| Tool | Description |
|
|
69
|
+
|------|-------------|
|
|
70
|
+
| `tescmd_node_status` | Check if the tescmd node is connected |
|
|
71
|
+
| `tescmd_get_location` | GPS coordinates, heading, speed |
|
|
72
|
+
| `tescmd_get_battery` | Battery level (%) and range (miles) |
|
|
73
|
+
| `tescmd_get_speed` | Current speed (mph) |
|
|
74
|
+
| `tescmd_get_charge_state` | Charging status |
|
|
75
|
+
| `tescmd_get_temperature` | Inside/outside temperatures |
|
|
76
|
+
| `tescmd_get_security` | Lock state, sentry mode |
|
|
77
|
+
|
|
78
|
+
### Controlling the Vehicle
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `tescmd_lock_doors` / `tescmd_unlock_doors` | Door lock/unlock |
|
|
82
|
+
| `tescmd_climate_on` / `tescmd_climate_off` | HVAC control |
|
|
83
|
+
| `tescmd_set_climate_temp` | Set cabin temperature (F) |
|
|
84
|
+
| `tescmd_start_charge` / `tescmd_stop_charge` | Charge control |
|
|
85
|
+
| `tescmd_set_charge_limit` | Set charge limit (50-100%) |
|
|
86
|
+
| `tescmd_open_trunk` / `tescmd_open_frunk` | Trunk/frunk |
|
|
87
|
+
| `tescmd_flash_lights` / `tescmd_honk_horn` | Locator alerts |
|
|
88
|
+
| `tescmd_sentry_on` / `tescmd_sentry_off` | Sentry Mode |
|
|
89
|
+
|
|
90
|
+
### Navigation
|
|
91
|
+
| Tool | Description |
|
|
92
|
+
|------|-------------|
|
|
93
|
+
| `tescmd_nav_send` | Send address/place to vehicle navigation |
|
|
94
|
+
| `tescmd_nav_gps` | Send GPS coordinates to navigation |
|
|
95
|
+
| `tescmd_nav_supercharger` | Route to nearest Supercharger |
|
|
96
|
+
| `tescmd_nav_waypoints` | Multi-stop route via waypoint IDs |
|
|
97
|
+
| `tescmd_homelink` | Trigger garage door (HomeLink) |
|
|
98
|
+
|
|
99
|
+
### Triggers
|
|
100
|
+
| Tool | Description |
|
|
101
|
+
|------|-------------|
|
|
102
|
+
| `tescmd_create_trigger` | Subscribe to telemetry conditions |
|
|
103
|
+
| `tescmd_delete_trigger` | Remove a trigger |
|
|
104
|
+
| `tescmd_list_triggers` | List active triggers |
|
|
105
|
+
| `tescmd_poll_triggers` | Check for fired triggers |
|
|
106
|
+
| `tescmd_battery_trigger` | Shortcut: battery level alert |
|
|
107
|
+
| `tescmd_cabin_temp_trigger` | Shortcut: cabin temp alert |
|
|
108
|
+
| `tescmd_outside_temp_trigger` | Shortcut: outside temp alert |
|
|
109
|
+
| `tescmd_location_trigger` | Shortcut: geofence alert |
|
|
110
|
+
|
|
111
|
+
### Meta
|
|
112
|
+
| Tool | Description |
|
|
113
|
+
|------|-------------|
|
|
114
|
+
| `tescmd_help` | Capabilities reference, workflows, setup guide |
|
|
115
|
+
| `tescmd_run_command` | Execute any command by name (meta-dispatch) |
|
|
116
|
+
|
|
117
|
+
## Slash Commands
|
|
118
|
+
|
|
119
|
+
| Command | Description |
|
|
120
|
+
|---------|-------------|
|
|
121
|
+
| `/battery` | Check battery level and range |
|
|
122
|
+
| `/charge` | Charge status, or `/charge start` / `/charge stop` / `/charge 80` |
|
|
123
|
+
| `/climate` | Temperature, or `/climate on` / `/climate off` / `/climate 72` |
|
|
124
|
+
| `/lock` | Lock all doors |
|
|
125
|
+
| `/unlock` | Unlock all doors |
|
|
126
|
+
| `/sentry` | Check sentry, or `/sentry on` / `/sentry off` |
|
|
127
|
+
| `/location` | Get GPS location |
|
|
128
|
+
| `/vehicle` | Full vehicle status summary |
|
|
129
|
+
|
|
130
|
+
## CLI Commands
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
openclaw tescmd status # Plugin and node status
|
|
134
|
+
openclaw tescmd commands # List all whitelisted commands
|
|
135
|
+
openclaw tescmd events # List telemetry event types
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Telemetry Events
|
|
139
|
+
|
|
140
|
+
The tescmd node streams these events to the Gateway in real-time:
|
|
141
|
+
|
|
142
|
+
| Event | Data |
|
|
143
|
+
|-------|------|
|
|
144
|
+
| `location` | latitude, longitude, heading, speed |
|
|
145
|
+
| `battery` | battery_level, range_miles |
|
|
146
|
+
| `inside_temp` / `outside_temp` | temp_f |
|
|
147
|
+
| `speed` | speed_mph |
|
|
148
|
+
| `charge_started` / `charge_complete` / `charge_stopped` | state |
|
|
149
|
+
| `charge_state_changed` | state |
|
|
150
|
+
| `security_changed` | field, value |
|
|
151
|
+
| `gear_changed` | gear |
|
|
152
|
+
| `trigger.fired` | trigger_id, field, value |
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
Minimal — the tescmd node handles all vehicle-specific configuration.
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"plugins": {
|
|
161
|
+
"entries": {
|
|
162
|
+
"openclaw-tescmd": {
|
|
163
|
+
"enabled": true,
|
|
164
|
+
"config": {
|
|
165
|
+
"debug": false
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
bun install
|
|
177
|
+
bun run check-types
|
|
178
|
+
bun run lint
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT
|
package/commands/cli.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI subcommands — terminal commands under `openclaw tescmd`.
|
|
3
|
+
*
|
|
4
|
+
* Registered commands:
|
|
5
|
+
* openclaw tescmd status — show plugin and node connection status
|
|
6
|
+
* openclaw tescmd commands — list all whitelisted commands
|
|
7
|
+
* openclaw tescmd events — list all telemetry event types
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
11
|
+
import { ALL_COMMANDS } from "../platform.js";
|
|
12
|
+
import { ALL_EVENT_TYPES, TELEMETRY_FIELD_MAP } from "../telemetry.js";
|
|
13
|
+
|
|
14
|
+
interface CliCommand {
|
|
15
|
+
command(name: string): CliCommand;
|
|
16
|
+
description(desc: string): CliCommand;
|
|
17
|
+
action(fn: () => void): CliCommand;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function registerCliCommands(api: OpenClawPluginApi): void {
|
|
21
|
+
api.registerCli(
|
|
22
|
+
({ program }: { program: unknown }) => {
|
|
23
|
+
const tescmd = (program as CliCommand)
|
|
24
|
+
.command("tescmd")
|
|
25
|
+
.description("Tesla vehicle platform (tescmd)");
|
|
26
|
+
|
|
27
|
+
tescmd
|
|
28
|
+
.command("status")
|
|
29
|
+
.description("Show plugin and node connection status")
|
|
30
|
+
.action(() => {
|
|
31
|
+
console.log("openclaw-tescmd plugin status");
|
|
32
|
+
console.log("─".repeat(40));
|
|
33
|
+
console.log(` Platform: tesla`);
|
|
34
|
+
console.log(` Commands: ${ALL_COMMANDS.length} whitelisted`);
|
|
35
|
+
console.log(` Events: ${ALL_EVENT_TYPES.length} telemetry types`);
|
|
36
|
+
console.log(` Node: https://github.com/oceanswave/tescmd`);
|
|
37
|
+
console.log(` Plugin: https://github.com/oceanswave/openclaw-tescmd`);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
tescmd
|
|
41
|
+
.command("commands")
|
|
42
|
+
.description("List all whitelisted commands")
|
|
43
|
+
.action(() => {
|
|
44
|
+
console.log("Whitelisted commands:");
|
|
45
|
+
console.log("");
|
|
46
|
+
const reads = ALL_COMMANDS.filter((c) => c.direction === "read");
|
|
47
|
+
const writes = ALL_COMMANDS.filter((c) => c.direction === "write");
|
|
48
|
+
console.log(` Reads (${reads.length}):`);
|
|
49
|
+
for (const cmd of reads) {
|
|
50
|
+
console.log(` ${cmd.method.padEnd(22)} ${cmd.label}`);
|
|
51
|
+
}
|
|
52
|
+
console.log("");
|
|
53
|
+
console.log(` Writes (${writes.length}):`);
|
|
54
|
+
for (const cmd of writes) {
|
|
55
|
+
console.log(` ${cmd.method.padEnd(22)} ${cmd.label}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
tescmd
|
|
60
|
+
.command("events")
|
|
61
|
+
.description("List all telemetry event types")
|
|
62
|
+
.action(() => {
|
|
63
|
+
console.log("Telemetry event types:");
|
|
64
|
+
console.log("");
|
|
65
|
+
for (const [field, eventType] of Object.entries(TELEMETRY_FIELD_MAP)) {
|
|
66
|
+
console.log(` ${field.padEnd(22)} → ${eventType}`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
{ commands: ["tescmd"] },
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
api.logger.info("Registered CLI commands: openclaw tescmd {status,commands,events}");
|
|
74
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash commands — user-typed shortcuts in chat.
|
|
3
|
+
*
|
|
4
|
+
* These are quick-action commands the user can type directly
|
|
5
|
+
* (e.g. "/battery", "/lock") without needing the agent to
|
|
6
|
+
* interpret natural language. Each command dispatches to the
|
|
7
|
+
* tescmd node and returns a formatted response.
|
|
8
|
+
*
|
|
9
|
+
* Registered commands:
|
|
10
|
+
* /battery — battery level + range
|
|
11
|
+
* /charge — full charge status
|
|
12
|
+
* /climate — temperature + climate state
|
|
13
|
+
* /lock — lock all doors
|
|
14
|
+
* /unlock — unlock all doors
|
|
15
|
+
* /sentry — toggle or check sentry mode
|
|
16
|
+
* /location — GPS coordinates
|
|
17
|
+
* /vehicle — comprehensive vehicle status summary
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
21
|
+
|
|
22
|
+
export function registerSlashCommands(api: OpenClawPluginApi): void {
|
|
23
|
+
api.registerCommand({
|
|
24
|
+
name: "battery",
|
|
25
|
+
description: "Check vehicle battery level and estimated range",
|
|
26
|
+
acceptsArgs: false,
|
|
27
|
+
requireAuth: true,
|
|
28
|
+
async handler(_ctx) {
|
|
29
|
+
return {
|
|
30
|
+
text: "Checking battery status via tescmd node...\n" + "_Invoking: battery.get_",
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
api.registerCommand({
|
|
36
|
+
name: "charge",
|
|
37
|
+
description: "Check charging status, or start/stop with arguments",
|
|
38
|
+
acceptsArgs: true,
|
|
39
|
+
requireAuth: true,
|
|
40
|
+
async handler(ctx) {
|
|
41
|
+
const arg = ctx.args?.trim().toLowerCase();
|
|
42
|
+
if (arg === "start") {
|
|
43
|
+
return { text: "Starting charge via tescmd node...\n_Invoking: charge.start_" };
|
|
44
|
+
}
|
|
45
|
+
if (arg === "stop") {
|
|
46
|
+
return { text: "Stopping charge via tescmd node...\n_Invoking: charge.stop_" };
|
|
47
|
+
}
|
|
48
|
+
if (arg && /^\d+$/.test(arg)) {
|
|
49
|
+
return {
|
|
50
|
+
text: `Setting charge limit to ${arg}% via tescmd node...\n_Invoking: charge.set_limit_`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
text:
|
|
55
|
+
"Checking charge state via tescmd node...\n" +
|
|
56
|
+
"_Invoking: charge_state.get + battery.get_\n\n" +
|
|
57
|
+
"**Usage:** `/charge` (status) | `/charge start` | `/charge stop` | `/charge 80` (set limit)",
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
api.registerCommand({
|
|
63
|
+
name: "climate",
|
|
64
|
+
description: "Check temperature or control climate (on/off/set)",
|
|
65
|
+
acceptsArgs: true,
|
|
66
|
+
requireAuth: true,
|
|
67
|
+
async handler(ctx) {
|
|
68
|
+
const arg = ctx.args?.trim().toLowerCase();
|
|
69
|
+
if (arg === "on") {
|
|
70
|
+
return { text: "Turning on climate via tescmd node...\n_Invoking: climate.on_" };
|
|
71
|
+
}
|
|
72
|
+
if (arg === "off") {
|
|
73
|
+
return { text: "Turning off climate via tescmd node...\n_Invoking: climate.off_" };
|
|
74
|
+
}
|
|
75
|
+
if (arg && /^\d+$/.test(arg)) {
|
|
76
|
+
return {
|
|
77
|
+
text: `Setting temperature to ${arg}°F via tescmd node...\n_Invoking: climate.set_temp_`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
text:
|
|
82
|
+
"Checking temperature via tescmd node...\n" +
|
|
83
|
+
"_Invoking: temperature.get_\n\n" +
|
|
84
|
+
"**Usage:** `/climate` (check) | `/climate on` | `/climate off` | `/climate 72` (set °F)",
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
api.registerCommand({
|
|
90
|
+
name: "lock",
|
|
91
|
+
description: "Lock all vehicle doors",
|
|
92
|
+
acceptsArgs: false,
|
|
93
|
+
requireAuth: true,
|
|
94
|
+
async handler(_ctx) {
|
|
95
|
+
return { text: "Locking doors via tescmd node...\n_Invoking: door.lock_" };
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
api.registerCommand({
|
|
100
|
+
name: "unlock",
|
|
101
|
+
description: "Unlock all vehicle doors",
|
|
102
|
+
acceptsArgs: false,
|
|
103
|
+
requireAuth: true,
|
|
104
|
+
async handler(_ctx) {
|
|
105
|
+
return { text: "Unlocking doors via tescmd node...\n_Invoking: door.unlock_" };
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
api.registerCommand({
|
|
110
|
+
name: "sentry",
|
|
111
|
+
description: "Check or toggle Sentry Mode (on/off)",
|
|
112
|
+
acceptsArgs: true,
|
|
113
|
+
requireAuth: true,
|
|
114
|
+
async handler(ctx) {
|
|
115
|
+
const arg = ctx.args?.trim().toLowerCase();
|
|
116
|
+
if (arg === "on") {
|
|
117
|
+
return { text: "Enabling Sentry Mode via tescmd node...\n_Invoking: sentry.on_" };
|
|
118
|
+
}
|
|
119
|
+
if (arg === "off") {
|
|
120
|
+
return { text: "Disabling Sentry Mode via tescmd node...\n_Invoking: sentry.off_" };
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
text:
|
|
124
|
+
"Checking security status via tescmd node...\n" +
|
|
125
|
+
"_Invoking: security.get_\n\n" +
|
|
126
|
+
"**Usage:** `/sentry` (check) | `/sentry on` | `/sentry off`",
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
api.registerCommand({
|
|
132
|
+
name: "location",
|
|
133
|
+
description: "Get vehicle GPS location",
|
|
134
|
+
acceptsArgs: false,
|
|
135
|
+
requireAuth: true,
|
|
136
|
+
async handler(_ctx) {
|
|
137
|
+
return {
|
|
138
|
+
text: "Getting vehicle location via tescmd node...\n_Invoking: location.get_",
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
api.registerCommand({
|
|
144
|
+
name: "vehicle",
|
|
145
|
+
description: "Comprehensive vehicle status summary",
|
|
146
|
+
acceptsArgs: false,
|
|
147
|
+
requireAuth: true,
|
|
148
|
+
async handler(_ctx) {
|
|
149
|
+
return {
|
|
150
|
+
text:
|
|
151
|
+
"Fetching full vehicle status via tescmd node...\n" +
|
|
152
|
+
"_Invoking: battery.get + charge_state.get + temperature.get + security.get + location.get_",
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
api.logger.info(
|
|
158
|
+
"Registered 8 slash commands: /battery /charge /climate /lock /unlock /sentry /location /vehicle",
|
|
159
|
+
);
|
|
160
|
+
}
|
package/config.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration parsing for the openclaw-tescmd plugin.
|
|
3
|
+
*
|
|
4
|
+
* Minimal — the tescmd node handles all vehicle-specific configuration.
|
|
5
|
+
* The plugin only exposes a debug toggle for verbose logging.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface TescmdConfig {
|
|
9
|
+
debug: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DEFAULT_CONFIG: TescmdConfig = {
|
|
13
|
+
debug: false,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Parse and validate raw plugin configuration.
|
|
18
|
+
*
|
|
19
|
+
* Returns a fully resolved {@link TescmdConfig} with defaults applied.
|
|
20
|
+
*/
|
|
21
|
+
export function parseConfig(raw: unknown): TescmdConfig {
|
|
22
|
+
if (raw == null || typeof raw !== "object") {
|
|
23
|
+
return { ...DEFAULT_CONFIG };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const obj = raw as Record<string, unknown>;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
debug: typeof obj.debug === "boolean" ? obj.debug : DEFAULT_CONFIG.debug,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Config schema export for the plugin entrypoint.
|
|
35
|
+
* OpenClaw calls `configSchema.parse()` to validate config at load time.
|
|
36
|
+
*/
|
|
37
|
+
export const tescmdConfigSchema = {
|
|
38
|
+
parse: parseConfig,
|
|
39
|
+
};
|
package/index.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw plugin: openclaw-tescmd
|
|
3
|
+
*
|
|
4
|
+
* Registers the Tesla vehicle platform with the OpenClaw Gateway,
|
|
5
|
+
* whitelists all 34 tescmd node commands, and exposes 37 richly-documented
|
|
6
|
+
* agent-callable tools for vehicle control and telemetry monitoring.
|
|
7
|
+
*
|
|
8
|
+
* The tescmd node (https://github.com/oceanswave/tescmd) connects to the
|
|
9
|
+
* Tesla Fleet API and streams real-time telemetry data. This plugin
|
|
10
|
+
* (https://github.com/oceanswave/openclaw-tescmd) is the Gateway-side
|
|
11
|
+
* counterpart that enables agents to discover and invoke Tesla vehicle
|
|
12
|
+
* commands through the OpenClaw tool system.
|
|
13
|
+
*
|
|
14
|
+
* Architecture:
|
|
15
|
+
* Agent → OpenClaw Gateway → [this plugin routes to] → tescmd node → Tesla Fleet API → Vehicle
|
|
16
|
+
*
|
|
17
|
+
* Tool categories (37 tools):
|
|
18
|
+
* - Help (1): capabilities reference and workflow guide (tescmd_help)
|
|
19
|
+
* - Status (1): node connection health check (tescmd_node_status)
|
|
20
|
+
* - Vehicle (3): location, battery, speed
|
|
21
|
+
* - Charge (4): charge state, start/stop/limit
|
|
22
|
+
* - Climate (4): temperature, HVAC on/off, set temp
|
|
23
|
+
* - Security (7): lock state, lock/unlock, flash, honk, sentry on/off
|
|
24
|
+
* - Trunk (2): trunk, frunk
|
|
25
|
+
* - Navigation (5): send destination, GPS, supercharger, waypoints, homelink
|
|
26
|
+
* - Triggers (8): list, poll, create, delete, + 4 convenience aliases
|
|
27
|
+
* - System (1): meta-dispatch (system.run)
|
|
28
|
+
*
|
|
29
|
+
* Slash commands (8):
|
|
30
|
+
* /battery, /charge, /climate, /lock, /unlock, /sentry, /location, /vehicle
|
|
31
|
+
*
|
|
32
|
+
* CLI subcommands:
|
|
33
|
+
* openclaw tescmd status | commands | events
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
37
|
+
import { registerCliCommands } from "./commands/cli.js";
|
|
38
|
+
import { registerSlashCommands } from "./commands/slash.js";
|
|
39
|
+
import { type TescmdConfig, tescmdConfigSchema } from "./config.js";
|
|
40
|
+
import { registerPlatform } from "./platform.js";
|
|
41
|
+
import { registerCapabilitiesTool } from "./tools/capabilities.js";
|
|
42
|
+
import { registerChargeTools } from "./tools/charge.js";
|
|
43
|
+
import { registerClimateTools } from "./tools/climate.js";
|
|
44
|
+
import { registerNavigationTools } from "./tools/navigation.js";
|
|
45
|
+
import { registerSecurityTools } from "./tools/security.js";
|
|
46
|
+
import { registerStatusTool } from "./tools/status.js";
|
|
47
|
+
import { registerSystemTools } from "./tools/system.js";
|
|
48
|
+
import { registerTriggerTools } from "./tools/triggers.js";
|
|
49
|
+
import { registerTrunkTools } from "./tools/trunk.js";
|
|
50
|
+
import { registerVehicleTools } from "./tools/vehicle.js";
|
|
51
|
+
|
|
52
|
+
export default {
|
|
53
|
+
id: "openclaw-tescmd",
|
|
54
|
+
name: "Tesla (tescmd)",
|
|
55
|
+
description:
|
|
56
|
+
"Tesla vehicle control and real-time telemetry via the tescmd node. " +
|
|
57
|
+
"Provides 37 agent-callable tools for vehicle status, charging, climate, " +
|
|
58
|
+
"security, trunk access, navigation, sentry mode, and trigger subscriptions. " +
|
|
59
|
+
"Streams telemetry events including GPS location, battery level, " +
|
|
60
|
+
"temperature, speed, charge state, and security changes.",
|
|
61
|
+
kind: "platform" as const,
|
|
62
|
+
configSchema: tescmdConfigSchema,
|
|
63
|
+
|
|
64
|
+
register(api: OpenClawPluginApi) {
|
|
65
|
+
const config = tescmdConfigSchema.parse(api.pluginConfig) as TescmdConfig;
|
|
66
|
+
|
|
67
|
+
if (config.debug) {
|
|
68
|
+
api.logger.info("openclaw-tescmd: debug mode enabled");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Register the Tesla platform + command whitelist
|
|
72
|
+
registerPlatform(api);
|
|
73
|
+
|
|
74
|
+
// Register all agent-callable tools by domain
|
|
75
|
+
registerCapabilitiesTool(api);
|
|
76
|
+
registerStatusTool(api);
|
|
77
|
+
registerVehicleTools(api);
|
|
78
|
+
registerChargeTools(api);
|
|
79
|
+
registerClimateTools(api);
|
|
80
|
+
registerSecurityTools(api);
|
|
81
|
+
registerTrunkTools(api);
|
|
82
|
+
registerNavigationTools(api);
|
|
83
|
+
registerTriggerTools(api);
|
|
84
|
+
registerSystemTools(api);
|
|
85
|
+
|
|
86
|
+
// Register slash commands and CLI subcommands
|
|
87
|
+
registerSlashCommands(api);
|
|
88
|
+
registerCliCommands(api);
|
|
89
|
+
|
|
90
|
+
// Register a service for lifecycle logging
|
|
91
|
+
api.registerService({
|
|
92
|
+
id: "tescmd-platform",
|
|
93
|
+
start() {
|
|
94
|
+
api.logger.info(
|
|
95
|
+
"openclaw-tescmd platform plugin active — " +
|
|
96
|
+
"34 commands whitelisted, 37 tools registered, " +
|
|
97
|
+
"8 slash commands, 3 CLI subcommands",
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
stop() {
|
|
101
|
+
api.logger.info("openclaw-tescmd platform plugin stopping");
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
api.logger.info("openclaw-tescmd plugin registered successfully");
|
|
106
|
+
},
|
|
107
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "openclaw-tescmd",
|
|
3
|
+
"kind": "platform",
|
|
4
|
+
"configSchema": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"debug": {
|
|
8
|
+
"type": "boolean",
|
|
9
|
+
"default": false,
|
|
10
|
+
"description": "Enable verbose debug logging"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"required": []
|
|
14
|
+
},
|
|
15
|
+
"uiHints": {
|
|
16
|
+
"debug": {
|
|
17
|
+
"label": "Debug Mode",
|
|
18
|
+
"help": "Enable verbose logging for troubleshooting node communication",
|
|
19
|
+
"advanced": true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oceanswave/openclaw-tescmd",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "OpenClaw platform plugin for Tesla vehicle control and telemetry via tescmd",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/oceanswave/openclaw-tescmd.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/oceanswave/openclaw-tescmd",
|
|
12
|
+
"files": [
|
|
13
|
+
"index.ts",
|
|
14
|
+
"config.ts",
|
|
15
|
+
"platform.ts",
|
|
16
|
+
"telemetry.ts",
|
|
17
|
+
"tools/",
|
|
18
|
+
"commands/",
|
|
19
|
+
"types/",
|
|
20
|
+
"openclaw.plugin.json",
|
|
21
|
+
"skill.md"
|
|
22
|
+
],
|
|
23
|
+
"openclaw": {
|
|
24
|
+
"extensions": [
|
|
25
|
+
"./index.ts"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"openclaw": ">=2026.1.29"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@sinclair/typebox": "^0.34.47"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@biomejs/biome": "^2.3.8",
|
|
36
|
+
"typescript": "^5.7.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"check-types": "tsc --noEmit",
|
|
43
|
+
"lint": "biome ci .",
|
|
44
|
+
"format": "biome format --write ."
|
|
45
|
+
}
|
|
46
|
+
}
|