ha-opencode 0.1.1 → 0.2.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/discovery.js DELETED
@@ -1,257 +0,0 @@
1
- /**
2
- * Extract the unique portion of a session ID by stripping the "ses_" prefix.
3
- */
4
- export function extractSessionIdPart(sessionId) {
5
- return sessionId.replace(/^ses_/, "");
6
- }
7
- /**
8
- * Generate device ID from session ID.
9
- */
10
- export function getDeviceIdForSession(sessionId) {
11
- return `opencode_${extractSessionIdPart(sessionId)}`;
12
- }
13
- /**
14
- * Generate the availability topic for LWT configuration.
15
- * This can be called before Discovery is instantiated.
16
- */
17
- export function getAvailabilityTopicForSession(sessionId) {
18
- const deviceId = getDeviceIdForSession(sessionId);
19
- return `opencode/${deviceId}/availability`;
20
- }
21
- /**
22
- * Create MQTT LWT (Last Will and Testament) config for availability tracking.
23
- */
24
- export function createWillConfig(sessionId) {
25
- return {
26
- topic: getAvailabilityTopicForSession(sessionId),
27
- payload: "offline",
28
- retain: true,
29
- };
30
- }
31
- const ENTITY_DEFINITIONS = [
32
- {
33
- key: "device_id",
34
- name: "Device ID",
35
- icon: "mdi:identifier",
36
- hasAttributes: true,
37
- },
38
- {
39
- key: "state",
40
- name: "State",
41
- icon: "mdi:state-machine",
42
- hasAttributes: true,
43
- },
44
- {
45
- key: "session_title",
46
- name: "Session",
47
- icon: "mdi:message-text",
48
- },
49
- {
50
- key: "model",
51
- name: "Model",
52
- icon: "mdi:brain",
53
- },
54
- {
55
- key: "current_tool",
56
- name: "Current Tool",
57
- icon: "mdi:tools",
58
- },
59
- {
60
- key: "tokens_input",
61
- name: "Input Tokens",
62
- icon: "mdi:arrow-right-bold",
63
- unit: "tokens",
64
- state_class: "measurement",
65
- },
66
- {
67
- key: "tokens_output",
68
- name: "Output Tokens",
69
- icon: "mdi:arrow-left-bold",
70
- unit: "tokens",
71
- state_class: "measurement",
72
- },
73
- {
74
- key: "cost",
75
- name: "Cost",
76
- icon: "mdi:currency-usd",
77
- unit: "USD",
78
- state_class: "total_increasing",
79
- },
80
- {
81
- key: "last_activity",
82
- name: "Last Activity",
83
- icon: "mdi:clock-outline",
84
- device_class: "timestamp",
85
- },
86
- {
87
- key: "permission",
88
- name: "Permission Request",
89
- icon: "mdi:shield-alert",
90
- hasAttributes: true,
91
- },
92
- ];
93
- export class Discovery {
94
- mqtt;
95
- haConfig;
96
- deviceId;
97
- device;
98
- stateTopicBase;
99
- sessionId;
100
- projectName;
101
- constructor(mqtt, haConfig, sessionId, projectName) {
102
- this.mqtt = mqtt;
103
- this.haConfig = haConfig;
104
- this.sessionId = sessionId;
105
- this.projectName = projectName;
106
- // Create device ID from session ID (strip ses_ prefix, use full remaining ID)
107
- this.deviceId = getDeviceIdForSession(sessionId);
108
- // Initial device name uses project name with "Untitled" placeholder
109
- this.device = {
110
- identifiers: [this.deviceId],
111
- name: `OpenCode - ${projectName} - Untitled`,
112
- manufacturer: "OpenCode",
113
- model: "AI Coding Assistant",
114
- sw_version: sessionId,
115
- };
116
- this.stateTopicBase = `opencode/${this.deviceId}`;
117
- }
118
- /**
119
- * Update the device friendly name when session title becomes available.
120
- * This re-publishes all entity configs with the updated device name.
121
- */
122
- async updateDeviceName(title) {
123
- this.device.name = `OpenCode - ${this.projectName} - ${title}`;
124
- // Re-register all entities with updated device info
125
- await this.registerDevice();
126
- }
127
- async registerDevice() {
128
- for (const entity of ENTITY_DEFINITIONS) {
129
- await this.registerEntity(entity);
130
- }
131
- }
132
- async registerEntity(entity) {
133
- const uniqueId = `${this.deviceId}_${entity.key}`;
134
- const configTopic = `${this.haConfig.discoveryPrefix}/sensor/${this.deviceId}/${entity.key}/config`;
135
- const config = {
136
- name: entity.name,
137
- unique_id: uniqueId,
138
- state_topic: this.getStateTopic(entity.key),
139
- device: this.device,
140
- // Availability tracking - entities show as unavailable when plugin disconnects
141
- availability_topic: this.getAvailabilityTopic(),
142
- payload_available: "online",
143
- payload_not_available: "offline",
144
- };
145
- if (entity.icon) {
146
- config.icon = entity.icon;
147
- }
148
- if ("unit" in entity && entity.unit) {
149
- config.unit_of_measurement = entity.unit;
150
- }
151
- if ("state_class" in entity && entity.state_class) {
152
- config.state_class = entity.state_class;
153
- }
154
- if ("device_class" in entity && entity.device_class) {
155
- config.device_class = entity.device_class;
156
- }
157
- if ("hasAttributes" in entity && entity.hasAttributes) {
158
- config.json_attributes_topic = this.getAttributesTopic(entity.key);
159
- }
160
- await this.mqtt.publish(configTopic, config, true);
161
- }
162
- getStateTopic(key) {
163
- return `${this.stateTopicBase}/${key}`;
164
- }
165
- getAttributesTopic(key) {
166
- return `${this.stateTopicBase}/${key}/attributes`;
167
- }
168
- getCommandTopic() {
169
- return `${this.stateTopicBase}/command`;
170
- }
171
- getResponseTopic() {
172
- return `${this.stateTopicBase}/response`;
173
- }
174
- getAvailabilityTopic() {
175
- return `${this.stateTopicBase}/availability`;
176
- }
177
- /**
178
- * Publish online status. Call this after device registration.
179
- */
180
- async publishAvailable() {
181
- await this.mqtt.publish(this.getAvailabilityTopic(), "online", true);
182
- }
183
- /**
184
- * Publish offline status. Call this before graceful shutdown.
185
- */
186
- async publishUnavailable() {
187
- await this.mqtt.publish(this.getAvailabilityTopic(), "offline", true);
188
- }
189
- async publishState(key, value) {
190
- const topic = this.getStateTopic(key);
191
- let payload;
192
- if (typeof value === "number") {
193
- // Use decimal formatting only for cost, integers for token counts
194
- payload = key === "cost" ? value.toFixed(6) : String(value);
195
- }
196
- else {
197
- payload = value;
198
- }
199
- await this.mqtt.publish(topic, payload, true);
200
- }
201
- async publishAttributes(key, attributes) {
202
- const topic = this.getAttributesTopic(key);
203
- await this.mqtt.publish(topic, attributes, true);
204
- }
205
- async publishDeviceInfo() {
206
- await this.publishState("device_id", this.deviceId);
207
- await this.publishAttributes("device_id", {
208
- command_topic: this.getCommandTopic(),
209
- response_topic: this.getResponseTopic(),
210
- state_topic_base: this.stateTopicBase,
211
- device_name: this.device.name,
212
- session_id: this.sessionId,
213
- project_name: this.projectName,
214
- });
215
- }
216
- async publishPermission(permission) {
217
- if (permission) {
218
- await this.publishState("permission", "pending");
219
- // Sanitize metadata to ensure it's JSON-serializable (SDK may return Decimal objects)
220
- let safeMetadata = {};
221
- try {
222
- safeMetadata = JSON.parse(JSON.stringify(permission.metadata));
223
- }
224
- catch {
225
- safeMetadata = { error: "metadata not serializable" };
226
- }
227
- await this.publishAttributes("permission", {
228
- permission_id: permission.id,
229
- type: permission.type,
230
- title: permission.title,
231
- session_id: permission.sessionID,
232
- message_id: permission.messageID,
233
- call_id: permission.callID || null,
234
- pattern: permission.pattern || null,
235
- metadata: safeMetadata,
236
- });
237
- }
238
- else {
239
- await this.publishState("permission", "none");
240
- await this.publishAttributes("permission", {});
241
- }
242
- }
243
- async unregisterDevice() {
244
- // Publish empty config to remove entities
245
- for (const entity of ENTITY_DEFINITIONS) {
246
- const configTopic = `${this.haConfig.discoveryPrefix}/sensor/${this.deviceId}/${entity.key}/config`;
247
- await this.mqtt.publish(configTopic, "", true);
248
- }
249
- }
250
- /**
251
- * Get the list of all entity keys for cleanup purposes.
252
- */
253
- static getEntityKeys() {
254
- return ENTITY_DEFINITIONS.map((e) => e.key);
255
- }
256
- }
257
- //# sourceMappingURL=discovery.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
package/dist/mqtt.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { MqttConfig } from "./config.js";
2
- export type MessageHandler = (topic: string, payload: string) => void;
3
- export interface MqttWillConfig {
4
- topic: string;
5
- payload: string;
6
- retain: boolean;
7
- }
8
- export interface MqttWrapper {
9
- publish(topic: string, payload: string | object, retain?: boolean): Promise<void>;
10
- subscribe(topic: string, handler: MessageHandler): Promise<void>;
11
- unsubscribe(topic: string): Promise<void>;
12
- isConnected(): boolean;
13
- close(): Promise<void>;
14
- }
15
- export declare function connectMqtt(config: MqttConfig, will?: MqttWillConfig): Promise<MqttWrapper>;
16
- //# sourceMappingURL=mqtt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mqtt.d.ts","sourceRoot":"","sources":["../src/mqtt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,IAAI,OAAO,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAoDjG"}
package/dist/mqtt.js DELETED
@@ -1,141 +0,0 @@
1
- import mqtt from "mqtt";
2
- export async function connectMqtt(config, will) {
3
- const options = {
4
- clientId: config.clientId,
5
- clean: true,
6
- connectTimeout: 10000,
7
- reconnectPeriod: 5000,
8
- };
9
- if (config.username) {
10
- options.username = config.username;
11
- }
12
- if (config.password) {
13
- options.password = config.password;
14
- }
15
- // Configure Last Will and Testament (LWT) for availability tracking
16
- if (will) {
17
- options.will = {
18
- topic: will.topic,
19
- payload: Buffer.from(will.payload),
20
- qos: 1,
21
- retain: will.retain,
22
- };
23
- }
24
- const url = `mqtt://${config.host}:${config.port}`;
25
- return new Promise((resolve, reject) => {
26
- const client = mqtt.connect(url, options);
27
- let connected = false;
28
- const timeout = setTimeout(() => {
29
- if (!connected) {
30
- client.end(true);
31
- reject(new Error(`MQTT connection timeout to ${url}`));
32
- }
33
- }, options.connectTimeout);
34
- client.on("connect", () => {
35
- connected = true;
36
- clearTimeout(timeout);
37
- resolve(createWrapper(client));
38
- });
39
- client.on("error", (err) => {
40
- if (!connected) {
41
- clearTimeout(timeout);
42
- client.end(true); // Stop reconnection attempts
43
- reject(err);
44
- }
45
- });
46
- });
47
- }
48
- /**
49
- * Check if a topic matches a pattern with MQTT wildcards.
50
- * + matches a single level, # matches multiple levels.
51
- */
52
- function topicMatchesPattern(topic, pattern) {
53
- const topicParts = topic.split("/");
54
- const patternParts = pattern.split("/");
55
- for (let i = 0; i < patternParts.length; i++) {
56
- const patternPart = patternParts[i];
57
- if (patternPart === "#") {
58
- // # matches everything from this point
59
- return true;
60
- }
61
- if (i >= topicParts.length) {
62
- // Topic is shorter than pattern
63
- return false;
64
- }
65
- if (patternPart !== "+" && patternPart !== topicParts[i]) {
66
- // Not a wildcard and doesn't match
67
- return false;
68
- }
69
- }
70
- // Pattern and topic must be same length (unless pattern ends with #)
71
- return topicParts.length === patternParts.length;
72
- }
73
- function createWrapper(client) {
74
- const handlers = new Map();
75
- client.on("message", (topic, payload) => {
76
- // Check all registered patterns for a match
77
- for (const [pattern, handler] of handlers) {
78
- if (topicMatchesPattern(topic, pattern)) {
79
- try {
80
- handler(topic, payload.toString());
81
- }
82
- catch (err) {
83
- console.error(`[ha-opencode] Error handling message on ${topic}:`, err);
84
- }
85
- break; // Only call first matching handler
86
- }
87
- }
88
- });
89
- return {
90
- publish(topic, payload, retain = false) {
91
- return new Promise((resolve, reject) => {
92
- const message = typeof payload === "string" ? payload : JSON.stringify(payload);
93
- client.publish(topic, message, { qos: 1, retain }, (err) => {
94
- if (err) {
95
- reject(err);
96
- }
97
- else {
98
- resolve();
99
- }
100
- });
101
- });
102
- },
103
- subscribe(topic, handler) {
104
- return new Promise((resolve, reject) => {
105
- client.subscribe(topic, { qos: 1 }, (err) => {
106
- if (err) {
107
- reject(err);
108
- }
109
- else {
110
- handlers.set(topic, handler);
111
- resolve();
112
- }
113
- });
114
- });
115
- },
116
- unsubscribe(topic) {
117
- return new Promise((resolve, reject) => {
118
- client.unsubscribe(topic, (err) => {
119
- if (err) {
120
- reject(err);
121
- }
122
- else {
123
- handlers.delete(topic);
124
- resolve();
125
- }
126
- });
127
- });
128
- },
129
- isConnected() {
130
- return client.connected;
131
- },
132
- close() {
133
- return new Promise((resolve) => {
134
- client.end(false, {}, () => {
135
- resolve();
136
- });
137
- });
138
- },
139
- };
140
- }
141
- //# sourceMappingURL=mqtt.js.map
package/dist/mqtt.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"mqtt.js","sourceRoot":"","sources":["../src/mqtt.ts"],"names":[],"mappings":"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"}