neoagent 2.3.1-beta.30 → 2.3.1-beta.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.3.1-beta.30",
3
+ "version": "2.3.1-beta.32",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "MIT",
6
6
  "main": "server/index.js",
@@ -55,7 +55,6 @@
55
55
  "@google/generative-ai": "^0.24.0",
56
56
  "@modelcontextprotocol/sdk": "^1.12.1",
57
57
  "@meshtastic/core": "^2.6.7",
58
- "@meshtastic/transport-node": "^0.0.2",
59
58
  "baileys": "^6.7.21",
60
59
  "bcrypt": "^6.0.0",
61
60
  "better-sqlite3": "^11.8.1",
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"42d3d75a56efe1a2e9902f52dc8006099c45d9
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "3171035555" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "987887827" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { BasePlatform } = require('./base');
4
4
  const { readMeshtasticEnabled } = require('./meshtastic_env');
5
+ const { MeshtasticTcpTransport } = require('./meshtastic_tcp_transport');
5
6
 
6
7
  const DEFAULT_TCP_PORT = 4403;
7
8
  const DEFAULT_CHANNEL = 0;
@@ -48,14 +49,25 @@ function parseChannel(value) {
48
49
 
49
50
  async function loadMeshtasticModules() {
50
51
  if (!meshtasticModulesPromise) {
51
- meshtasticModulesPromise = Promise.all([
52
- import('@meshtastic/core'),
53
- import('@meshtastic/transport-node'),
54
- ]).then(([core, transport]) => ({
52
+ meshtasticModulesPromise = import('@meshtastic/core').then((core) => ({
55
53
  MeshDevice: core.MeshDevice,
56
54
  Types: core.Types,
57
- TransportNode: transport.TransportNode,
58
- }));
55
+ createTransport: (hostname, port, timeout) =>
56
+ MeshtasticTcpTransport.create(core, hostname, port, timeout),
57
+ })).catch((error) => {
58
+ meshtasticModulesPromise = null;
59
+ const message = String(error?.message || error || '');
60
+ if (
61
+ error?.code === 'ERR_MODULE_NOT_FOUND'
62
+ || /Cannot find package '@meshtastic\/core'/.test(message)
63
+ || /Cannot find module '@meshtastic\/core'/.test(message)
64
+ ) {
65
+ throw new Error(
66
+ 'Meshtastic support is not installed. Install @meshtastic/core or disable the Meshtastic integration.'
67
+ );
68
+ }
69
+ throw error;
70
+ });
59
71
  }
60
72
  return meshtasticModulesPromise;
61
73
  }
@@ -127,7 +139,7 @@ class MeshtasticPlatform extends BasePlatform {
127
139
  const modules = await loadMeshtasticModules();
128
140
  this._modules = modules;
129
141
 
130
- const transport = await modules.TransportNode.create(this.host, this.port, 60000);
142
+ const transport = await modules.createTransport(this.host, this.port, 60000);
131
143
  this._transport = transport;
132
144
 
133
145
  const device = new modules.MeshDevice(transport);
@@ -0,0 +1,147 @@
1
+ 'use strict';
2
+
3
+ const { Socket } = require('node:net');
4
+ const { Readable, Writable } = require('node:stream');
5
+
6
+ class MeshtasticTcpTransport {
7
+ static async create(core, hostname, port = 4403, timeout = 60000) {
8
+ return await new Promise((resolve, reject) => {
9
+ const socket = new Socket();
10
+ const onError = (error) => {
11
+ socket.destroy();
12
+ socket.removeAllListeners();
13
+ reject(error);
14
+ };
15
+
16
+ socket.once('error', onError);
17
+ socket.once('ready', () => {
18
+ socket.removeListener('error', onError);
19
+ resolve(new MeshtasticTcpTransport(core, socket));
20
+ });
21
+
22
+ socket.setTimeout(timeout);
23
+ socket.connect(port, hostname);
24
+ });
25
+ }
26
+
27
+ constructor(core, connection) {
28
+ this._core = core;
29
+ this._socket = connection;
30
+ this._lastStatus = core.Types.DeviceStatusEnum.DeviceDisconnected;
31
+ this._closingByUser = false;
32
+ this._errored = false;
33
+ this._fromDeviceController = null;
34
+ this._pipePromise = null;
35
+ this._abortController = new AbortController();
36
+
37
+ this._socket.on('error', () => {
38
+ this._errored = true;
39
+ this._socket?.removeAllListeners();
40
+ this._socket?.destroy();
41
+ if (!this._closingByUser) {
42
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceDisconnected, 'socket-error');
43
+ }
44
+ });
45
+
46
+ this._socket.on('end', () => {
47
+ if (this._closingByUser) return;
48
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceDisconnected, 'socket-end');
49
+ this._socket?.removeAllListeners();
50
+ this._socket?.destroy();
51
+ });
52
+
53
+ this._socket.on('timeout', () => {
54
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceDisconnected, 'socket-timeout');
55
+ this._socket?.removeAllListeners();
56
+ this._socket?.destroy();
57
+ });
58
+
59
+ this._socket.on('close', () => {
60
+ if (this._closingByUser) return;
61
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceDisconnected, 'socket-closed');
62
+ });
63
+
64
+ const transformed = Readable.toWeb(connection).pipeThrough(core.Utils.fromDeviceStream());
65
+ this._fromDevice = new ReadableStream({
66
+ start: async (controller) => {
67
+ this._fromDeviceController = controller;
68
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceConnecting);
69
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceConnected);
70
+ const reader = transformed.getReader();
71
+
72
+ try {
73
+ while (true) {
74
+ const { value, done } = await reader.read();
75
+ if (done) break;
76
+ controller.enqueue(value);
77
+ }
78
+ controller.close();
79
+ } catch (error) {
80
+ if (this._closingByUser || this._errored) {
81
+ controller.close();
82
+ } else {
83
+ this._emitStatus(core.Types.DeviceStatusEnum.DeviceDisconnected, 'read-error');
84
+ controller.error(error instanceof Error ? error : new Error(String(error)));
85
+ }
86
+
87
+ try {
88
+ await transformed.cancel();
89
+ } catch {}
90
+ } finally {
91
+ reader.releaseLock();
92
+ }
93
+ },
94
+ });
95
+
96
+ const toDeviceTransform = core.Utils.toDeviceStream();
97
+ this._toDevice = toDeviceTransform.writable;
98
+ this._pipePromise = toDeviceTransform.readable.pipeTo(
99
+ Writable.toWeb(connection),
100
+ { signal: this._abortController.signal }
101
+ ).catch((error) => {
102
+ if (this._abortController.signal.aborted || this._socket?.destroyed) return;
103
+ const socketError = error instanceof Error ? error : new Error(String(error));
104
+ this._socket?.destroy(socketError);
105
+ });
106
+ }
107
+
108
+ get toDevice() {
109
+ return this._toDevice;
110
+ }
111
+
112
+ get fromDevice() {
113
+ return this._fromDevice;
114
+ }
115
+
116
+ async disconnect() {
117
+ try {
118
+ this._closingByUser = true;
119
+ this._emitStatus(this._core.Types.DeviceStatusEnum.DeviceDisconnected, 'user');
120
+ this._abortController.abort();
121
+ if (this._pipePromise) {
122
+ await this._pipePromise;
123
+ }
124
+ this._socket?.destroy();
125
+ } finally {
126
+ this._socket = null;
127
+ this._closingByUser = false;
128
+ this._errored = false;
129
+ }
130
+ }
131
+
132
+ _emitStatus(nextStatus, reason) {
133
+ if (nextStatus === this._lastStatus) return;
134
+ this._lastStatus = nextStatus;
135
+ this._fromDeviceController?.enqueue({
136
+ type: 'status',
137
+ data: {
138
+ status: nextStatus,
139
+ reason,
140
+ },
141
+ });
142
+ }
143
+ }
144
+
145
+ module.exports = {
146
+ MeshtasticTcpTransport,
147
+ };