panteao-ts 1.0.0 → 1.1.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/dist/cjs/index.js +57 -28
- package/dist/esm/index.js +63 -72
- package/package.json +16 -6
- package/panteaots-1.0.0.tgz +0 -0
- package/src/index.ts +0 -306
- package/tsconfig.cjs.json +0 -8
- package/tsconfig.json +0 -13
package/dist/cjs/index.js
CHANGED
|
@@ -39,6 +39,45 @@ const events_1 = require("events");
|
|
|
39
39
|
const child_process = __importStar(require("child_process"));
|
|
40
40
|
const path = __importStar(require("path"));
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
|
+
const module_1 = require("module");
|
|
43
|
+
function findEngineBinary(binName) {
|
|
44
|
+
const platformPkg = `panteao-engine-${process.platform}-${process.arch}`;
|
|
45
|
+
const requireFromProject = (0, module_1.createRequire)(process.cwd() + '/package.json');
|
|
46
|
+
const searchRoots = [
|
|
47
|
+
process.cwd(),
|
|
48
|
+
path.resolve(process.cwd(), 'node_modules'),
|
|
49
|
+
path.resolve(process.cwd(), '..'),
|
|
50
|
+
path.resolve(process.cwd(), '..', '..'),
|
|
51
|
+
path.resolve(process.cwd(), '..', '..', '..')
|
|
52
|
+
];
|
|
53
|
+
const candidates = [];
|
|
54
|
+
for (const root of searchRoots) {
|
|
55
|
+
candidates.push(path.join(root, 'node_modules', platformPkg, 'bin', binName), path.join(root, 'node_modules', platformPkg, binName), path.join(root, platformPkg, 'bin', binName), path.join(root, platformPkg, binName), path.join(root, 'bin', binName), path.join(root, binName));
|
|
56
|
+
}
|
|
57
|
+
const envPath = process.env.PANTEAO_ENGINE_PATH || process.env.PANTEAO_ENGINE_BIN;
|
|
58
|
+
if (envPath) {
|
|
59
|
+
candidates.push(envPath);
|
|
60
|
+
}
|
|
61
|
+
for (const candidate of candidates) {
|
|
62
|
+
if (fs.existsSync(candidate)) {
|
|
63
|
+
return candidate;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const pkgPath = requireFromProject.resolve(path.join(platformPkg, 'package.json'));
|
|
68
|
+
const pkgDir = path.dirname(pkgPath);
|
|
69
|
+
for (const candidate of [
|
|
70
|
+
path.join(pkgDir, 'bin', binName),
|
|
71
|
+
path.join(pkgDir, binName)
|
|
72
|
+
]) {
|
|
73
|
+
if (fs.existsSync(candidate)) {
|
|
74
|
+
return candidate;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (e) { }
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
42
81
|
function getFreePort() {
|
|
43
82
|
return new Promise((resolve, reject) => {
|
|
44
83
|
const server = net.createServer();
|
|
@@ -78,38 +117,13 @@ class BdiClient extends events_1.EventEmitter {
|
|
|
78
117
|
if (!binPath) {
|
|
79
118
|
const isWin = process.platform === 'win32';
|
|
80
119
|
const binName = isWin ? 'panteao-engine.exe' : 'panteao-engine';
|
|
81
|
-
|
|
82
|
-
const platformPkg = `@panteao/engine-${process.platform}-${process.arch}`;
|
|
83
|
-
let resolvedPath = null;
|
|
84
|
-
try {
|
|
85
|
-
const pkgPath = require.resolve(path.join(platformPkg, 'package.json'));
|
|
86
|
-
const pkgDir = path.dirname(pkgPath);
|
|
87
|
-
const candidate = path.join(pkgDir, 'bin', binName);
|
|
88
|
-
const candidateFallback = path.join(pkgDir, binName);
|
|
89
|
-
if (fs.existsSync(candidate)) {
|
|
90
|
-
resolvedPath = candidate;
|
|
91
|
-
}
|
|
92
|
-
else if (fs.existsSync(candidateFallback)) {
|
|
93
|
-
resolvedPath = candidateFallback;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (e) {
|
|
97
|
-
// Platform package not installed or resolved
|
|
98
|
-
}
|
|
120
|
+
const resolvedPath = findEngineBinary(binName);
|
|
99
121
|
if (resolvedPath) {
|
|
100
122
|
binPath = resolvedPath;
|
|
101
123
|
}
|
|
102
124
|
else {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const candidate2 = path.join(__dirname, 'bin', binName);
|
|
106
|
-
if (fs.existsSync(candidate1)) {
|
|
107
|
-
binPath = candidate1;
|
|
108
|
-
}
|
|
109
|
-
else if (fs.existsSync(candidate2)) {
|
|
110
|
-
binPath = candidate2;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
125
|
+
binPath = path.join(process.cwd(), 'node_modules', '.bin', binName);
|
|
126
|
+
if (!fs.existsSync(binPath)) {
|
|
113
127
|
binPath = binName;
|
|
114
128
|
}
|
|
115
129
|
}
|
|
@@ -121,6 +135,21 @@ class BdiClient extends events_1.EventEmitter {
|
|
|
121
135
|
if (this.port === 0) {
|
|
122
136
|
this.port = await getFreePort();
|
|
123
137
|
}
|
|
138
|
+
if (!fs.existsSync(this.binPath)) {
|
|
139
|
+
const errMsg = `[Panteão] Engine binary not found at resolved path: ${this.binPath}. ` +
|
|
140
|
+
`Ensure the correct architecture package (panteao-engine-${process.platform}-${process.arch}) is installed ` +
|
|
141
|
+
`or provide a valid absolute path via the 'binPath' option.`;
|
|
142
|
+
this.emit('error', new Error(errMsg));
|
|
143
|
+
throw new Error(errMsg);
|
|
144
|
+
}
|
|
145
|
+
if (process.platform !== 'win32') {
|
|
146
|
+
try {
|
|
147
|
+
fs.accessSync(this.binPath, fs.constants.X_OK);
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
fs.chmodSync(this.binPath, 0o755);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
124
153
|
const args = [this.project, '--port', String(this.port)];
|
|
125
154
|
this.process = child_process.spawn(this.binPath, args, { stdio: 'ignore' });
|
|
126
155
|
await new Promise((resolve) => setTimeout(resolve, 800));
|
package/dist/esm/index.js
CHANGED
|
@@ -1,44 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import * as child_process from 'child_process';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
function findEngineBinary(binName) {
|
|
8
|
+
const platformPkg = `panteao-engine-${process.platform}-${process.arch}`;
|
|
9
|
+
const requireFromProject = createRequire(process.cwd() + '/package.json');
|
|
10
|
+
const searchRoots = [
|
|
11
|
+
process.cwd(),
|
|
12
|
+
path.resolve(process.cwd(), 'node_modules'),
|
|
13
|
+
path.resolve(process.cwd(), '..'),
|
|
14
|
+
path.resolve(process.cwd(), '..', '..'),
|
|
15
|
+
path.resolve(process.cwd(), '..', '..', '..')
|
|
16
|
+
];
|
|
17
|
+
const candidates = [];
|
|
18
|
+
for (const root of searchRoots) {
|
|
19
|
+
candidates.push(path.join(root, 'node_modules', platformPkg, 'bin', binName), path.join(root, 'node_modules', platformPkg, binName), path.join(root, platformPkg, 'bin', binName), path.join(root, platformPkg, binName), path.join(root, 'bin', binName), path.join(root, binName));
|
|
7
20
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Panteão = exports.Panteao = exports.BdiClient = void 0;
|
|
37
|
-
const net = __importStar(require("net"));
|
|
38
|
-
const events_1 = require("events");
|
|
39
|
-
const child_process = __importStar(require("child_process"));
|
|
40
|
-
const path = __importStar(require("path"));
|
|
41
|
-
const fs = __importStar(require("fs"));
|
|
21
|
+
const envPath = process.env.PANTEAO_ENGINE_PATH || process.env.PANTEAO_ENGINE_BIN;
|
|
22
|
+
if (envPath) {
|
|
23
|
+
candidates.push(envPath);
|
|
24
|
+
}
|
|
25
|
+
for (const candidate of candidates) {
|
|
26
|
+
if (fs.existsSync(candidate)) {
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const pkgPath = requireFromProject.resolve(path.join(platformPkg, 'package.json'));
|
|
32
|
+
const pkgDir = path.dirname(pkgPath);
|
|
33
|
+
for (const candidate of [
|
|
34
|
+
path.join(pkgDir, 'bin', binName),
|
|
35
|
+
path.join(pkgDir, binName)
|
|
36
|
+
]) {
|
|
37
|
+
if (fs.existsSync(candidate)) {
|
|
38
|
+
return candidate;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (e) { }
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
42
45
|
function getFreePort() {
|
|
43
46
|
return new Promise((resolve, reject) => {
|
|
44
47
|
const server = net.createServer();
|
|
@@ -55,7 +58,7 @@ function getFreePort() {
|
|
|
55
58
|
server.on('error', reject);
|
|
56
59
|
});
|
|
57
60
|
}
|
|
58
|
-
class BdiClient extends
|
|
61
|
+
export class BdiClient extends EventEmitter {
|
|
59
62
|
socket;
|
|
60
63
|
host;
|
|
61
64
|
port;
|
|
@@ -78,38 +81,13 @@ class BdiClient extends events_1.EventEmitter {
|
|
|
78
81
|
if (!binPath) {
|
|
79
82
|
const isWin = process.platform === 'win32';
|
|
80
83
|
const binName = isWin ? 'panteao-engine.exe' : 'panteao-engine';
|
|
81
|
-
|
|
82
|
-
const platformPkg = `@panteao/engine-${process.platform}-${process.arch}`;
|
|
83
|
-
let resolvedPath = null;
|
|
84
|
-
try {
|
|
85
|
-
const pkgPath = require.resolve(path.join(platformPkg, 'package.json'));
|
|
86
|
-
const pkgDir = path.dirname(pkgPath);
|
|
87
|
-
const candidate = path.join(pkgDir, 'bin', binName);
|
|
88
|
-
const candidateFallback = path.join(pkgDir, binName);
|
|
89
|
-
if (fs.existsSync(candidate)) {
|
|
90
|
-
resolvedPath = candidate;
|
|
91
|
-
}
|
|
92
|
-
else if (fs.existsSync(candidateFallback)) {
|
|
93
|
-
resolvedPath = candidateFallback;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (e) {
|
|
97
|
-
// Platform package not installed or resolved
|
|
98
|
-
}
|
|
84
|
+
const resolvedPath = findEngineBinary(binName);
|
|
99
85
|
if (resolvedPath) {
|
|
100
86
|
binPath = resolvedPath;
|
|
101
87
|
}
|
|
102
88
|
else {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const candidate2 = path.join(__dirname, 'bin', binName);
|
|
106
|
-
if (fs.existsSync(candidate1)) {
|
|
107
|
-
binPath = candidate1;
|
|
108
|
-
}
|
|
109
|
-
else if (fs.existsSync(candidate2)) {
|
|
110
|
-
binPath = candidate2;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
89
|
+
binPath = path.join(process.cwd(), 'node_modules', '.bin', binName);
|
|
90
|
+
if (!fs.existsSync(binPath)) {
|
|
113
91
|
binPath = binName;
|
|
114
92
|
}
|
|
115
93
|
}
|
|
@@ -121,6 +99,21 @@ class BdiClient extends events_1.EventEmitter {
|
|
|
121
99
|
if (this.port === 0) {
|
|
122
100
|
this.port = await getFreePort();
|
|
123
101
|
}
|
|
102
|
+
if (!fs.existsSync(this.binPath)) {
|
|
103
|
+
const errMsg = `[Panteão] Engine binary not found at resolved path: ${this.binPath}. ` +
|
|
104
|
+
`Ensure the correct architecture package (panteao-engine-${process.platform}-${process.arch}) is installed ` +
|
|
105
|
+
`or provide a valid absolute path via the 'binPath' option.`;
|
|
106
|
+
this.emit('error', new Error(errMsg));
|
|
107
|
+
throw new Error(errMsg);
|
|
108
|
+
}
|
|
109
|
+
if (process.platform !== 'win32') {
|
|
110
|
+
try {
|
|
111
|
+
fs.accessSync(this.binPath, fs.constants.X_OK);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
fs.chmodSync(this.binPath, 0o755);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
124
117
|
const args = [this.project, '--port', String(this.port)];
|
|
125
118
|
this.process = child_process.spawn(this.binPath, args, { stdio: 'ignore' });
|
|
126
119
|
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
@@ -318,6 +311,4 @@ class BdiClient extends events_1.EventEmitter {
|
|
|
318
311
|
}
|
|
319
312
|
}
|
|
320
313
|
}
|
|
321
|
-
|
|
322
|
-
exports.Panteao = BdiClient;
|
|
323
|
-
exports.Panteão = BdiClient;
|
|
314
|
+
export { BdiClient as Panteao, BdiClient as Panteão };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "panteao-ts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "TypeScript client for the Panteao BDI agent engine",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -20,16 +20,26 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsc && tsc -p tsconfig.cjs.json && echo '{\"type\": \"module\"}' > dist/esm/package.json && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json"
|
|
22
22
|
},
|
|
23
|
-
"keywords": [
|
|
23
|
+
"keywords": [
|
|
24
|
+
"bdi",
|
|
25
|
+
"agents",
|
|
26
|
+
"jason",
|
|
27
|
+
"ai",
|
|
28
|
+
"multi-agent",
|
|
29
|
+
"typescript"
|
|
30
|
+
],
|
|
24
31
|
"license": "MIT",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist/"
|
|
34
|
+
],
|
|
25
35
|
"devDependencies": {
|
|
26
36
|
"typescript": "^5.0.0",
|
|
27
37
|
"@types/node": "^20.0.0"
|
|
28
38
|
},
|
|
29
39
|
"optionalDependencies": {
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
40
|
+
"panteao-engine-win32-x64": "^1.0.0",
|
|
41
|
+
"panteao-engine-linux-x64": "^1.0.0",
|
|
42
|
+
"panteao-engine-darwin-arm64": "^1.0.0",
|
|
43
|
+
"panteao-engine-darwin-x64": "^1.0.0"
|
|
34
44
|
}
|
|
35
45
|
}
|
package/panteaots-1.0.0.tgz
DELETED
|
Binary file
|
package/src/index.ts
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import * as net from 'net';
|
|
2
|
-
import { EventEmitter } from 'events';
|
|
3
|
-
import * as child_process from 'child_process';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import * as fs from 'fs';
|
|
6
|
-
|
|
7
|
-
export interface BdiClientOptions {
|
|
8
|
-
host?: string;
|
|
9
|
-
port?: number;
|
|
10
|
-
autoReconnect?: boolean;
|
|
11
|
-
reconnectInterval?: number;
|
|
12
|
-
project?: string;
|
|
13
|
-
binPath?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type ActionCallback = (args: string[], respond: (success: boolean) => void) => void;
|
|
17
|
-
|
|
18
|
-
function getFreePort(): Promise<number> {
|
|
19
|
-
return new Promise((resolve, reject) => {
|
|
20
|
-
const server = net.createServer();
|
|
21
|
-
server.listen(0, '127.0.0.1', () => {
|
|
22
|
-
const address = server.address();
|
|
23
|
-
const port = typeof address === 'string' ? 0 : address?.port;
|
|
24
|
-
server.close(() => {
|
|
25
|
-
if (port) resolve(port);
|
|
26
|
-
else reject(new Error('Failed to allocate port'));
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
server.on('error', reject);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export class BdiClient extends EventEmitter {
|
|
34
|
-
private socket: net.Socket;
|
|
35
|
-
private host: string;
|
|
36
|
-
private port: number;
|
|
37
|
-
private buffer: string = '';
|
|
38
|
-
private autoReconnect: boolean;
|
|
39
|
-
private reconnectInterval: number;
|
|
40
|
-
private actionHandlers: Map<string, ActionCallback> = new Map();
|
|
41
|
-
private project?: string;
|
|
42
|
-
private binPath: string;
|
|
43
|
-
private process: child_process.ChildProcess | null = null;
|
|
44
|
-
|
|
45
|
-
constructor(options: BdiClientOptions = {}) {
|
|
46
|
-
super();
|
|
47
|
-
this.host = options.host || '127.0.0.1';
|
|
48
|
-
this.port = options.port || 0;
|
|
49
|
-
this.project = options.project;
|
|
50
|
-
this.autoReconnect = options.project ? false : (options.autoReconnect ?? true);
|
|
51
|
-
this.reconnectInterval = options.reconnectInterval || 2000;
|
|
52
|
-
this.socket = new net.Socket();
|
|
53
|
-
|
|
54
|
-
let binPath = options.binPath;
|
|
55
|
-
if (!binPath) {
|
|
56
|
-
const isWin = process.platform === 'win32';
|
|
57
|
-
const binName = isWin ? 'panteao-engine.exe' : 'panteao-engine';
|
|
58
|
-
|
|
59
|
-
// Try to resolve from platform-specific package first
|
|
60
|
-
const platformPkg = `@panteao/engine-${process.platform}-${process.arch}`;
|
|
61
|
-
let resolvedPath: string | null = null;
|
|
62
|
-
try {
|
|
63
|
-
const pkgPath = require.resolve(path.join(platformPkg, 'package.json'));
|
|
64
|
-
const pkgDir = path.dirname(pkgPath);
|
|
65
|
-
const candidate = path.join(pkgDir, 'bin', binName);
|
|
66
|
-
const candidateFallback = path.join(pkgDir, binName);
|
|
67
|
-
if (fs.existsSync(candidate)) {
|
|
68
|
-
resolvedPath = candidate;
|
|
69
|
-
} else if (fs.existsSync(candidateFallback)) {
|
|
70
|
-
resolvedPath = candidateFallback;
|
|
71
|
-
}
|
|
72
|
-
} catch (e) {
|
|
73
|
-
// Platform package not installed or resolved
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (resolvedPath) {
|
|
77
|
-
binPath = resolvedPath;
|
|
78
|
-
} else {
|
|
79
|
-
// Fallback to local paths
|
|
80
|
-
const candidate1 = path.join(__dirname, binName);
|
|
81
|
-
const candidate2 = path.join(__dirname, 'bin', binName);
|
|
82
|
-
if (fs.existsSync(candidate1)) {
|
|
83
|
-
binPath = candidate1;
|
|
84
|
-
} else if (fs.existsSync(candidate2)) {
|
|
85
|
-
binPath = candidate2;
|
|
86
|
-
} else {
|
|
87
|
-
binPath = binName;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
this.binPath = binPath;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public async connect(): Promise<void> {
|
|
95
|
-
if (this.project) {
|
|
96
|
-
if (this.port === 0) {
|
|
97
|
-
this.port = await getFreePort();
|
|
98
|
-
}
|
|
99
|
-
const args = [this.project, '--port', String(this.port)];
|
|
100
|
-
this.process = child_process.spawn(this.binPath, args, { stdio: 'ignore' });
|
|
101
|
-
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
102
|
-
} else if (this.port === 0) {
|
|
103
|
-
this.port = 44444;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return new Promise((resolve, reject) => {
|
|
107
|
-
let handshakeBuffer = '';
|
|
108
|
-
const onConnect = () => {
|
|
109
|
-
const onData = (data: Buffer) => {
|
|
110
|
-
handshakeBuffer += data.toString('utf8');
|
|
111
|
-
const lines = handshakeBuffer.split('\n');
|
|
112
|
-
handshakeBuffer = lines.pop() || '';
|
|
113
|
-
for (const line of lines) {
|
|
114
|
-
try {
|
|
115
|
-
if (!line.trim()) continue;
|
|
116
|
-
const msg = JSON.parse(line);
|
|
117
|
-
if (msg.type === 'mas_ready') {
|
|
118
|
-
this.socket.off('data', onData);
|
|
119
|
-
this.socket.off('error', onError);
|
|
120
|
-
this.setupSocketEvents();
|
|
121
|
-
this.emit('connect');
|
|
122
|
-
resolve();
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
} catch (e) {}
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
const onError = (err: Error) => {
|
|
129
|
-
this.socket.off('data', onData);
|
|
130
|
-
if (this.process) {
|
|
131
|
-
this.process.kill();
|
|
132
|
-
this.process = null;
|
|
133
|
-
}
|
|
134
|
-
reject(err);
|
|
135
|
-
};
|
|
136
|
-
this.socket.on('data', onData);
|
|
137
|
-
this.socket.once('error', onError);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const onInitialError = (err: Error) => {
|
|
141
|
-
if (this.process) {
|
|
142
|
-
this.process.kill();
|
|
143
|
-
this.process = null;
|
|
144
|
-
}
|
|
145
|
-
reject(err);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
this.socket.once('error', onInitialError);
|
|
149
|
-
this.socket.connect(this.port, this.host, () => {
|
|
150
|
-
this.socket.off('error', onInitialError);
|
|
151
|
-
onConnect();
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
private setupSocketEvents(): void {
|
|
157
|
-
this.socket.on('data', (data: Buffer) => {
|
|
158
|
-
this.buffer += data.toString('utf8');
|
|
159
|
-
const lines = this.buffer.split('\n');
|
|
160
|
-
this.buffer = lines.pop() || '';
|
|
161
|
-
|
|
162
|
-
for (const line of lines) {
|
|
163
|
-
if (line.trim().length === 0) continue;
|
|
164
|
-
this.handleIncomingLine(line);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
this.socket.on('close', () => {
|
|
169
|
-
this.emit('disconnect');
|
|
170
|
-
if (this.autoReconnect) {
|
|
171
|
-
setTimeout(() => {
|
|
172
|
-
this.connect().catch(() => {});
|
|
173
|
-
}, this.reconnectInterval);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
this.socket.on('error', (err: Error) => {
|
|
178
|
-
this.emit('error', err);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private handleIncomingLine(line: string): void {
|
|
183
|
-
try {
|
|
184
|
-
const msg = JSON.parse(line);
|
|
185
|
-
if (msg.type === 'action') {
|
|
186
|
-
const rawAction: string = msg.action;
|
|
187
|
-
const { name, args } = this.parseAction(rawAction);
|
|
188
|
-
const handler = this.actionHandlers.get(name);
|
|
189
|
-
|
|
190
|
-
if (handler) {
|
|
191
|
-
const respond = (success: boolean) => {
|
|
192
|
-
this.sendActionResult(msg.id, success);
|
|
193
|
-
};
|
|
194
|
-
handler(args, respond);
|
|
195
|
-
} else {
|
|
196
|
-
this.sendActionResult(msg.id, true);
|
|
197
|
-
}
|
|
198
|
-
this.emit('action', { name, args, agent: msg.agent, id: msg.id });
|
|
199
|
-
} else if (msg.type === 'message') {
|
|
200
|
-
const { performative, sender, receiver, content } = msg;
|
|
201
|
-
this.emit('message', performative, sender, receiver, content);
|
|
202
|
-
this.emit(performative, sender, receiver, content);
|
|
203
|
-
|
|
204
|
-
// Compatibility: parse message content as an action
|
|
205
|
-
if (content && typeof content === 'string') {
|
|
206
|
-
const parsed = this.parseAction(content);
|
|
207
|
-
if (parsed && parsed.name) {
|
|
208
|
-
const handler = this.actionHandlers.get(parsed.name);
|
|
209
|
-
if (handler) {
|
|
210
|
-
const dummyRespond = () => {};
|
|
211
|
-
handler(parsed.args, dummyRespond);
|
|
212
|
-
}
|
|
213
|
-
this.emit('action', { name: parsed.name, args: parsed.args, agent: sender, id: null });
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
} catch (e) {
|
|
218
|
-
this.emit('error', e);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
private parseAction(actionStr: string): { name: string; args: string[] } {
|
|
223
|
-
const parenIdx = actionStr.indexOf('(');
|
|
224
|
-
if (parenIdx === -1) {
|
|
225
|
-
return { name: actionStr.trim(), args: [] };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const name = actionStr.substring(0, parenIdx).trim();
|
|
229
|
-
const argsStr = actionStr.substring(parenIdx + 1, actionStr.lastIndexOf(')'));
|
|
230
|
-
|
|
231
|
-
const args: string[] = [];
|
|
232
|
-
let current = '';
|
|
233
|
-
let insideQuotes = false;
|
|
234
|
-
let depthBrackets = 0;
|
|
235
|
-
let depthParens = 0;
|
|
236
|
-
|
|
237
|
-
for (let i = 0; i < argsStr.length; i++) {
|
|
238
|
-
const char = argsStr[i];
|
|
239
|
-
if (char === '"') {
|
|
240
|
-
insideQuotes = !insideQuotes;
|
|
241
|
-
current += char;
|
|
242
|
-
} else if (!insideQuotes && char === '[') {
|
|
243
|
-
depthBrackets++;
|
|
244
|
-
current += char;
|
|
245
|
-
} else if (!insideQuotes && char === ']') {
|
|
246
|
-
depthBrackets--;
|
|
247
|
-
current += char;
|
|
248
|
-
} else if (!insideQuotes && char === '(') {
|
|
249
|
-
depthParens++;
|
|
250
|
-
current += char;
|
|
251
|
-
} else if (!insideQuotes && char === ')') {
|
|
252
|
-
depthParens--;
|
|
253
|
-
current += char;
|
|
254
|
-
} else if (char === ',' && !insideQuotes && depthBrackets === 0 && depthParens === 0) {
|
|
255
|
-
args.push(this.cleanArg(current));
|
|
256
|
-
current = '';
|
|
257
|
-
} else {
|
|
258
|
-
current += char;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (current.trim().length > 0) {
|
|
262
|
-
args.push(this.cleanArg(current));
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return { name, args };
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
private cleanArg(arg: string): string {
|
|
269
|
-
const s = arg.trim();
|
|
270
|
-
if (s.startsWith('"') && s.endsWith('"') && s.length >= 2) {
|
|
271
|
-
return s.substring(1, s.length - 1);
|
|
272
|
-
}
|
|
273
|
-
return s;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
public sendMsg(performative: string, sender: string, receiver: string, content: string): void {
|
|
277
|
-
const payload = JSON.stringify({ type: 'message', performative, sender, receiver, content }) + '\n';
|
|
278
|
-
this.socket.write(payload);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
public sendPerception(action: 'add' | 'remove', perception: string): void {
|
|
282
|
-
const payload = JSON.stringify({ type: 'perception', action, perception }) + '\n';
|
|
283
|
-
this.socket.write(payload);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
public registerAction(actionName: string, callback: ActionCallback): void {
|
|
287
|
-
this.actionHandlers.set(actionName, callback);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private sendActionResult(id: string, success: boolean): void {
|
|
291
|
-
const payload = JSON.stringify({ type: 'action_result', id, success }) + '\n';
|
|
292
|
-
this.socket.write(payload);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
public close(): void {
|
|
296
|
-
this.autoReconnect = false;
|
|
297
|
-
this.socket.destroy();
|
|
298
|
-
if (this.process) {
|
|
299
|
-
this.process.kill();
|
|
300
|
-
this.process = null;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export { BdiClient as Panteao, BdiClient as Panteão };
|
|
306
|
-
|
package/tsconfig.cjs.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"outDir": "./dist/esm",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true
|
|
11
|
-
},
|
|
12
|
-
"include": ["src/**/*"]
|
|
13
|
-
}
|