@nubisco/openbridge 1.4.1 → 1.5.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.
Files changed (44) hide show
  1. package/dist/__tests__/auth-origin.test.js +2 -4
  2. package/dist/__tests__/auth-origin.test.js.map +1 -1
  3. package/dist/__tests__/mcp.test.d.ts +2 -0
  4. package/dist/__tests__/mcp.test.d.ts.map +1 -0
  5. package/dist/__tests__/mcp.test.js +464 -0
  6. package/dist/__tests__/mcp.test.js.map +1 -0
  7. package/dist/access.d.ts +148 -0
  8. package/dist/access.d.ts.map +1 -0
  9. package/dist/access.js +401 -0
  10. package/dist/access.js.map +1 -0
  11. package/dist/auth.d.ts +13 -5
  12. package/dist/auth.d.ts.map +1 -1
  13. package/dist/auth.js +16 -10
  14. package/dist/auth.js.map +1 -1
  15. package/dist/index.js +8 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/mcp/index.d.ts +48 -0
  18. package/dist/mcp/index.d.ts.map +1 -0
  19. package/dist/mcp/index.js +173 -0
  20. package/dist/mcp/index.js.map +1 -0
  21. package/dist/mcp/oauth.d.ts +35 -0
  22. package/dist/mcp/oauth.d.ts.map +1 -0
  23. package/dist/mcp/oauth.js +319 -0
  24. package/dist/mcp/oauth.js.map +1 -0
  25. package/dist/mcp/tools.d.ts +39 -0
  26. package/dist/mcp/tools.d.ts.map +1 -0
  27. package/dist/mcp/tools.js +432 -0
  28. package/dist/mcp/tools.js.map +1 -0
  29. package/dist/server.d.ts.map +1 -1
  30. package/dist/server.js +67 -114
  31. package/dist/server.js.map +1 -1
  32. package/dist/services/bridge.d.ts +102 -0
  33. package/dist/services/bridge.d.ts.map +1 -0
  34. package/dist/services/bridge.js +191 -0
  35. package/dist/services/bridge.js.map +1 -0
  36. package/dist/token-cli.d.ts +10 -0
  37. package/dist/token-cli.d.ts.map +1 -0
  38. package/dist/token-cli.js +76 -0
  39. package/dist/token-cli.js.map +1 -0
  40. package/package.json +6 -5
  41. package/ui-dist/assets/{index-CL7JhxrS.css → index-9bWNU3bq.css} +2 -2
  42. package/ui-dist/assets/index-DIyesg4J.js +109 -0
  43. package/ui-dist/index.html +2 -2
  44. package/ui-dist/assets/index-Rvs_bO_V.js +0 -109
@@ -0,0 +1,102 @@
1
+ /**
2
+ * What the bridge knows about its devices, as plain functions.
3
+ *
4
+ * The REST routes in server.ts and the MCP tools in mcp/tools.ts are two thin
5
+ * adapters over these, side by side in one process. Every check lives here, so
6
+ * an agent can never do more than the same request through the HTTP API (see
7
+ * "MCP servers" in the workspace AGENTS.md).
8
+ *
9
+ * A refusal is a ServiceError carrying the HTTP status the route answers with.
10
+ * Fastify sends it as it does any error with a statusCode, and the MCP layer
11
+ * turns it into a result the model reads.
12
+ */
13
+ import type { DeviceDescriptor, DeviceHealth, PluginRegistry } from '@nubisco/openbridge-core';
14
+ import { type LogEntry, type LogLevel } from '@nubisco/openbridge-logger';
15
+ import type { HomebridgeAPI } from '@nubisco/openbridge-compatibility-homebridge';
16
+ import type { DeviceEvent, DeviceEventLog } from '../device-events.js';
17
+ import type { DeviceObservation, ObservationStore } from '../observations.js';
18
+ import { type Point } from '../timeseries.js';
19
+ import type { HomeKitServiceTypes } from '../homekit-service-type.js';
20
+ export type ControlHandler = (value: unknown) => void | Promise<void>;
21
+ export declare class ServiceError extends Error {
22
+ readonly statusCode: number;
23
+ constructor(statusCode: number, message: string);
24
+ }
25
+ export declare function isServiceError(err: unknown): err is ServiceError;
26
+ /** Everything the functions below read, handed over once by createServer. */
27
+ export interface BridgeContext {
28
+ registry: PluginRegistry;
29
+ home: string;
30
+ hapAPI: HomebridgeAPI | null;
31
+ controls: Map<string, ControlHandler>;
32
+ restrictedControls: Set<string>;
33
+ deviceEvents: DeviceEventLog | null;
34
+ observations: ObservationStore | null;
35
+ homekitServiceTypes: HomeKitServiceTypes | null;
36
+ nativeAccessoryUuid: ((deviceId: string) => string | null) | null;
37
+ }
38
+ export type DeviceView = DeviceDescriptor & {
39
+ telemetry: Record<string, unknown>;
40
+ pluginStatus: string;
41
+ homekitType: string | null;
42
+ health: DeviceHealth;
43
+ };
44
+ /** Find a registered device by id across every plugin. */
45
+ export declare function findDevice(registry: PluginRegistry, deviceId: string): DeviceDescriptor | null;
46
+ /** Every device across every plugin, with its latest telemetry and health. */
47
+ export declare function listDevices(ctx: BridgeContext): DeviceView[];
48
+ export declare function getDevice(ctx: BridgeContext, deviceId: string): DeviceView;
49
+ /** The controls a plugin registered for a device, and whether each is restricted. */
50
+ export declare function deviceControls(ctx: BridgeContext, deviceId: string): Array<{
51
+ id: string;
52
+ restricted: boolean;
53
+ }>;
54
+ /** Run one control. A restricted control is refused here, for every caller. */
55
+ export declare function controlDevice(ctx: BridgeContext, deviceId: string, control: string, value: unknown): Promise<void>;
56
+ export interface MetricQuery {
57
+ metric?: string;
58
+ /** Unix seconds. Defaults to a day before `to`. */
59
+ from?: number;
60
+ /** Unix seconds. Defaults to now. */
61
+ to?: number;
62
+ maxPoints?: number;
63
+ }
64
+ export interface MetricSeries {
65
+ metric: NonNullable<DeviceDescriptor['metrics']>[number];
66
+ resolution: number;
67
+ tier: string;
68
+ from: number;
69
+ to: number;
70
+ points: Point[];
71
+ }
72
+ /**
73
+ * A device's recorded history for one metric over a range. Without a metric it
74
+ * reports what the device offers, so a caller can choose without a second read.
75
+ */
76
+ export declare function deviceMetrics(ctx: BridgeContext, deviceId: string, q: MetricQuery): {
77
+ deviceId: string;
78
+ metrics: NonNullable<DeviceDescriptor['metrics']>;
79
+ series: MetricSeries | null;
80
+ };
81
+ export declare function deviceEvents(ctx: BridgeContext, deviceId: string, limit?: number): DeviceEvent[];
82
+ export declare function deviceObservations(ctx: BridgeContext, deviceId: string, limit?: number): {
83
+ observations: DeviceObservation[];
84
+ total: number;
85
+ };
86
+ export interface LogQuery {
87
+ plugin?: string;
88
+ limit?: number;
89
+ /** Only this level and above. */
90
+ minLevel?: LogLevel;
91
+ /** Case-insensitive substring of the message. */
92
+ contains?: string;
93
+ /** ISO timestamp: only entries after it. */
94
+ since?: string;
95
+ }
96
+ /** The daemon's in-memory log buffer, oldest first, newest `limit` kept. */
97
+ export declare function readLogs(q: LogQuery): LogEntry[];
98
+ /** Accessories published by Homebridge-compatible plugins, with their characteristic values. */
99
+ export declare function listAccessories(ctx: BridgeContext): import("@nubisco/openbridge-compatibility-homebridge").SerializedAccessory[];
100
+ /** Write one HomeKit characteristic, which runs the plugin's onSet handler. */
101
+ export declare function setCharacteristic(ctx: BridgeContext, uuid: string, serviceUuid: string, charUuid: string, value: unknown): void;
102
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/services/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * What the bridge knows about its devices, as plain functions.
3
+ *
4
+ * The REST routes in server.ts and the MCP tools in mcp/tools.ts are two thin
5
+ * adapters over these, side by side in one process. Every check lives here, so
6
+ * an agent can never do more than the same request through the HTTP API (see
7
+ * "MCP servers" in the workspace AGENTS.md).
8
+ *
9
+ * A refusal is a ServiceError carrying the HTTP status the route answers with.
10
+ * Fastify sends it as it does any error with a statusCode, and the MCP layer
11
+ * turns it into a result the model reads.
12
+ */
13
+ import { readFileSync } from 'fs';
14
+ import { join } from 'path';
15
+ import { Logger } from '@nubisco/openbridge-logger';
16
+ import { assessDeviceHealth } from '../device-health.js';
17
+ import { DeviceSeries } from '../timeseries.js';
18
+ export class ServiceError extends Error {
19
+ statusCode;
20
+ constructor(statusCode, message) {
21
+ super(message);
22
+ this.statusCode = statusCode;
23
+ }
24
+ }
25
+ export function isServiceError(err) {
26
+ return err instanceof ServiceError;
27
+ }
28
+ function customNames(home) {
29
+ try {
30
+ return JSON.parse(readFileSync(join(home, 'device-names.json'), 'utf8'));
31
+ }
32
+ catch {
33
+ return {};
34
+ }
35
+ }
36
+ /** Find a registered device by id across every plugin. */
37
+ export function findDevice(registry, deviceId) {
38
+ for (const instance of registry.getAll()) {
39
+ const device = instance.devices?.[deviceId];
40
+ if (device)
41
+ return device;
42
+ }
43
+ return null;
44
+ }
45
+ /** Every device across every plugin, with its latest telemetry and health. */
46
+ export function listDevices(ctx) {
47
+ const names = customNames(ctx.home);
48
+ const devices = [];
49
+ for (const instance of ctx.registry.getAll()) {
50
+ if (!instance.devices)
51
+ continue;
52
+ for (const device of Object.values(instance.devices)) {
53
+ const telemetry = instance.telemetry?.[device.id] ?? {};
54
+ const name = names[device.id] ?? device.name;
55
+ // What the device is *presented* as, which may differ from the widget
56
+ // type its plugin declared. Sent so the card can show a relay driving a
57
+ // lamp as a light rather than contradicting the inspector next to it.
58
+ const accessoryUuid = ctx.nativeAccessoryUuid?.(device.id) ?? null;
59
+ const homekitType = accessoryUuid ? (ctx.homekitServiceTypes?.typeForAccessory(accessoryUuid) ?? null) : null;
60
+ // Derived here rather than stored, so it is always current and there
61
+ // is no second copy of the truth to go stale on its own.
62
+ const health = assessDeviceHealth({
63
+ telemetry,
64
+ intervalSeconds: device.telemetryIntervalSeconds,
65
+ pluginStatus: instance.status,
66
+ });
67
+ devices.push({ ...device, name, telemetry, pluginStatus: instance.status, homekitType, health });
68
+ }
69
+ }
70
+ return devices;
71
+ }
72
+ export function getDevice(ctx, deviceId) {
73
+ const device = listDevices(ctx).find((d) => d.id === deviceId);
74
+ if (!device)
75
+ throw new ServiceError(404, `Device '${deviceId}' not found`);
76
+ return device;
77
+ }
78
+ /** The controls a plugin registered for a device, and whether each is restricted. */
79
+ export function deviceControls(ctx, deviceId) {
80
+ const prefix = `${deviceId}::`;
81
+ const out = [];
82
+ for (const key of ctx.controls.keys()) {
83
+ if (!key.startsWith(prefix))
84
+ continue;
85
+ out.push({ id: key.slice(prefix.length), restricted: ctx.restrictedControls.has(key) });
86
+ }
87
+ return out;
88
+ }
89
+ /** Run one control. A restricted control is refused here, for every caller. */
90
+ export async function controlDevice(ctx, deviceId, control, value) {
91
+ const key = `${deviceId}::${control}`;
92
+ if (ctx.restrictedControls.has(key)) {
93
+ throw new ServiceError(403, `Control '${control}' is restricted for device '${deviceId}'`);
94
+ }
95
+ const handler = ctx.controls.get(key);
96
+ if (!handler)
97
+ throw new ServiceError(404, `No control '${control}' registered for device '${deviceId}'`);
98
+ await handler(value);
99
+ }
100
+ /**
101
+ * A device's recorded history for one metric over a range. Without a metric it
102
+ * reports what the device offers, so a caller can choose without a second read.
103
+ */
104
+ export function deviceMetrics(ctx, deviceId, q) {
105
+ const device = findDevice(ctx.registry, deviceId);
106
+ if (!device)
107
+ throw new ServiceError(404, `Device '${deviceId}' not found`);
108
+ const metrics = device.metrics ?? [];
109
+ if (metrics.length === 0)
110
+ return { deviceId, metrics: [], series: null };
111
+ if (!q.metric)
112
+ return { deviceId, metrics, series: null };
113
+ const descriptor = metrics.find((m) => m.key === q.metric);
114
+ if (!descriptor)
115
+ throw new ServiceError(404, `Device '${deviceId}' does not report '${q.metric}'`);
116
+ const now = Math.floor(Date.now() / 1000);
117
+ const toSec = q.to ?? now;
118
+ const fromSec = q.from ?? toSec - 86400;
119
+ if (!Number.isFinite(fromSec) || !Number.isFinite(toSec) || fromSec >= toSec) {
120
+ throw new ServiceError(400, 'Invalid from/to range');
121
+ }
122
+ const series = new DeviceSeries(join(ctx.home, 'metrics'), deviceId, metrics);
123
+ const points = Math.min(5000, Math.max(10, q.maxPoints || 720));
124
+ const result = series.query(descriptor.key, fromSec, toSec, points);
125
+ return {
126
+ deviceId,
127
+ metrics,
128
+ series: {
129
+ metric: descriptor,
130
+ resolution: result.tier.interval,
131
+ tier: result.tier.name,
132
+ from: fromSec,
133
+ to: toSec,
134
+ points: result.points,
135
+ },
136
+ };
137
+ }
138
+ export function deviceEvents(ctx, deviceId, limit = 100) {
139
+ if (!ctx.deviceEvents)
140
+ throw new ServiceError(503, 'event log unavailable');
141
+ return ctx.deviceEvents.read(deviceId, Number.isFinite(limit) ? limit : 100);
142
+ }
143
+ export function deviceObservations(ctx, deviceId, limit = 100) {
144
+ if (!ctx.observations)
145
+ throw new ServiceError(503, 'observation store unavailable');
146
+ return {
147
+ observations: ctx.observations.list(deviceId, Number.isFinite(limit) ? limit : 100),
148
+ total: ctx.observations.count(deviceId),
149
+ };
150
+ }
151
+ const LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
152
+ /** The daemon's in-memory log buffer, oldest first, newest `limit` kept. */
153
+ export function readLogs(q) {
154
+ const limit = q.limit ?? 200;
155
+ // The REST route never filtered, so it asks for the buffer as it always did.
156
+ if (!q.minLevel && !q.contains && !q.since)
157
+ return Logger.getEntries(q.plugin, limit);
158
+ const needle = q.contains?.toLowerCase();
159
+ const floor = q.minLevel ? LEVEL_ORDER[q.minLevel] : 0;
160
+ return Logger.getEntries(q.plugin, Number.MAX_SAFE_INTEGER)
161
+ .filter((e) => LEVEL_ORDER[e.level] >= floor &&
162
+ (!q.since || e.timestamp > q.since) &&
163
+ (!needle || e.message.toLowerCase().includes(needle)))
164
+ .slice(-limit);
165
+ }
166
+ /** Accessories published by Homebridge-compatible plugins, with their characteristic values. */
167
+ export function listAccessories(ctx) {
168
+ return ctx.hapAPI ? ctx.hapAPI.getAccessories() : [];
169
+ }
170
+ /** Write one HomeKit characteristic, which runs the plugin's onSet handler. */
171
+ export function setCharacteristic(ctx, uuid, serviceUuid, charUuid, value) {
172
+ if (!ctx.hapAPI)
173
+ throw new ServiceError(503, 'HAP not available');
174
+ const raw = ctx.hapAPI.getRawAccessories();
175
+ const acc = raw.find((a) => a.UUID === uuid);
176
+ if (!acc)
177
+ throw new ServiceError(404, `Accessory '${uuid}' not found`);
178
+ const svc = acc.services?.find((s) => s.UUID === serviceUuid);
179
+ if (!svc)
180
+ throw new ServiceError(404, `Service '${serviceUuid}' not found`);
181
+ const ch = svc.characteristics?.find((c) => c.UUID === charUuid);
182
+ if (!ch)
183
+ throw new ServiceError(404, `Characteristic '${charUuid}' not found`);
184
+ try {
185
+ ch.setValue(value);
186
+ }
187
+ catch (err) {
188
+ throw new ServiceError(500, `setValue failed: ${err}`);
189
+ }
190
+ }
191
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/services/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `openbridge token ...`: manage MCP tokens from the host.
3
+ *
4
+ * The way in for a bridge whose dashboard sign-in is off, and a way back in
5
+ * for any bridge: whoever has a shell on the host already owns the bridge, so
6
+ * no further proof is asked. Writes the same access.json the daemon reads, and
7
+ * the daemon picks the change up without a restart.
8
+ */
9
+ export declare function runTokenCommand(args: string[], home?: string): number;
10
+ //# sourceMappingURL=token-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-cli.d.ts","sourceRoot":"","sources":["../src/token-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmBH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,SAAuC,GAAG,MAAM,CAqDnG"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * `openbridge token ...`: manage MCP tokens from the host.
3
+ *
4
+ * The way in for a bridge whose dashboard sign-in is off, and a way back in
5
+ * for any bridge: whoever has a shell on the host already owns the bridge, so
6
+ * no further proof is asked. Writes the same access.json the daemon reads, and
7
+ * the daemon picks the change up without a restart.
8
+ */
9
+ import os from 'os';
10
+ import { join, resolve } from 'path';
11
+ import { AccessStore } from './access.js';
12
+ const USAGE = `Usage:
13
+ openbridge token create <name> [--control] Create a token (read-only unless --control)
14
+ openbridge token list List tokens
15
+ openbridge token revoke <id> Revoke a token
16
+
17
+ A token opens the MCP endpoint at /mcp and nothing else. Read-only tokens see
18
+ devices, history, events, observations and logs. --control also lets the agent
19
+ operate devices.`;
20
+ function flagValue(args, ...names) {
21
+ return args.some((a) => names.includes(a));
22
+ }
23
+ export function runTokenCommand(args, home = resolve(os.homedir(), '.openbridge')) {
24
+ const store = new AccessStore(join(home, 'access.json'));
25
+ const [sub, ...rest] = args;
26
+ const positional = rest.filter((a) => !a.startsWith('-'));
27
+ switch (sub) {
28
+ case 'create': {
29
+ const name = positional.join(' ').trim();
30
+ if (!name) {
31
+ console.error('A name is required, e.g. openbridge token create "Claude on my laptop"\n');
32
+ console.error(USAGE);
33
+ return 1;
34
+ }
35
+ const access = flagValue(rest, '--control') ? 'control' : 'read';
36
+ const { token } = store.createToken(name, access, { id: 'local', email: null });
37
+ console.log(`Created "${name}" with ${access === 'control' ? 'read and control' : 'read-only'} access.`);
38
+ console.log('It works once the daemon runs with OPENBRIDGE_MCP=on, which is off by default.');
39
+ console.log('Copy it now, it is not shown again:\n');
40
+ console.log(` ${token}\n`);
41
+ console.log('Connect Claude Code with:\n');
42
+ console.log(` claude mcp add --transport http openbridge http://<this-host>:8582/mcp \\`);
43
+ console.log(` --header "Authorization: Bearer ${token}"`);
44
+ return 0;
45
+ }
46
+ case 'list': {
47
+ const tokens = store.listTokens();
48
+ if (tokens.length === 0) {
49
+ console.log('No tokens.');
50
+ return 0;
51
+ }
52
+ for (const t of tokens) {
53
+ const used = t.lastUsedAt ? `last used ${t.lastUsedAt}` : 'never used';
54
+ console.log(`${t.id} ${t.access.padEnd(7)} ${t.name} (${used})`);
55
+ }
56
+ return 0;
57
+ }
58
+ case 'revoke': {
59
+ const id = positional[0];
60
+ if (!id) {
61
+ console.error(USAGE);
62
+ return 1;
63
+ }
64
+ if (!store.revokeToken(id)) {
65
+ console.error(`No token with id ${id}`);
66
+ return 1;
67
+ }
68
+ console.log('Revoked.');
69
+ return 0;
70
+ }
71
+ default:
72
+ console.log(USAGE);
73
+ return sub === undefined || sub === 'help' || sub === '--help' ? 0 : 1;
74
+ }
75
+ }
76
+ //# sourceMappingURL=token-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-cli.js","sourceRoot":"","sources":["../src/token-cli.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nubisco/openbridge",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "description": "Local-first home automation bridge for developers. Plugin-based, TypeScript-first, Homebridge-compatible.",
5
5
  "author": "José Silva <jose@nubisco.io>",
6
6
  "license": "MIT",
@@ -53,10 +53,11 @@
53
53
  "hap-nodejs": "^0.14.3",
54
54
  "qrcode-terminal": "^0.12.0",
55
55
  "systeminformation": "^5.33.16",
56
- "@nubisco/openbridge-compatibility-homebridge": "1.4.1",
57
- "@nubisco/openbridge-core": "1.4.1",
58
- "@nubisco/openbridge-config": "1.4.1",
59
- "@nubisco/openbridge-logger": "1.4.1"
56
+ "zod": "^4.3.5",
57
+ "@nubisco/openbridge-compatibility-homebridge": "1.5.1",
58
+ "@nubisco/openbridge-config": "1.5.1",
59
+ "@nubisco/openbridge-logger": "1.5.1",
60
+ "@nubisco/openbridge-core": "1.5.1"
60
61
  },
61
62
  "optionalDependencies": {
62
63
  "node-pty": "^1.1.0"