pty-manager 1.2.5 → 1.2.8

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 CHANGED
@@ -379,6 +379,7 @@ declare class PTYSession extends EventEmitter {
379
379
  private _lastActivityAt;
380
380
  private messageCounter;
381
381
  private logger;
382
+ private sessionRules;
382
383
  readonly id: string;
383
384
  readonly config: SpawnConfig;
384
385
  constructor(adapter: CLIAdapter, config: SpawnConfig, logger?: Logger);
@@ -386,6 +387,28 @@ declare class PTYSession extends EventEmitter {
386
387
  get pid(): number | undefined;
387
388
  get startedAt(): Date | undefined;
388
389
  get lastActivityAt(): Date | undefined;
390
+ /**
391
+ * Add an auto-response rule to this session.
392
+ * Session rules are checked before adapter rules.
393
+ */
394
+ addAutoResponseRule(rule: AutoResponseRule): void;
395
+ /**
396
+ * Remove an auto-response rule by pattern.
397
+ * Returns true if a rule was removed.
398
+ */
399
+ removeAutoResponseRule(pattern: RegExp): boolean;
400
+ /**
401
+ * Set all session auto-response rules, replacing existing ones.
402
+ */
403
+ setAutoResponseRules(rules: AutoResponseRule[]): void;
404
+ /**
405
+ * Get all session auto-response rules.
406
+ */
407
+ getAutoResponseRules(): AutoResponseRule[];
408
+ /**
409
+ * Clear all session auto-response rules.
410
+ */
411
+ clearAutoResponseRules(): void;
389
412
  /**
390
413
  * Start the PTY session
391
414
  */
@@ -399,7 +422,8 @@ declare class PTYSession extends EventEmitter {
399
422
  */
400
423
  private detectAndHandleBlockingPrompt;
401
424
  /**
402
- * Try to match and apply auto-response rules
425
+ * Try to match and apply auto-response rules.
426
+ * Session rules are checked first, then adapter rules.
403
427
  */
404
428
  private tryAutoResponse;
405
429
  /**
@@ -550,6 +574,28 @@ declare class PTYManager extends EventEmitter {
550
574
  * Get the underlying PTYSession (for advanced use)
551
575
  */
552
576
  getSession(sessionId: string): PTYSession | undefined;
577
+ /**
578
+ * Add an auto-response rule to a session.
579
+ * Session rules are checked before adapter rules.
580
+ */
581
+ addAutoResponseRule(sessionId: string, rule: AutoResponseRule): void;
582
+ /**
583
+ * Remove an auto-response rule from a session by pattern.
584
+ * Returns true if a rule was removed.
585
+ */
586
+ removeAutoResponseRule(sessionId: string, pattern: RegExp): boolean;
587
+ /**
588
+ * Set all auto-response rules for a session, replacing existing ones.
589
+ */
590
+ setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): void;
591
+ /**
592
+ * Get all auto-response rules for a session.
593
+ */
594
+ getAutoResponseRules(sessionId: string): AutoResponseRule[];
595
+ /**
596
+ * Clear all auto-response rules for a session.
597
+ */
598
+ clearAutoResponseRules(sessionId: string): void;
553
599
  }
554
600
 
555
601
  /**
@@ -775,6 +821,29 @@ declare class BunCompatiblePTYManager extends EventEmitter {
775
821
  * Subscribe to output from a specific session
776
822
  */
777
823
  onSessionData(id: string, callback: (data: string) => void): () => void;
824
+ private serializeRule;
825
+ /**
826
+ * Add an auto-response rule to a session.
827
+ * Session rules are checked before adapter rules.
828
+ */
829
+ addAutoResponseRule(sessionId: string, rule: AutoResponseRule): Promise<void>;
830
+ /**
831
+ * Remove an auto-response rule from a session by pattern.
832
+ * Returns true if a rule was removed.
833
+ */
834
+ removeAutoResponseRule(sessionId: string, pattern: RegExp): Promise<boolean>;
835
+ /**
836
+ * Set all auto-response rules for a session, replacing existing ones.
837
+ */
838
+ setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): Promise<void>;
839
+ /**
840
+ * Get all auto-response rules for a session.
841
+ */
842
+ getAutoResponseRules(sessionId: string): Promise<AutoResponseRule[]>;
843
+ /**
844
+ * Clear all auto-response rules for a session.
845
+ */
846
+ clearAutoResponseRules(sessionId: string): Promise<void>;
778
847
  /**
779
848
  * Shutdown the worker and all sessions
780
849
  */
package/dist/index.d.ts CHANGED
@@ -379,6 +379,7 @@ declare class PTYSession extends EventEmitter {
379
379
  private _lastActivityAt;
380
380
  private messageCounter;
381
381
  private logger;
382
+ private sessionRules;
382
383
  readonly id: string;
383
384
  readonly config: SpawnConfig;
384
385
  constructor(adapter: CLIAdapter, config: SpawnConfig, logger?: Logger);
@@ -386,6 +387,28 @@ declare class PTYSession extends EventEmitter {
386
387
  get pid(): number | undefined;
387
388
  get startedAt(): Date | undefined;
388
389
  get lastActivityAt(): Date | undefined;
390
+ /**
391
+ * Add an auto-response rule to this session.
392
+ * Session rules are checked before adapter rules.
393
+ */
394
+ addAutoResponseRule(rule: AutoResponseRule): void;
395
+ /**
396
+ * Remove an auto-response rule by pattern.
397
+ * Returns true if a rule was removed.
398
+ */
399
+ removeAutoResponseRule(pattern: RegExp): boolean;
400
+ /**
401
+ * Set all session auto-response rules, replacing existing ones.
402
+ */
403
+ setAutoResponseRules(rules: AutoResponseRule[]): void;
404
+ /**
405
+ * Get all session auto-response rules.
406
+ */
407
+ getAutoResponseRules(): AutoResponseRule[];
408
+ /**
409
+ * Clear all session auto-response rules.
410
+ */
411
+ clearAutoResponseRules(): void;
389
412
  /**
390
413
  * Start the PTY session
391
414
  */
@@ -399,7 +422,8 @@ declare class PTYSession extends EventEmitter {
399
422
  */
400
423
  private detectAndHandleBlockingPrompt;
401
424
  /**
402
- * Try to match and apply auto-response rules
425
+ * Try to match and apply auto-response rules.
426
+ * Session rules are checked first, then adapter rules.
403
427
  */
404
428
  private tryAutoResponse;
405
429
  /**
@@ -550,6 +574,28 @@ declare class PTYManager extends EventEmitter {
550
574
  * Get the underlying PTYSession (for advanced use)
551
575
  */
552
576
  getSession(sessionId: string): PTYSession | undefined;
577
+ /**
578
+ * Add an auto-response rule to a session.
579
+ * Session rules are checked before adapter rules.
580
+ */
581
+ addAutoResponseRule(sessionId: string, rule: AutoResponseRule): void;
582
+ /**
583
+ * Remove an auto-response rule from a session by pattern.
584
+ * Returns true if a rule was removed.
585
+ */
586
+ removeAutoResponseRule(sessionId: string, pattern: RegExp): boolean;
587
+ /**
588
+ * Set all auto-response rules for a session, replacing existing ones.
589
+ */
590
+ setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): void;
591
+ /**
592
+ * Get all auto-response rules for a session.
593
+ */
594
+ getAutoResponseRules(sessionId: string): AutoResponseRule[];
595
+ /**
596
+ * Clear all auto-response rules for a session.
597
+ */
598
+ clearAutoResponseRules(sessionId: string): void;
553
599
  }
554
600
 
555
601
  /**
@@ -775,6 +821,29 @@ declare class BunCompatiblePTYManager extends EventEmitter {
775
821
  * Subscribe to output from a specific session
776
822
  */
777
823
  onSessionData(id: string, callback: (data: string) => void): () => void;
824
+ private serializeRule;
825
+ /**
826
+ * Add an auto-response rule to a session.
827
+ * Session rules are checked before adapter rules.
828
+ */
829
+ addAutoResponseRule(sessionId: string, rule: AutoResponseRule): Promise<void>;
830
+ /**
831
+ * Remove an auto-response rule from a session by pattern.
832
+ * Returns true if a rule was removed.
833
+ */
834
+ removeAutoResponseRule(sessionId: string, pattern: RegExp): Promise<boolean>;
835
+ /**
836
+ * Set all auto-response rules for a session, replacing existing ones.
837
+ */
838
+ setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): Promise<void>;
839
+ /**
840
+ * Get all auto-response rules for a session.
841
+ */
842
+ getAutoResponseRules(sessionId: string): Promise<AutoResponseRule[]>;
843
+ /**
844
+ * Clear all auto-response rules for a session.
845
+ */
846
+ clearAutoResponseRules(sessionId: string): Promise<void>;
778
847
  /**
779
848
  * Shutdown the worker and all sessions
780
849
  */
package/dist/index.js CHANGED
@@ -321,6 +321,7 @@ var PTYSession = class extends import_events.EventEmitter {
321
321
  _lastActivityAt = null;
322
322
  messageCounter = 0;
323
323
  logger;
324
+ sessionRules = [];
324
325
  id;
325
326
  config;
326
327
  get status() {
@@ -335,6 +336,75 @@ var PTYSession = class extends import_events.EventEmitter {
335
336
  get lastActivityAt() {
336
337
  return this._lastActivityAt ?? void 0;
337
338
  }
339
+ // ─────────────────────────────────────────────────────────────────────────────
340
+ // Runtime Auto-Response Rules API
341
+ // ─────────────────────────────────────────────────────────────────────────────
342
+ /**
343
+ * Add an auto-response rule to this session.
344
+ * Session rules are checked before adapter rules.
345
+ */
346
+ addAutoResponseRule(rule) {
347
+ const existingIndex = this.sessionRules.findIndex(
348
+ (r) => r.pattern.source === rule.pattern.source && r.pattern.flags === rule.pattern.flags
349
+ );
350
+ if (existingIndex >= 0) {
351
+ this.sessionRules[existingIndex] = rule;
352
+ this.logger.debug(
353
+ { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
354
+ "Replaced existing auto-response rule"
355
+ );
356
+ } else {
357
+ this.sessionRules.push(rule);
358
+ this.logger.debug(
359
+ { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },
360
+ "Added auto-response rule"
361
+ );
362
+ }
363
+ }
364
+ /**
365
+ * Remove an auto-response rule by pattern.
366
+ * Returns true if a rule was removed.
367
+ */
368
+ removeAutoResponseRule(pattern) {
369
+ const initialLength = this.sessionRules.length;
370
+ this.sessionRules = this.sessionRules.filter(
371
+ (r) => !(r.pattern.source === pattern.source && r.pattern.flags === pattern.flags)
372
+ );
373
+ const removed = this.sessionRules.length < initialLength;
374
+ if (removed) {
375
+ this.logger.debug(
376
+ { sessionId: this.id, pattern: pattern.source },
377
+ "Removed auto-response rule"
378
+ );
379
+ }
380
+ return removed;
381
+ }
382
+ /**
383
+ * Set all session auto-response rules, replacing existing ones.
384
+ */
385
+ setAutoResponseRules(rules) {
386
+ this.sessionRules = [...rules];
387
+ this.logger.debug(
388
+ { sessionId: this.id, count: rules.length },
389
+ "Set auto-response rules"
390
+ );
391
+ }
392
+ /**
393
+ * Get all session auto-response rules.
394
+ */
395
+ getAutoResponseRules() {
396
+ return [...this.sessionRules];
397
+ }
398
+ /**
399
+ * Clear all session auto-response rules.
400
+ */
401
+ clearAutoResponseRules() {
402
+ this.sessionRules = [];
403
+ this.logger.debug({ sessionId: this.id }, "Cleared auto-response rules");
404
+ }
405
+ // ─────────────────────────────────────────────────────────────────────────────
406
+ // Lifecycle
407
+ // ─────────────────────────────────────────────────────────────────────────────
338
408
  /**
339
409
  * Start the PTY session
340
410
  */
@@ -415,7 +485,9 @@ var PTYSession = class extends import_events.EventEmitter {
415
485
  this._status = "stopped";
416
486
  this.emit("exit", exitDetection.code || 0);
417
487
  }
418
- this.tryParseOutput();
488
+ if (this._status !== "starting" && this._status !== "authenticating") {
489
+ this.tryParseOutput();
490
+ }
419
491
  });
420
492
  this.ptyProcess.onExit(({ exitCode, signal }) => {
421
493
  this._status = "stopped";
@@ -476,23 +548,27 @@ var PTYSession = class extends import_events.EventEmitter {
476
548
  return false;
477
549
  }
478
550
  /**
479
- * Try to match and apply auto-response rules
551
+ * Try to match and apply auto-response rules.
552
+ * Session rules are checked first, then adapter rules.
480
553
  */
481
554
  tryAutoResponse() {
482
- const rules = this.adapter.autoResponseRules;
483
- if (!rules || rules.length === 0) {
555
+ const adapterRules = this.adapter.autoResponseRules || [];
556
+ const allRules = [...this.sessionRules, ...adapterRules];
557
+ if (allRules.length === 0) {
484
558
  return false;
485
559
  }
486
- for (const rule of rules) {
560
+ for (const rule of allRules) {
487
561
  if (rule.pattern.test(this.outputBuffer)) {
488
562
  const safe = rule.safe !== false;
563
+ const isSessionRule = this.sessionRules.includes(rule);
489
564
  if (safe) {
490
565
  this.logger.info(
491
566
  {
492
567
  sessionId: this.id,
493
568
  promptType: rule.type,
494
569
  description: rule.description,
495
- response: rule.response
570
+ response: rule.response,
571
+ source: isSessionRule ? "session" : "adapter"
496
572
  },
497
573
  "Applying auto-response rule"
498
574
  );
@@ -963,6 +1039,61 @@ var PTYManager = class extends import_events2.EventEmitter {
963
1039
  getSession(sessionId) {
964
1040
  return this.sessions.get(sessionId);
965
1041
  }
1042
+ // ─────────────────────────────────────────────────────────────────────────────
1043
+ // Runtime Auto-Response Rules API
1044
+ // ─────────────────────────────────────────────────────────────────────────────
1045
+ /**
1046
+ * Add an auto-response rule to a session.
1047
+ * Session rules are checked before adapter rules.
1048
+ */
1049
+ addAutoResponseRule(sessionId, rule) {
1050
+ const session = this.sessions.get(sessionId);
1051
+ if (!session) {
1052
+ throw new Error(`Session not found: ${sessionId}`);
1053
+ }
1054
+ session.addAutoResponseRule(rule);
1055
+ }
1056
+ /**
1057
+ * Remove an auto-response rule from a session by pattern.
1058
+ * Returns true if a rule was removed.
1059
+ */
1060
+ removeAutoResponseRule(sessionId, pattern) {
1061
+ const session = this.sessions.get(sessionId);
1062
+ if (!session) {
1063
+ throw new Error(`Session not found: ${sessionId}`);
1064
+ }
1065
+ return session.removeAutoResponseRule(pattern);
1066
+ }
1067
+ /**
1068
+ * Set all auto-response rules for a session, replacing existing ones.
1069
+ */
1070
+ setAutoResponseRules(sessionId, rules) {
1071
+ const session = this.sessions.get(sessionId);
1072
+ if (!session) {
1073
+ throw new Error(`Session not found: ${sessionId}`);
1074
+ }
1075
+ session.setAutoResponseRules(rules);
1076
+ }
1077
+ /**
1078
+ * Get all auto-response rules for a session.
1079
+ */
1080
+ getAutoResponseRules(sessionId) {
1081
+ const session = this.sessions.get(sessionId);
1082
+ if (!session) {
1083
+ throw new Error(`Session not found: ${sessionId}`);
1084
+ }
1085
+ return session.getAutoResponseRules();
1086
+ }
1087
+ /**
1088
+ * Clear all auto-response rules for a session.
1089
+ */
1090
+ clearAutoResponseRules(sessionId) {
1091
+ const session = this.sessions.get(sessionId);
1092
+ if (!session) {
1093
+ throw new Error(`Session not found: ${sessionId}`);
1094
+ }
1095
+ session.clearAutoResponseRules();
1096
+ }
966
1097
  };
967
1098
 
968
1099
  // src/adapters/base-adapter.ts
@@ -1049,7 +1180,7 @@ var BaseCLIAdapter = class {
1049
1180
  instructions: "Please select a project or workspace"
1050
1181
  };
1051
1182
  }
1052
- if (/\[y\/n\]|\(y\/n\)|\[Y\/n\]|\[y\/N\]/i.test(stripped) && stripped.includes("?")) {
1183
+ if (/\[y\/n\]|\(y\/n\)|\[Y\/n\]|\[y\/N\]|\(Y\)es\/\(N\)o|Yes\/No\??/i.test(stripped)) {
1053
1184
  return {
1054
1185
  detected: true,
1055
1186
  type: "unknown",
@@ -1057,7 +1188,49 @@ var BaseCLIAdapter = class {
1057
1188
  // Last 200 chars for context
1058
1189
  options: ["y", "n"],
1059
1190
  canAutoRespond: false,
1060
- instructions: "Unknown confirmation prompt detected"
1191
+ instructions: "Confirmation prompt detected"
1192
+ };
1193
+ }
1194
+ if (/^\s*[›>]?\s*[1-9]\.\s+\w+/m.test(stripped) && /\?\s*$/m.test(stripped)) {
1195
+ const optionMatches = stripped.match(/[›>]?\s*([1-9])\.\s+([^\n]+)/g);
1196
+ const options = optionMatches ? optionMatches.map((m) => m.replace(/^[›>\s]*/, "").trim()) : [];
1197
+ return {
1198
+ detected: true,
1199
+ type: "unknown",
1200
+ prompt: stripped.slice(-300),
1201
+ options: options.length > 0 ? options : void 0,
1202
+ canAutoRespond: false,
1203
+ instructions: "Menu selection prompt detected"
1204
+ };
1205
+ }
1206
+ if (/press enter|hit enter|enter to (confirm|continue|proceed)|press return/i.test(stripped)) {
1207
+ return {
1208
+ detected: true,
1209
+ type: "unknown",
1210
+ prompt: stripped.slice(-200),
1211
+ suggestedResponse: "\n",
1212
+ canAutoRespond: false,
1213
+ instructions: "Enter/confirm prompt detected"
1214
+ };
1215
+ }
1216
+ if (/trust|allow|permission|grant access/i.test(stripped) && /\?\s*$/m.test(stripped)) {
1217
+ return {
1218
+ detected: true,
1219
+ type: "permission",
1220
+ prompt: stripped.slice(-200),
1221
+ canAutoRespond: false,
1222
+ instructions: "Permission/trust prompt detected"
1223
+ };
1224
+ }
1225
+ const lines = stripped.split("\n").filter((l) => l.trim());
1226
+ const lastLine = lines[lines.length - 1] || "";
1227
+ if (/\?\s*$/.test(lastLine) && lastLine.length < 200) {
1228
+ return {
1229
+ detected: true,
1230
+ type: "unknown",
1231
+ prompt: lastLine.trim(),
1232
+ canAutoRespond: false,
1233
+ instructions: "Question prompt detected"
1061
1234
  };
1062
1235
  }
1063
1236
  return { detected: false };
@@ -1505,6 +1678,18 @@ var BunCompatiblePTYManager = class extends import_events3.EventEmitter {
1505
1678
  this.resolvePending("list", sessions);
1506
1679
  break;
1507
1680
  }
1681
+ case "rules": {
1682
+ const serializedRules = event.rules;
1683
+ const rules = serializedRules.map((r) => ({
1684
+ pattern: new RegExp(r.pattern, r.flags || ""),
1685
+ type: r.type,
1686
+ response: r.response,
1687
+ description: r.description,
1688
+ safe: r.safe
1689
+ }));
1690
+ this.resolvePending(`getRules:${id}`, rules);
1691
+ break;
1692
+ }
1508
1693
  case "ack": {
1509
1694
  const cmd = event.cmd;
1510
1695
  const success = event.success;
@@ -1642,6 +1827,74 @@ var BunCompatiblePTYManager = class extends import_events3.EventEmitter {
1642
1827
  this.on(`data:${id}`, handler);
1643
1828
  return () => this.off(`data:${id}`, handler);
1644
1829
  }
1830
+ // ─────────────────────────────────────────────────────────────────────────────
1831
+ // Runtime Auto-Response Rules API
1832
+ // ─────────────────────────────────────────────────────────────────────────────
1833
+ serializeRule(rule) {
1834
+ return {
1835
+ pattern: rule.pattern.source,
1836
+ flags: rule.pattern.flags || void 0,
1837
+ type: rule.type,
1838
+ response: rule.response,
1839
+ description: rule.description,
1840
+ safe: rule.safe
1841
+ };
1842
+ }
1843
+ /**
1844
+ * Add an auto-response rule to a session.
1845
+ * Session rules are checked before adapter rules.
1846
+ */
1847
+ async addAutoResponseRule(sessionId, rule) {
1848
+ await this.waitForReady();
1849
+ const serialized = this.serializeRule(rule);
1850
+ this.sendCommand({ cmd: "addRule", id: sessionId, rule: serialized });
1851
+ await this.createPending(`addRule:${sessionId}`);
1852
+ }
1853
+ /**
1854
+ * Remove an auto-response rule from a session by pattern.
1855
+ * Returns true if a rule was removed.
1856
+ */
1857
+ async removeAutoResponseRule(sessionId, pattern) {
1858
+ await this.waitForReady();
1859
+ this.sendCommand({
1860
+ cmd: "removeRule",
1861
+ id: sessionId,
1862
+ pattern: pattern.source,
1863
+ flags: pattern.flags || void 0
1864
+ });
1865
+ try {
1866
+ await this.createPending(`removeRule:${sessionId}`);
1867
+ return true;
1868
+ } catch {
1869
+ return false;
1870
+ }
1871
+ }
1872
+ /**
1873
+ * Set all auto-response rules for a session, replacing existing ones.
1874
+ */
1875
+ async setAutoResponseRules(sessionId, rules) {
1876
+ await this.waitForReady();
1877
+ const serialized = rules.map((r) => this.serializeRule(r));
1878
+ this.sendCommand({ cmd: "setRules", id: sessionId, rules: serialized });
1879
+ await this.createPending(`setRules:${sessionId}`);
1880
+ }
1881
+ /**
1882
+ * Get all auto-response rules for a session.
1883
+ */
1884
+ async getAutoResponseRules(sessionId) {
1885
+ await this.waitForReady();
1886
+ this.sendCommand({ cmd: "getRules", id: sessionId });
1887
+ const rules = await this.createPending(`getRules:${sessionId}`);
1888
+ return rules;
1889
+ }
1890
+ /**
1891
+ * Clear all auto-response rules for a session.
1892
+ */
1893
+ async clearAutoResponseRules(sessionId) {
1894
+ await this.waitForReady();
1895
+ this.sendCommand({ cmd: "clearRules", id: sessionId });
1896
+ await this.createPending(`clearRules:${sessionId}`);
1897
+ }
1645
1898
  /**
1646
1899
  * Shutdown the worker and all sessions
1647
1900
  */