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/index.mjs
CHANGED
|
@@ -283,6 +283,7 @@ var PTYSession = class extends EventEmitter {
|
|
|
283
283
|
_lastActivityAt = null;
|
|
284
284
|
messageCounter = 0;
|
|
285
285
|
logger;
|
|
286
|
+
sessionRules = [];
|
|
286
287
|
id;
|
|
287
288
|
config;
|
|
288
289
|
get status() {
|
|
@@ -297,6 +298,75 @@ var PTYSession = class extends EventEmitter {
|
|
|
297
298
|
get lastActivityAt() {
|
|
298
299
|
return this._lastActivityAt ?? void 0;
|
|
299
300
|
}
|
|
301
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
302
|
+
// Runtime Auto-Response Rules API
|
|
303
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
304
|
+
/**
|
|
305
|
+
* Add an auto-response rule to this session.
|
|
306
|
+
* Session rules are checked before adapter rules.
|
|
307
|
+
*/
|
|
308
|
+
addAutoResponseRule(rule) {
|
|
309
|
+
const existingIndex = this.sessionRules.findIndex(
|
|
310
|
+
(r) => r.pattern.source === rule.pattern.source && r.pattern.flags === rule.pattern.flags
|
|
311
|
+
);
|
|
312
|
+
if (existingIndex >= 0) {
|
|
313
|
+
this.sessionRules[existingIndex] = rule;
|
|
314
|
+
this.logger.debug(
|
|
315
|
+
{ sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
|
|
316
|
+
"Replaced existing auto-response rule"
|
|
317
|
+
);
|
|
318
|
+
} else {
|
|
319
|
+
this.sessionRules.push(rule);
|
|
320
|
+
this.logger.debug(
|
|
321
|
+
{ sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
|
|
322
|
+
"Added auto-response rule"
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Remove an auto-response rule by pattern.
|
|
328
|
+
* Returns true if a rule was removed.
|
|
329
|
+
*/
|
|
330
|
+
removeAutoResponseRule(pattern) {
|
|
331
|
+
const initialLength = this.sessionRules.length;
|
|
332
|
+
this.sessionRules = this.sessionRules.filter(
|
|
333
|
+
(r) => !(r.pattern.source === pattern.source && r.pattern.flags === pattern.flags)
|
|
334
|
+
);
|
|
335
|
+
const removed = this.sessionRules.length < initialLength;
|
|
336
|
+
if (removed) {
|
|
337
|
+
this.logger.debug(
|
|
338
|
+
{ sessionId: this.id, pattern: pattern.source },
|
|
339
|
+
"Removed auto-response rule"
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
return removed;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Set all session auto-response rules, replacing existing ones.
|
|
346
|
+
*/
|
|
347
|
+
setAutoResponseRules(rules) {
|
|
348
|
+
this.sessionRules = [...rules];
|
|
349
|
+
this.logger.debug(
|
|
350
|
+
{ sessionId: this.id, count: rules.length },
|
|
351
|
+
"Set auto-response rules"
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get all session auto-response rules.
|
|
356
|
+
*/
|
|
357
|
+
getAutoResponseRules() {
|
|
358
|
+
return [...this.sessionRules];
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Clear all session auto-response rules.
|
|
362
|
+
*/
|
|
363
|
+
clearAutoResponseRules() {
|
|
364
|
+
this.sessionRules = [];
|
|
365
|
+
this.logger.debug({ sessionId: this.id }, "Cleared auto-response rules");
|
|
366
|
+
}
|
|
367
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
368
|
+
// Lifecycle
|
|
369
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
300
370
|
/**
|
|
301
371
|
* Start the PTY session
|
|
302
372
|
*/
|
|
@@ -438,23 +508,27 @@ var PTYSession = class extends EventEmitter {
|
|
|
438
508
|
return false;
|
|
439
509
|
}
|
|
440
510
|
/**
|
|
441
|
-
* Try to match and apply auto-response rules
|
|
511
|
+
* Try to match and apply auto-response rules.
|
|
512
|
+
* Session rules are checked first, then adapter rules.
|
|
442
513
|
*/
|
|
443
514
|
tryAutoResponse() {
|
|
444
|
-
const
|
|
445
|
-
|
|
515
|
+
const adapterRules = this.adapter.autoResponseRules || [];
|
|
516
|
+
const allRules = [...this.sessionRules, ...adapterRules];
|
|
517
|
+
if (allRules.length === 0) {
|
|
446
518
|
return false;
|
|
447
519
|
}
|
|
448
|
-
for (const rule of
|
|
520
|
+
for (const rule of allRules) {
|
|
449
521
|
if (rule.pattern.test(this.outputBuffer)) {
|
|
450
522
|
const safe = rule.safe !== false;
|
|
523
|
+
const isSessionRule = this.sessionRules.includes(rule);
|
|
451
524
|
if (safe) {
|
|
452
525
|
this.logger.info(
|
|
453
526
|
{
|
|
454
527
|
sessionId: this.id,
|
|
455
528
|
promptType: rule.type,
|
|
456
529
|
description: rule.description,
|
|
457
|
-
response: rule.response
|
|
530
|
+
response: rule.response,
|
|
531
|
+
source: isSessionRule ? "session" : "adapter"
|
|
458
532
|
},
|
|
459
533
|
"Applying auto-response rule"
|
|
460
534
|
);
|
|
@@ -925,6 +999,61 @@ var PTYManager = class extends EventEmitter2 {
|
|
|
925
999
|
getSession(sessionId) {
|
|
926
1000
|
return this.sessions.get(sessionId);
|
|
927
1001
|
}
|
|
1002
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1003
|
+
// Runtime Auto-Response Rules API
|
|
1004
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1005
|
+
/**
|
|
1006
|
+
* Add an auto-response rule to a session.
|
|
1007
|
+
* Session rules are checked before adapter rules.
|
|
1008
|
+
*/
|
|
1009
|
+
addAutoResponseRule(sessionId, rule) {
|
|
1010
|
+
const session = this.sessions.get(sessionId);
|
|
1011
|
+
if (!session) {
|
|
1012
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1013
|
+
}
|
|
1014
|
+
session.addAutoResponseRule(rule);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Remove an auto-response rule from a session by pattern.
|
|
1018
|
+
* Returns true if a rule was removed.
|
|
1019
|
+
*/
|
|
1020
|
+
removeAutoResponseRule(sessionId, pattern) {
|
|
1021
|
+
const session = this.sessions.get(sessionId);
|
|
1022
|
+
if (!session) {
|
|
1023
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1024
|
+
}
|
|
1025
|
+
return session.removeAutoResponseRule(pattern);
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Set all auto-response rules for a session, replacing existing ones.
|
|
1029
|
+
*/
|
|
1030
|
+
setAutoResponseRules(sessionId, rules) {
|
|
1031
|
+
const session = this.sessions.get(sessionId);
|
|
1032
|
+
if (!session) {
|
|
1033
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1034
|
+
}
|
|
1035
|
+
session.setAutoResponseRules(rules);
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Get all auto-response rules for a session.
|
|
1039
|
+
*/
|
|
1040
|
+
getAutoResponseRules(sessionId) {
|
|
1041
|
+
const session = this.sessions.get(sessionId);
|
|
1042
|
+
if (!session) {
|
|
1043
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1044
|
+
}
|
|
1045
|
+
return session.getAutoResponseRules();
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Clear all auto-response rules for a session.
|
|
1049
|
+
*/
|
|
1050
|
+
clearAutoResponseRules(sessionId) {
|
|
1051
|
+
const session = this.sessions.get(sessionId);
|
|
1052
|
+
if (!session) {
|
|
1053
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
1054
|
+
}
|
|
1055
|
+
session.clearAutoResponseRules();
|
|
1056
|
+
}
|
|
928
1057
|
};
|
|
929
1058
|
|
|
930
1059
|
// src/adapters/base-adapter.ts
|
|
@@ -1011,7 +1140,7 @@ var BaseCLIAdapter = class {
|
|
|
1011
1140
|
instructions: "Please select a project or workspace"
|
|
1012
1141
|
};
|
|
1013
1142
|
}
|
|
1014
|
-
if (/\[y\/n\]|\(y\/n\)|\[Y\/n\]|\[y\/N\]
|
|
1143
|
+
if (/\[y\/n\]|\(y\/n\)|\[Y\/n\]|\[y\/N\]|\(Y\)es\/\(N\)o|Yes\/No\??/i.test(stripped)) {
|
|
1015
1144
|
return {
|
|
1016
1145
|
detected: true,
|
|
1017
1146
|
type: "unknown",
|
|
@@ -1019,7 +1148,49 @@ var BaseCLIAdapter = class {
|
|
|
1019
1148
|
// Last 200 chars for context
|
|
1020
1149
|
options: ["y", "n"],
|
|
1021
1150
|
canAutoRespond: false,
|
|
1022
|
-
instructions: "
|
|
1151
|
+
instructions: "Confirmation prompt detected"
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
if (/^\s*[›>]?\s*[1-9]\.\s+\w+/m.test(stripped) && /\?\s*$/m.test(stripped)) {
|
|
1155
|
+
const optionMatches = stripped.match(/[›>]?\s*([1-9])\.\s+([^\n]+)/g);
|
|
1156
|
+
const options = optionMatches ? optionMatches.map((m) => m.replace(/^[›>\s]*/, "").trim()) : [];
|
|
1157
|
+
return {
|
|
1158
|
+
detected: true,
|
|
1159
|
+
type: "unknown",
|
|
1160
|
+
prompt: stripped.slice(-300),
|
|
1161
|
+
options: options.length > 0 ? options : void 0,
|
|
1162
|
+
canAutoRespond: false,
|
|
1163
|
+
instructions: "Menu selection prompt detected"
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
if (/press enter|hit enter|enter to (confirm|continue|proceed)|press return/i.test(stripped)) {
|
|
1167
|
+
return {
|
|
1168
|
+
detected: true,
|
|
1169
|
+
type: "unknown",
|
|
1170
|
+
prompt: stripped.slice(-200),
|
|
1171
|
+
suggestedResponse: "\n",
|
|
1172
|
+
canAutoRespond: false,
|
|
1173
|
+
instructions: "Enter/confirm prompt detected"
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
if (/trust|allow|permission|grant access/i.test(stripped) && /\?\s*$/m.test(stripped)) {
|
|
1177
|
+
return {
|
|
1178
|
+
detected: true,
|
|
1179
|
+
type: "permission",
|
|
1180
|
+
prompt: stripped.slice(-200),
|
|
1181
|
+
canAutoRespond: false,
|
|
1182
|
+
instructions: "Permission/trust prompt detected"
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
const lines = stripped.split("\n").filter((l) => l.trim());
|
|
1186
|
+
const lastLine = lines[lines.length - 1] || "";
|
|
1187
|
+
if (/\?\s*$/.test(lastLine) && lastLine.length < 200) {
|
|
1188
|
+
return {
|
|
1189
|
+
detected: true,
|
|
1190
|
+
type: "unknown",
|
|
1191
|
+
prompt: lastLine.trim(),
|
|
1192
|
+
canAutoRespond: false,
|
|
1193
|
+
instructions: "Question prompt detected"
|
|
1023
1194
|
};
|
|
1024
1195
|
}
|
|
1025
1196
|
return { detected: false };
|
|
@@ -1300,11 +1471,13 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1300
1471
|
nodePath;
|
|
1301
1472
|
workerPath;
|
|
1302
1473
|
env;
|
|
1474
|
+
adapterModules;
|
|
1303
1475
|
constructor(options = {}) {
|
|
1304
1476
|
super();
|
|
1305
1477
|
this.nodePath = options.nodePath || "node";
|
|
1306
1478
|
this.workerPath = options.workerPath || this.findWorkerPath();
|
|
1307
1479
|
this.env = options.env || {};
|
|
1480
|
+
this.adapterModules = options.adapterModules || [];
|
|
1308
1481
|
this.readyPromise = new Promise((resolve) => {
|
|
1309
1482
|
this.readyResolve = resolve;
|
|
1310
1483
|
});
|
|
@@ -1363,6 +1536,9 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1363
1536
|
const id = event.id;
|
|
1364
1537
|
switch (eventType) {
|
|
1365
1538
|
case "worker_ready":
|
|
1539
|
+
if (this.adapterModules.length > 0) {
|
|
1540
|
+
this.sendCommand({ cmd: "registerAdapters", modules: this.adapterModules });
|
|
1541
|
+
}
|
|
1366
1542
|
this.ready = true;
|
|
1367
1543
|
this.readyResolve();
|
|
1368
1544
|
this.emit("ready");
|
|
@@ -1462,6 +1638,18 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1462
1638
|
this.resolvePending("list", sessions);
|
|
1463
1639
|
break;
|
|
1464
1640
|
}
|
|
1641
|
+
case "rules": {
|
|
1642
|
+
const serializedRules = event.rules;
|
|
1643
|
+
const rules = serializedRules.map((r) => ({
|
|
1644
|
+
pattern: new RegExp(r.pattern, r.flags || ""),
|
|
1645
|
+
type: r.type,
|
|
1646
|
+
response: r.response,
|
|
1647
|
+
description: r.description,
|
|
1648
|
+
safe: r.safe
|
|
1649
|
+
}));
|
|
1650
|
+
this.resolvePending(`getRules:${id}`, rules);
|
|
1651
|
+
break;
|
|
1652
|
+
}
|
|
1465
1653
|
case "ack": {
|
|
1466
1654
|
const cmd = event.cmd;
|
|
1467
1655
|
const success = event.success;
|
|
@@ -1599,6 +1787,74 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1599
1787
|
this.on(`data:${id}`, handler);
|
|
1600
1788
|
return () => this.off(`data:${id}`, handler);
|
|
1601
1789
|
}
|
|
1790
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1791
|
+
// Runtime Auto-Response Rules API
|
|
1792
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1793
|
+
serializeRule(rule) {
|
|
1794
|
+
return {
|
|
1795
|
+
pattern: rule.pattern.source,
|
|
1796
|
+
flags: rule.pattern.flags || void 0,
|
|
1797
|
+
type: rule.type,
|
|
1798
|
+
response: rule.response,
|
|
1799
|
+
description: rule.description,
|
|
1800
|
+
safe: rule.safe
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
/**
|
|
1804
|
+
* Add an auto-response rule to a session.
|
|
1805
|
+
* Session rules are checked before adapter rules.
|
|
1806
|
+
*/
|
|
1807
|
+
async addAutoResponseRule(sessionId, rule) {
|
|
1808
|
+
await this.waitForReady();
|
|
1809
|
+
const serialized = this.serializeRule(rule);
|
|
1810
|
+
this.sendCommand({ cmd: "addRule", id: sessionId, rule: serialized });
|
|
1811
|
+
await this.createPending(`addRule:${sessionId}`);
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Remove an auto-response rule from a session by pattern.
|
|
1815
|
+
* Returns true if a rule was removed.
|
|
1816
|
+
*/
|
|
1817
|
+
async removeAutoResponseRule(sessionId, pattern) {
|
|
1818
|
+
await this.waitForReady();
|
|
1819
|
+
this.sendCommand({
|
|
1820
|
+
cmd: "removeRule",
|
|
1821
|
+
id: sessionId,
|
|
1822
|
+
pattern: pattern.source,
|
|
1823
|
+
flags: pattern.flags || void 0
|
|
1824
|
+
});
|
|
1825
|
+
try {
|
|
1826
|
+
await this.createPending(`removeRule:${sessionId}`);
|
|
1827
|
+
return true;
|
|
1828
|
+
} catch {
|
|
1829
|
+
return false;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* Set all auto-response rules for a session, replacing existing ones.
|
|
1834
|
+
*/
|
|
1835
|
+
async setAutoResponseRules(sessionId, rules) {
|
|
1836
|
+
await this.waitForReady();
|
|
1837
|
+
const serialized = rules.map((r) => this.serializeRule(r));
|
|
1838
|
+
this.sendCommand({ cmd: "setRules", id: sessionId, rules: serialized });
|
|
1839
|
+
await this.createPending(`setRules:${sessionId}`);
|
|
1840
|
+
}
|
|
1841
|
+
/**
|
|
1842
|
+
* Get all auto-response rules for a session.
|
|
1843
|
+
*/
|
|
1844
|
+
async getAutoResponseRules(sessionId) {
|
|
1845
|
+
await this.waitForReady();
|
|
1846
|
+
this.sendCommand({ cmd: "getRules", id: sessionId });
|
|
1847
|
+
const rules = await this.createPending(`getRules:${sessionId}`);
|
|
1848
|
+
return rules;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Clear all auto-response rules for a session.
|
|
1852
|
+
*/
|
|
1853
|
+
async clearAutoResponseRules(sessionId) {
|
|
1854
|
+
await this.waitForReady();
|
|
1855
|
+
this.sendCommand({ cmd: "clearRules", id: sessionId });
|
|
1856
|
+
await this.createPending(`clearRules:${sessionId}`);
|
|
1857
|
+
}
|
|
1602
1858
|
/**
|
|
1603
1859
|
* Shutdown the worker and all sessions
|
|
1604
1860
|
*/
|