pty-manager 1.2.4 → 1.2.7
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/index.d.mts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +263 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +263 -7
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +263 -5
- package/package.json +1 -1
package/dist/pty-worker.js
CHANGED
|
@@ -304,6 +304,7 @@ var PTYSession = class extends import_events.EventEmitter {
|
|
|
304
304
|
_lastActivityAt = null;
|
|
305
305
|
messageCounter = 0;
|
|
306
306
|
logger;
|
|
307
|
+
sessionRules = [];
|
|
307
308
|
id;
|
|
308
309
|
config;
|
|
309
310
|
get status() {
|
|
@@ -318,6 +319,75 @@ var PTYSession = class extends import_events.EventEmitter {
|
|
|
318
319
|
get lastActivityAt() {
|
|
319
320
|
return this._lastActivityAt ?? void 0;
|
|
320
321
|
}
|
|
322
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
323
|
+
// Runtime Auto-Response Rules API
|
|
324
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
325
|
+
/**
|
|
326
|
+
* Add an auto-response rule to this session.
|
|
327
|
+
* Session rules are checked before adapter rules.
|
|
328
|
+
*/
|
|
329
|
+
addAutoResponseRule(rule) {
|
|
330
|
+
const existingIndex = this.sessionRules.findIndex(
|
|
331
|
+
(r) => r.pattern.source === rule.pattern.source && r.pattern.flags === rule.pattern.flags
|
|
332
|
+
);
|
|
333
|
+
if (existingIndex >= 0) {
|
|
334
|
+
this.sessionRules[existingIndex] = rule;
|
|
335
|
+
this.logger.debug(
|
|
336
|
+
{ sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
|
|
337
|
+
"Replaced existing auto-response rule"
|
|
338
|
+
);
|
|
339
|
+
} else {
|
|
340
|
+
this.sessionRules.push(rule);
|
|
341
|
+
this.logger.debug(
|
|
342
|
+
{ sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
|
|
343
|
+
"Added auto-response rule"
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Remove an auto-response rule by pattern.
|
|
349
|
+
* Returns true if a rule was removed.
|
|
350
|
+
*/
|
|
351
|
+
removeAutoResponseRule(pattern) {
|
|
352
|
+
const initialLength = this.sessionRules.length;
|
|
353
|
+
this.sessionRules = this.sessionRules.filter(
|
|
354
|
+
(r) => !(r.pattern.source === pattern.source && r.pattern.flags === pattern.flags)
|
|
355
|
+
);
|
|
356
|
+
const removed = this.sessionRules.length < initialLength;
|
|
357
|
+
if (removed) {
|
|
358
|
+
this.logger.debug(
|
|
359
|
+
{ sessionId: this.id, pattern: pattern.source },
|
|
360
|
+
"Removed auto-response rule"
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
return removed;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Set all session auto-response rules, replacing existing ones.
|
|
367
|
+
*/
|
|
368
|
+
setAutoResponseRules(rules) {
|
|
369
|
+
this.sessionRules = [...rules];
|
|
370
|
+
this.logger.debug(
|
|
371
|
+
{ sessionId: this.id, count: rules.length },
|
|
372
|
+
"Set auto-response rules"
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Get all session auto-response rules.
|
|
377
|
+
*/
|
|
378
|
+
getAutoResponseRules() {
|
|
379
|
+
return [...this.sessionRules];
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Clear all session auto-response rules.
|
|
383
|
+
*/
|
|
384
|
+
clearAutoResponseRules() {
|
|
385
|
+
this.sessionRules = [];
|
|
386
|
+
this.logger.debug({ sessionId: this.id }, "Cleared auto-response rules");
|
|
387
|
+
}
|
|
388
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
389
|
+
// Lifecycle
|
|
390
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
321
391
|
/**
|
|
322
392
|
* Start the PTY session
|
|
323
393
|
*/
|
|
@@ -459,23 +529,27 @@ var PTYSession = class extends import_events.EventEmitter {
|
|
|
459
529
|
return false;
|
|
460
530
|
}
|
|
461
531
|
/**
|
|
462
|
-
* Try to match and apply auto-response rules
|
|
532
|
+
* Try to match and apply auto-response rules.
|
|
533
|
+
* Session rules are checked first, then adapter rules.
|
|
463
534
|
*/
|
|
464
535
|
tryAutoResponse() {
|
|
465
|
-
const
|
|
466
|
-
|
|
536
|
+
const adapterRules = this.adapter.autoResponseRules || [];
|
|
537
|
+
const allRules = [...this.sessionRules, ...adapterRules];
|
|
538
|
+
if (allRules.length === 0) {
|
|
467
539
|
return false;
|
|
468
540
|
}
|
|
469
|
-
for (const rule of
|
|
541
|
+
for (const rule of allRules) {
|
|
470
542
|
if (rule.pattern.test(this.outputBuffer)) {
|
|
471
543
|
const safe = rule.safe !== false;
|
|
544
|
+
const isSessionRule = this.sessionRules.includes(rule);
|
|
472
545
|
if (safe) {
|
|
473
546
|
this.logger.info(
|
|
474
547
|
{
|
|
475
548
|
sessionId: this.id,
|
|
476
549
|
promptType: rule.type,
|
|
477
550
|
description: rule.description,
|
|
478
|
-
response: rule.response
|
|
551
|
+
response: rule.response,
|
|
552
|
+
source: isSessionRule ? "session" : "adapter"
|
|
479
553
|
},
|
|
480
554
|
"Applying auto-response rule"
|
|
481
555
|
);
|
|
@@ -946,6 +1020,61 @@ var PTYManager = class extends import_events2.EventEmitter {
|
|
|
946
1020
|
getSession(sessionId) {
|
|
947
1021
|
return this.sessions.get(sessionId);
|
|
948
1022
|
}
|
|
1023
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1024
|
+
// Runtime Auto-Response Rules API
|
|
1025
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1026
|
+
/**
|
|
1027
|
+
* Add an auto-response rule to a session.
|
|
1028
|
+
* Session rules are checked before adapter rules.
|
|
1029
|
+
*/
|
|
1030
|
+
addAutoResponseRule(sessionId, rule) {
|
|
1031
|
+
const session = this.sessions.get(sessionId);
|
|
1032
|
+
if (!session) {
|
|
1033
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1034
|
+
}
|
|
1035
|
+
session.addAutoResponseRule(rule);
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Remove an auto-response rule from a session by pattern.
|
|
1039
|
+
* Returns true if a rule was removed.
|
|
1040
|
+
*/
|
|
1041
|
+
removeAutoResponseRule(sessionId, pattern) {
|
|
1042
|
+
const session = this.sessions.get(sessionId);
|
|
1043
|
+
if (!session) {
|
|
1044
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1045
|
+
}
|
|
1046
|
+
return session.removeAutoResponseRule(pattern);
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Set all auto-response rules for a session, replacing existing ones.
|
|
1050
|
+
*/
|
|
1051
|
+
setAutoResponseRules(sessionId, rules) {
|
|
1052
|
+
const session = this.sessions.get(sessionId);
|
|
1053
|
+
if (!session) {
|
|
1054
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1055
|
+
}
|
|
1056
|
+
session.setAutoResponseRules(rules);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Get all auto-response rules for a session.
|
|
1060
|
+
*/
|
|
1061
|
+
getAutoResponseRules(sessionId) {
|
|
1062
|
+
const session = this.sessions.get(sessionId);
|
|
1063
|
+
if (!session) {
|
|
1064
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1065
|
+
}
|
|
1066
|
+
return session.getAutoResponseRules();
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Clear all auto-response rules for a session.
|
|
1070
|
+
*/
|
|
1071
|
+
clearAutoResponseRules(sessionId) {
|
|
1072
|
+
const session = this.sessions.get(sessionId);
|
|
1073
|
+
if (!session) {
|
|
1074
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1075
|
+
}
|
|
1076
|
+
session.clearAutoResponseRules();
|
|
1077
|
+
}
|
|
949
1078
|
};
|
|
950
1079
|
|
|
951
1080
|
// src/adapters/shell-adapter.ts
|
|
@@ -1185,6 +1314,93 @@ async function handleShutdown() {
|
|
|
1185
1314
|
}
|
|
1186
1315
|
setTimeout(() => process.exit(0), 100);
|
|
1187
1316
|
}
|
|
1317
|
+
function handleRegisterAdapters(modules) {
|
|
1318
|
+
try {
|
|
1319
|
+
for (const modulePath of modules) {
|
|
1320
|
+
const mod = require(modulePath);
|
|
1321
|
+
if (typeof mod.createAllAdapters === "function") {
|
|
1322
|
+
const adapters = mod.createAllAdapters();
|
|
1323
|
+
for (const adapter of adapters) {
|
|
1324
|
+
manager.registerAdapter(adapter);
|
|
1325
|
+
}
|
|
1326
|
+
} else if (Array.isArray(mod.default)) {
|
|
1327
|
+
for (const adapter of mod.default) {
|
|
1328
|
+
manager.registerAdapter(adapter);
|
|
1329
|
+
}
|
|
1330
|
+
} else if (mod.default && typeof mod.default.adapterType === "string") {
|
|
1331
|
+
manager.registerAdapter(mod.default);
|
|
1332
|
+
} else {
|
|
1333
|
+
throw new Error(`Module ${modulePath} does not export createAllAdapters() or adapters`);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
ack("registerAdapters", void 0, true);
|
|
1337
|
+
} catch (err) {
|
|
1338
|
+
ack("registerAdapters", void 0, false, err instanceof Error ? err.message : String(err));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
function deserializeRule(serialized) {
|
|
1342
|
+
return {
|
|
1343
|
+
pattern: new RegExp(serialized.pattern, serialized.flags || ""),
|
|
1344
|
+
type: serialized.type,
|
|
1345
|
+
response: serialized.response,
|
|
1346
|
+
description: serialized.description,
|
|
1347
|
+
safe: serialized.safe
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
function serializeRule(rule) {
|
|
1351
|
+
return {
|
|
1352
|
+
pattern: rule.pattern.source,
|
|
1353
|
+
flags: rule.pattern.flags || void 0,
|
|
1354
|
+
type: rule.type,
|
|
1355
|
+
response: rule.response,
|
|
1356
|
+
description: rule.description,
|
|
1357
|
+
safe: rule.safe
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
function handleAddRule(id, serializedRule) {
|
|
1361
|
+
try {
|
|
1362
|
+
const rule = deserializeRule(serializedRule);
|
|
1363
|
+
manager.addAutoResponseRule(id, rule);
|
|
1364
|
+
ack("addRule", id, true);
|
|
1365
|
+
} catch (err) {
|
|
1366
|
+
ack("addRule", id, false, err instanceof Error ? err.message : String(err));
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
function handleRemoveRule(id, pattern, flags) {
|
|
1370
|
+
try {
|
|
1371
|
+
const regex = new RegExp(pattern, flags || "");
|
|
1372
|
+
const removed = manager.removeAutoResponseRule(id, regex);
|
|
1373
|
+
ack("removeRule", id, removed, removed ? void 0 : "Rule not found");
|
|
1374
|
+
} catch (err) {
|
|
1375
|
+
ack("removeRule", id, false, err instanceof Error ? err.message : String(err));
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
function handleSetRules(id, serializedRules) {
|
|
1379
|
+
try {
|
|
1380
|
+
const rules = serializedRules.map(deserializeRule);
|
|
1381
|
+
manager.setAutoResponseRules(id, rules);
|
|
1382
|
+
ack("setRules", id, true);
|
|
1383
|
+
} catch (err) {
|
|
1384
|
+
ack("setRules", id, false, err instanceof Error ? err.message : String(err));
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
function handleGetRules(id) {
|
|
1388
|
+
try {
|
|
1389
|
+
const rules = manager.getAutoResponseRules(id);
|
|
1390
|
+
const serialized = rules.map(serializeRule);
|
|
1391
|
+
emit({ event: "rules", id, rules: serialized });
|
|
1392
|
+
} catch (err) {
|
|
1393
|
+
emit({ event: "error", id, message: err instanceof Error ? err.message : String(err) });
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
function handleClearRules(id) {
|
|
1397
|
+
try {
|
|
1398
|
+
manager.clearAutoResponseRules(id);
|
|
1399
|
+
ack("clearRules", id, true);
|
|
1400
|
+
} catch (err) {
|
|
1401
|
+
ack("clearRules", id, false, err instanceof Error ? err.message : String(err));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1188
1404
|
function processCommand(line) {
|
|
1189
1405
|
let command;
|
|
1190
1406
|
try {
|
|
@@ -1242,6 +1458,48 @@ function processCommand(line) {
|
|
|
1242
1458
|
case "shutdown":
|
|
1243
1459
|
handleShutdown();
|
|
1244
1460
|
break;
|
|
1461
|
+
case "registerAdapters":
|
|
1462
|
+
if (!command.modules || !Array.isArray(command.modules)) {
|
|
1463
|
+
ack("registerAdapters", void 0, false, "Missing modules array");
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
handleRegisterAdapters(command.modules);
|
|
1467
|
+
break;
|
|
1468
|
+
case "addRule":
|
|
1469
|
+
if (!command.id || !command.rule) {
|
|
1470
|
+
ack("addRule", command.id, false, "Missing id or rule");
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
handleAddRule(command.id, command.rule);
|
|
1474
|
+
break;
|
|
1475
|
+
case "removeRule":
|
|
1476
|
+
if (!command.id || !command.pattern) {
|
|
1477
|
+
ack("removeRule", command.id, false, "Missing id or pattern");
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
handleRemoveRule(command.id, command.pattern, command.flags);
|
|
1481
|
+
break;
|
|
1482
|
+
case "setRules":
|
|
1483
|
+
if (!command.id || !command.rules) {
|
|
1484
|
+
ack("setRules", command.id, false, "Missing id or rules");
|
|
1485
|
+
return;
|
|
1486
|
+
}
|
|
1487
|
+
handleSetRules(command.id, command.rules);
|
|
1488
|
+
break;
|
|
1489
|
+
case "getRules":
|
|
1490
|
+
if (!command.id) {
|
|
1491
|
+
ack("getRules", command.id, false, "Missing id");
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
handleGetRules(command.id);
|
|
1495
|
+
break;
|
|
1496
|
+
case "clearRules":
|
|
1497
|
+
if (!command.id) {
|
|
1498
|
+
ack("clearRules", command.id, false, "Missing id");
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
handleClearRules(command.id);
|
|
1502
|
+
break;
|
|
1245
1503
|
default:
|
|
1246
1504
|
emit({ event: "error", message: `Unknown command: ${command.cmd}` });
|
|
1247
1505
|
}
|
package/package.json
CHANGED