@orkestrel/terminal 0.0.4 → 0.0.6
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/src/core/index.cjs +133 -119
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +23 -20
- package/dist/src/core/index.d.ts +23 -20
- package/dist/src/core/index.js +133 -119
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +56 -44
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +9 -9
- package/dist/src/server/index.d.ts +9 -9
- package/dist/src/server/index.js +56 -44
- package/dist/src/server/index.js.map +1 -1
- package/package.json +21 -18
package/dist/src/core/index.js
CHANGED
|
@@ -228,7 +228,7 @@ var TerminalError = class extends Error {
|
|
|
228
228
|
super(message);
|
|
229
229
|
this.name = "TerminalError";
|
|
230
230
|
this.code = code;
|
|
231
|
-
this.context = context;
|
|
231
|
+
if (context !== void 0) this.context = context;
|
|
232
232
|
}
|
|
233
233
|
};
|
|
234
234
|
/**
|
|
@@ -250,6 +250,33 @@ function isTerminalError(value) {
|
|
|
250
250
|
return value instanceof TerminalError;
|
|
251
251
|
}
|
|
252
252
|
//#endregion
|
|
253
|
+
//#region src/core/validators.ts
|
|
254
|
+
/** Narrow an unknown value to a {@link PromptType} — one of the six prompt forms. */
|
|
255
|
+
var isPromptType = literalOf("input", "password", "confirm", "select", "checkbox", "editor");
|
|
256
|
+
/** Narrow an unknown value to a {@link PendingPromptStatus}. */
|
|
257
|
+
var isPendingPromptStatus = literalOf("pending", "answered", "expired");
|
|
258
|
+
/**
|
|
259
|
+
* Narrow an unknown wire value to a {@link PendingPrompt} before dispatching it.
|
|
260
|
+
*
|
|
261
|
+
* @param value - The decoded wire value to inspect
|
|
262
|
+
* @returns Whether `value` is a complete pending-prompt record
|
|
263
|
+
*/
|
|
264
|
+
var isPendingPrompt = recordOf({
|
|
265
|
+
id: isNonEmptyString,
|
|
266
|
+
form: isPromptType,
|
|
267
|
+
message: isString,
|
|
268
|
+
options: isRecord,
|
|
269
|
+
status: isPendingPromptStatus,
|
|
270
|
+
time: isNumber,
|
|
271
|
+
from: isString,
|
|
272
|
+
to: isString
|
|
273
|
+
}, ["from", "to"]);
|
|
274
|
+
/** Narrow an unknown value to a {@link TerminalSnapshot}. */
|
|
275
|
+
var isTerminalSnapshot = recordOf({
|
|
276
|
+
id: isNonEmptyString,
|
|
277
|
+
timeout: isNumber
|
|
278
|
+
}, ["timeout"]);
|
|
279
|
+
//#endregion
|
|
253
280
|
//#region src/core/helpers.ts
|
|
254
281
|
/**
|
|
255
282
|
* Decode one keypress's bytes into a {@link KeyEvent} — total, never throws. A `Uint8Array` is
|
|
@@ -513,6 +540,7 @@ function inputReduce(state, key) {
|
|
|
513
540
|
view: inputView(state),
|
|
514
541
|
status: "cancel"
|
|
515
542
|
};
|
|
543
|
+
const { error: _error, ...clear } = state;
|
|
516
544
|
if (key.name === "return") {
|
|
517
545
|
const answer = state.value.length > 0 ? state.value : state.default;
|
|
518
546
|
const result = state.validator(answer);
|
|
@@ -529,9 +557,8 @@ function inputReduce(state, key) {
|
|
|
529
557
|
}
|
|
530
558
|
return {
|
|
531
559
|
state: {
|
|
532
|
-
...
|
|
533
|
-
value: answer
|
|
534
|
-
error: void 0
|
|
560
|
+
...clear,
|
|
561
|
+
value: answer
|
|
535
562
|
},
|
|
536
563
|
view: `${submitHeader(state.styler, state.message)} ${state.styler.dim(answer)}`,
|
|
537
564
|
status: "submit",
|
|
@@ -545,9 +572,8 @@ function inputReduce(state, key) {
|
|
|
545
572
|
status: "active"
|
|
546
573
|
};
|
|
547
574
|
const next = {
|
|
548
|
-
...
|
|
549
|
-
value
|
|
550
|
-
error: void 0
|
|
575
|
+
...clear,
|
|
576
|
+
value
|
|
551
577
|
};
|
|
552
578
|
return {
|
|
553
579
|
state: next,
|
|
@@ -583,6 +609,7 @@ function passwordReduce(state, key) {
|
|
|
583
609
|
view: passwordView(state),
|
|
584
610
|
status: "cancel"
|
|
585
611
|
};
|
|
612
|
+
const { error: _error, ...clear } = state;
|
|
586
613
|
if (key.name === "return") {
|
|
587
614
|
const result = state.validator(state.value);
|
|
588
615
|
if (result !== true) {
|
|
@@ -597,10 +624,7 @@ function passwordReduce(state, key) {
|
|
|
597
624
|
};
|
|
598
625
|
}
|
|
599
626
|
return {
|
|
600
|
-
state:
|
|
601
|
-
...state,
|
|
602
|
-
error: void 0
|
|
603
|
-
},
|
|
627
|
+
state: clear,
|
|
604
628
|
view: `${submitHeader(state.styler, state.message)} ${state.styler.dim(state.mask.repeat(state.value.length))}`,
|
|
605
629
|
status: "submit",
|
|
606
630
|
value: state.value
|
|
@@ -613,9 +637,8 @@ function passwordReduce(state, key) {
|
|
|
613
637
|
status: "active"
|
|
614
638
|
};
|
|
615
639
|
const next = {
|
|
616
|
-
...
|
|
617
|
-
value
|
|
618
|
-
error: void 0
|
|
640
|
+
...clear,
|
|
641
|
+
value
|
|
619
642
|
};
|
|
620
643
|
return {
|
|
621
644
|
state: next,
|
|
@@ -752,8 +775,8 @@ function createCheckboxState(options) {
|
|
|
752
775
|
styler: options.styler ?? createStyler(),
|
|
753
776
|
focused: 0,
|
|
754
777
|
checked,
|
|
755
|
-
min: options.min,
|
|
756
|
-
max: options.max
|
|
778
|
+
...options.min !== void 0 ? { min: options.min } : {},
|
|
779
|
+
...options.max !== void 0 ? { max: options.max } : {}
|
|
757
780
|
};
|
|
758
781
|
}
|
|
759
782
|
/** Render a {@link CheckboxState} as a MULTI-LINE styled view — the header, one box per choice (focused + checked marked), a count, and any error. */
|
|
@@ -785,11 +808,11 @@ function checkboxReduce(state, key) {
|
|
|
785
808
|
status: "cancel"
|
|
786
809
|
};
|
|
787
810
|
const count = state.choices.length;
|
|
811
|
+
const { error: _error, ...clear } = state;
|
|
788
812
|
if ((key.name === "up" || key.name === "k") && count > 0) {
|
|
789
813
|
const next = {
|
|
790
|
-
...
|
|
791
|
-
focused: (state.focused - 1 + count) % count
|
|
792
|
-
error: void 0
|
|
814
|
+
...clear,
|
|
815
|
+
focused: (state.focused - 1 + count) % count
|
|
793
816
|
};
|
|
794
817
|
return {
|
|
795
818
|
state: next,
|
|
@@ -799,9 +822,8 @@ function checkboxReduce(state, key) {
|
|
|
799
822
|
}
|
|
800
823
|
if ((key.name === "down" || key.name === "j") && count > 0) {
|
|
801
824
|
const next = {
|
|
802
|
-
...
|
|
803
|
-
focused: (state.focused + 1) % count
|
|
804
|
-
error: void 0
|
|
825
|
+
...clear,
|
|
826
|
+
focused: (state.focused + 1) % count
|
|
805
827
|
};
|
|
806
828
|
return {
|
|
807
829
|
state: next,
|
|
@@ -812,9 +834,8 @@ function checkboxReduce(state, key) {
|
|
|
812
834
|
if (key.name === "space" && count > 0) {
|
|
813
835
|
const checked = toggleIndex(state.checked, state.focused);
|
|
814
836
|
const next = {
|
|
815
|
-
...
|
|
816
|
-
checked
|
|
817
|
-
error: void 0
|
|
837
|
+
...clear,
|
|
838
|
+
checked
|
|
818
839
|
};
|
|
819
840
|
return {
|
|
820
841
|
state: next,
|
|
@@ -839,10 +860,7 @@ function checkboxReduce(state, key) {
|
|
|
839
860
|
const values = ordered.map((index) => state.choices[index]?.value).filter((value) => value !== void 0);
|
|
840
861
|
const summary = ordered.map((index) => state.choices[index]?.name).filter((name) => name !== void 0).join(", ");
|
|
841
862
|
return {
|
|
842
|
-
state:
|
|
843
|
-
...state,
|
|
844
|
-
error: void 0
|
|
845
|
-
},
|
|
863
|
+
state: clear,
|
|
846
864
|
view: `${submitHeader(state.styler, state.message)} ${state.styler.dim(summary)}`,
|
|
847
865
|
status: "submit",
|
|
848
866
|
value: values
|
|
@@ -892,6 +910,7 @@ function editorReduce(state, key) {
|
|
|
892
910
|
view: editorView(state),
|
|
893
911
|
status: "cancel"
|
|
894
912
|
};
|
|
913
|
+
const { error: _error, ...clear } = state;
|
|
895
914
|
if (key.ctrl && key.name === "d") {
|
|
896
915
|
const lines = state.current.length > 0 ? [...state.lines, state.current] : state.lines;
|
|
897
916
|
const joined = lines.join("\n");
|
|
@@ -909,10 +928,7 @@ function editorReduce(state, key) {
|
|
|
909
928
|
};
|
|
910
929
|
}
|
|
911
930
|
return {
|
|
912
|
-
state:
|
|
913
|
-
...state,
|
|
914
|
-
error: void 0
|
|
915
|
-
},
|
|
931
|
+
state: clear,
|
|
916
932
|
view: `${submitHeader(state.styler, state.message)} ${state.styler.dim(`${String(lines.length)} line${lines.length === 1 ? "" : "s"}`)}`,
|
|
917
933
|
status: "submit",
|
|
918
934
|
value: answer
|
|
@@ -920,10 +936,9 @@ function editorReduce(state, key) {
|
|
|
920
936
|
}
|
|
921
937
|
if (key.name === "return") {
|
|
922
938
|
const next = {
|
|
923
|
-
...
|
|
939
|
+
...clear,
|
|
924
940
|
lines: [...state.lines, state.current],
|
|
925
|
-
current: ""
|
|
926
|
-
error: void 0
|
|
941
|
+
current: ""
|
|
927
942
|
};
|
|
928
943
|
return {
|
|
929
944
|
state: next,
|
|
@@ -938,9 +953,8 @@ function editorReduce(state, key) {
|
|
|
938
953
|
status: "active"
|
|
939
954
|
};
|
|
940
955
|
const next = {
|
|
941
|
-
...
|
|
942
|
-
current
|
|
943
|
-
error: void 0
|
|
956
|
+
...clear,
|
|
957
|
+
current
|
|
944
958
|
};
|
|
945
959
|
return {
|
|
946
960
|
state: next,
|
|
@@ -1020,24 +1034,6 @@ function serializeChoices(choices) {
|
|
|
1020
1034
|
return normalized;
|
|
1021
1035
|
});
|
|
1022
1036
|
}
|
|
1023
|
-
/** Narrow an unknown value to a {@link PromptType} — one of the six prompt forms. */
|
|
1024
|
-
var isPromptType = literalOf("input", "password", "confirm", "select", "checkbox", "editor");
|
|
1025
|
-
/** Narrow an unknown value to a {@link PendingPromptStatus}. */
|
|
1026
|
-
var isPendingPromptStatus = literalOf("pending", "answered", "expired");
|
|
1027
|
-
/**
|
|
1028
|
-
* Narrow an unknown wire value to a {@link PendingPrompt} — the §14 guard a {@link PromptClient}
|
|
1029
|
-
* applies to each decoded SSE `pending` payload before dispatching it (never an `as`).
|
|
1030
|
-
*/
|
|
1031
|
-
var isPendingPrompt = recordOf({
|
|
1032
|
-
id: isNonEmptyString,
|
|
1033
|
-
form: isPromptType,
|
|
1034
|
-
message: isString,
|
|
1035
|
-
options: isRecord,
|
|
1036
|
-
status: isPendingPromptStatus,
|
|
1037
|
-
time: isNumber,
|
|
1038
|
-
from: isString,
|
|
1039
|
-
to: isString
|
|
1040
|
-
}, ["from", "to"]);
|
|
1041
1037
|
/**
|
|
1042
1038
|
* Rebuild a wire-decoded `validate` payload into a {@link ValidationRules} bag — the inverse of
|
|
1043
1039
|
* {@link serializeValidationRules}. Keeps only the primitive rule values (`boolean` / `number` /
|
|
@@ -1103,11 +1099,10 @@ function resolveChoices(options, guard) {
|
|
|
1103
1099
|
function sanitizeChoiceLabels(choices) {
|
|
1104
1100
|
return choices.map((choice) => {
|
|
1105
1101
|
if (isString(choice)) return stripControls(choice);
|
|
1106
|
-
const description = choice.description === void 0 ? void 0 : stripControls(choice.description);
|
|
1107
1102
|
return {
|
|
1108
1103
|
...choice,
|
|
1109
1104
|
name: stripControls(choice.name),
|
|
1110
|
-
description
|
|
1105
|
+
...choice.description !== void 0 ? { description: stripControls(choice.description) } : {}
|
|
1111
1106
|
};
|
|
1112
1107
|
});
|
|
1113
1108
|
}
|
|
@@ -1131,42 +1126,49 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1131
1126
|
const value = resolveOption(options, "default", isString);
|
|
1132
1127
|
return terminal.input({
|
|
1133
1128
|
message,
|
|
1134
|
-
|
|
1135
|
-
validate
|
|
1129
|
+
...value !== void 0 ? { default: stripControls(value) } : {},
|
|
1130
|
+
...validate !== void 0 ? { validate } : {}
|
|
1136
1131
|
});
|
|
1137
1132
|
}
|
|
1138
1133
|
case "password": {
|
|
1139
1134
|
const value = resolveOption(options, "mask", isString);
|
|
1140
1135
|
return terminal.password({
|
|
1141
1136
|
message,
|
|
1142
|
-
|
|
1143
|
-
validate
|
|
1137
|
+
...value !== void 0 ? { mask: stripControls(value) } : {},
|
|
1138
|
+
...validate !== void 0 ? { validate } : {}
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
case "confirm": {
|
|
1142
|
+
const value = resolveOption(options, "default", isBoolean);
|
|
1143
|
+
return terminal.confirm({
|
|
1144
|
+
message,
|
|
1145
|
+
...value !== void 0 ? { default: value } : {}
|
|
1144
1146
|
});
|
|
1145
1147
|
}
|
|
1146
|
-
case "confirm": return terminal.confirm({
|
|
1147
|
-
message,
|
|
1148
|
-
default: resolveOption(options, "default", isBoolean)
|
|
1149
|
-
});
|
|
1150
1148
|
case "select": {
|
|
1151
1149
|
const value = resolveOption(options, "default", isString);
|
|
1152
1150
|
return terminal.select({
|
|
1153
1151
|
message,
|
|
1154
1152
|
choices: sanitizeChoiceLabels(resolveChoices(options, isPromptChoice)),
|
|
1155
|
-
|
|
1153
|
+
...value !== void 0 ? { default: stripControls(value) } : {}
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
case "checkbox": {
|
|
1157
|
+
const min = resolveOption(options, "min", isNumber);
|
|
1158
|
+
const max = resolveOption(options, "max", isNumber);
|
|
1159
|
+
return terminal.checkbox({
|
|
1160
|
+
message,
|
|
1161
|
+
choices: sanitizeChoiceLabels(resolveChoices(options, isCheckboxChoice)),
|
|
1162
|
+
...min !== void 0 ? { min } : {},
|
|
1163
|
+
...max !== void 0 ? { max } : {}
|
|
1156
1164
|
});
|
|
1157
1165
|
}
|
|
1158
|
-
case "checkbox": return terminal.checkbox({
|
|
1159
|
-
message,
|
|
1160
|
-
choices: sanitizeChoiceLabels(resolveChoices(options, isCheckboxChoice)),
|
|
1161
|
-
min: resolveOption(options, "min", isNumber),
|
|
1162
|
-
max: resolveOption(options, "max", isNumber)
|
|
1163
|
-
});
|
|
1164
1166
|
case "editor": {
|
|
1165
1167
|
const value = resolveOption(options, "default", isString);
|
|
1166
1168
|
return terminal.editor({
|
|
1167
1169
|
message,
|
|
1168
|
-
|
|
1169
|
-
validate
|
|
1170
|
+
...value !== void 0 ? { default: stripControls(value) } : {},
|
|
1171
|
+
...validate !== void 0 ? { validate } : {}
|
|
1170
1172
|
});
|
|
1171
1173
|
}
|
|
1172
1174
|
}
|
|
@@ -1261,11 +1263,6 @@ function serializeShutdown() {
|
|
|
1261
1263
|
function isAnswerPayload(value) {
|
|
1262
1264
|
return isRecord(value) && isNonEmptyString(value.id) && "value" in value;
|
|
1263
1265
|
}
|
|
1264
|
-
/** Narrow an unknown value to a {@link TerminalSnapshot} — a non-empty `id` plus an optional numeric `timeout`. */
|
|
1265
|
-
var isTerminalSnapshot = recordOf({
|
|
1266
|
-
id: isNonEmptyString,
|
|
1267
|
-
timeout: isNumber
|
|
1268
|
-
}, ["timeout"]);
|
|
1269
1266
|
//#endregion
|
|
1270
1267
|
//#region src/core/Prompt.ts
|
|
1271
1268
|
/**
|
|
@@ -1314,8 +1311,8 @@ var Prompt = class {
|
|
|
1314
1311
|
this.#timer = options?.timer ?? defaultTimer;
|
|
1315
1312
|
this.#cap = options?.cap;
|
|
1316
1313
|
this.#emitter = new Emitter({
|
|
1317
|
-
on: options
|
|
1318
|
-
error: options
|
|
1314
|
+
...options?.on !== void 0 ? { on: options.on } : {},
|
|
1315
|
+
...options?.error !== void 0 ? { error: options.error } : {}
|
|
1319
1316
|
});
|
|
1320
1317
|
}
|
|
1321
1318
|
get emitter() {
|
|
@@ -1402,23 +1399,8 @@ var Prompt = class {
|
|
|
1402
1399
|
id,
|
|
1403
1400
|
value: new Promise((resolve, reject) => {
|
|
1404
1401
|
const cancel = this.#timer(() => this.#expire(id), this.#timeout);
|
|
1405
|
-
const respond = (
|
|
1406
|
-
|
|
1407
|
-
if (accepted === void 0) return void 0;
|
|
1408
|
-
const current = this.#parked.get(id);
|
|
1409
|
-
if (current !== void 0) this.#parked.set(id, {
|
|
1410
|
-
...current,
|
|
1411
|
-
prompt: {
|
|
1412
|
-
...current.prompt,
|
|
1413
|
-
status: "answered"
|
|
1414
|
-
}
|
|
1415
|
-
});
|
|
1416
|
-
resolve(accepted);
|
|
1417
|
-
return accepted;
|
|
1418
|
-
};
|
|
1419
|
-
const expire = () => {
|
|
1420
|
-
reject(new TerminalError("EXPIRE", `prompt ${id} expired`, { id }));
|
|
1421
|
-
};
|
|
1402
|
+
const respond = this.#createRespond(id, gate, resolve);
|
|
1403
|
+
const expire = this.#createExpire(id, reject);
|
|
1422
1404
|
this.#parked.set(id, {
|
|
1423
1405
|
prompt,
|
|
1424
1406
|
respond,
|
|
@@ -1429,6 +1411,25 @@ var Prompt = class {
|
|
|
1429
1411
|
})
|
|
1430
1412
|
};
|
|
1431
1413
|
}
|
|
1414
|
+
#createRespond(id, gate, resolve) {
|
|
1415
|
+
return (answer) => {
|
|
1416
|
+
const accepted = gate(answer);
|
|
1417
|
+
if (accepted === void 0) return void 0;
|
|
1418
|
+
const current = this.#parked.get(id);
|
|
1419
|
+
if (current !== void 0) this.#parked.set(id, {
|
|
1420
|
+
...current,
|
|
1421
|
+
prompt: {
|
|
1422
|
+
...current.prompt,
|
|
1423
|
+
status: "answered"
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1426
|
+
resolve(accepted);
|
|
1427
|
+
return accepted;
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
#createExpire(id, reject) {
|
|
1431
|
+
return () => reject(new TerminalError("EXPIRE", `prompt ${id} expired`, { id }));
|
|
1432
|
+
}
|
|
1432
1433
|
#gate(form, options) {
|
|
1433
1434
|
switch (form) {
|
|
1434
1435
|
case "input":
|
|
@@ -1554,8 +1555,8 @@ var PromptClient = class {
|
|
|
1554
1555
|
this.#fetch = options.fetch ?? globalFetch;
|
|
1555
1556
|
this.#timer = options.timer ?? defaultTimer;
|
|
1556
1557
|
this.#emitter = new Emitter({
|
|
1557
|
-
on: options.on,
|
|
1558
|
-
error: options.error
|
|
1558
|
+
...options.on !== void 0 ? { on: options.on } : {},
|
|
1559
|
+
...options.error !== void 0 ? { error: options.error } : {}
|
|
1559
1560
|
});
|
|
1560
1561
|
}
|
|
1561
1562
|
get emitter() {
|
|
@@ -1679,17 +1680,18 @@ var PromptClient = class {
|
|
|
1679
1680
|
}
|
|
1680
1681
|
#wait(ms) {
|
|
1681
1682
|
return new Promise((resolve) => {
|
|
1682
|
-
const settle = ()
|
|
1683
|
-
this.#backoff = void 0;
|
|
1684
|
-
this.#wake = void 0;
|
|
1685
|
-
resolve();
|
|
1686
|
-
};
|
|
1683
|
+
const settle = this.#createSettler(resolve);
|
|
1687
1684
|
this.#wake = settle;
|
|
1688
|
-
this.#backoff = this.#timer(
|
|
1689
|
-
settle();
|
|
1690
|
-
}, ms);
|
|
1685
|
+
this.#backoff = this.#timer(settle, ms);
|
|
1691
1686
|
});
|
|
1692
1687
|
}
|
|
1688
|
+
#createSettler(resolve) {
|
|
1689
|
+
return () => {
|
|
1690
|
+
this.#backoff = void 0;
|
|
1691
|
+
this.#wake = void 0;
|
|
1692
|
+
resolve();
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1693
1695
|
};
|
|
1694
1696
|
//#endregion
|
|
1695
1697
|
//#region src/core/TerminalManager.ts
|
|
@@ -1742,8 +1744,8 @@ var TerminalManager = class {
|
|
|
1742
1744
|
this.#timer = options?.timer;
|
|
1743
1745
|
this.#cap = options?.cap;
|
|
1744
1746
|
this.#emitter = new Emitter({
|
|
1745
|
-
on: options
|
|
1746
|
-
error: options
|
|
1747
|
+
...options?.on !== void 0 ? { on: options.on } : {},
|
|
1748
|
+
...options?.error !== void 0 ? { error: options.error } : {}
|
|
1747
1749
|
});
|
|
1748
1750
|
}
|
|
1749
1751
|
get emitter() {
|
|
@@ -1771,9 +1773,9 @@ var TerminalManager = class {
|
|
|
1771
1773
|
...cap !== void 0 ? { cap } : {}
|
|
1772
1774
|
});
|
|
1773
1775
|
const listeners = {
|
|
1774
|
-
pending:
|
|
1775
|
-
answer:
|
|
1776
|
-
expire:
|
|
1776
|
+
pending: this.#createPendingListener(),
|
|
1777
|
+
answer: this.#createAnswerListener(name),
|
|
1778
|
+
expire: this.#createExpireListener(name)
|
|
1777
1779
|
};
|
|
1778
1780
|
broker.emitter.on("pending", listeners.pending);
|
|
1779
1781
|
broker.emitter.on("answer", listeners.answer);
|
|
@@ -1809,9 +1811,7 @@ var TerminalManager = class {
|
|
|
1809
1811
|
from,
|
|
1810
1812
|
to
|
|
1811
1813
|
});
|
|
1812
|
-
const clear = ()
|
|
1813
|
-
this.#edges.delete(ticket.id);
|
|
1814
|
-
};
|
|
1814
|
+
const clear = this.#createEdgeClear(ticket.id);
|
|
1815
1815
|
ticket.value.then(clear, clear);
|
|
1816
1816
|
}
|
|
1817
1817
|
return ticket.value;
|
|
@@ -1871,6 +1871,20 @@ var TerminalManager = class {
|
|
|
1871
1871
|
this.clear();
|
|
1872
1872
|
this.#emitter.destroy();
|
|
1873
1873
|
}
|
|
1874
|
+
#createPendingListener() {
|
|
1875
|
+
return (prompt) => this.#emitter.emit("pending", prompt);
|
|
1876
|
+
}
|
|
1877
|
+
#createAnswerListener(name) {
|
|
1878
|
+
return (id, value) => this.#emitter.emit("answer", name, id, value);
|
|
1879
|
+
}
|
|
1880
|
+
#createExpireListener(name) {
|
|
1881
|
+
return (id) => this.#emitter.emit("expire", name, id);
|
|
1882
|
+
}
|
|
1883
|
+
#createEdgeClear(id) {
|
|
1884
|
+
return () => {
|
|
1885
|
+
this.#edges.delete(id);
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1874
1888
|
#removeOne(name) {
|
|
1875
1889
|
const broker = this.#terminals.get(name);
|
|
1876
1890
|
if (broker === void 0) return false;
|
|
@@ -1982,7 +1996,7 @@ var MemoryTerminalStore = class {
|
|
|
1982
1996
|
* - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes
|
|
1983
1997
|
* the row `{ id: snapshot.id, snapshot }`.
|
|
1984
1998
|
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
1985
|
-
* a {@link TerminalSnapshot} ({@link import('./
|
|
1999
|
+
* a {@link TerminalSnapshot} ({@link import('./validators.js').isTerminalSnapshot} — the AGENTS §14
|
|
1986
2000
|
* boundary narrow for an untrusted storage read), or `undefined` if none is stored.
|
|
1987
2001
|
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
1988
2002
|
*
|