pty-manager 1.2.5 → 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 +70 -1
- package/dist/index.d.ts +70 -1
- package/dist/index.js +258 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +258 -7
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +232 -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 };
|
|
@@ -1467,6 +1638,18 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1467
1638
|
this.resolvePending("list", sessions);
|
|
1468
1639
|
break;
|
|
1469
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
|
+
}
|
|
1470
1653
|
case "ack": {
|
|
1471
1654
|
const cmd = event.cmd;
|
|
1472
1655
|
const success = event.success;
|
|
@@ -1604,6 +1787,74 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1604
1787
|
this.on(`data:${id}`, handler);
|
|
1605
1788
|
return () => this.off(`data:${id}`, handler);
|
|
1606
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
|
+
}
|
|
1607
1858
|
/**
|
|
1608
1859
|
* Shutdown the worker and all sessions
|
|
1609
1860
|
*/
|