@threadbase-sh/streamer 1.70.1 → 1.70.2
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/api/handlers/sessions.handlers.d.ts.map +1 -1
- package/dist/cli.cjs +77 -10
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +77 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +77 -10
- package/dist/index.js.map +1 -1
- package/dist/services/prompts/promptRegistry.d.ts +33 -0
- package/dist/services/prompts/promptRegistry.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9877,6 +9877,58 @@ var PromptRegistry = class {
|
|
|
9877
9877
|
this.publish(entry);
|
|
9878
9878
|
return copyPrompt(entry.prompt);
|
|
9879
9879
|
}
|
|
9880
|
+
/**
|
|
9881
|
+
* The provider's prompt left the screen.
|
|
9882
|
+
*
|
|
9883
|
+
* Distinct from `transition` because the detector cannot tell a teardown it
|
|
9884
|
+
* observed on its own from one OUR OWN write caused. On a screen-scraped gate
|
|
9885
|
+
* the answer keys remove the box, and pty-manager's sendKeys fires the close
|
|
9886
|
+
* synchronously from inside the write — so the close always arrives before
|
|
9887
|
+
* the answer that caused it has settled, and reporting it as a cancel failed
|
|
9888
|
+
* every answer whose bytes had already landed (#720).
|
|
9889
|
+
*
|
|
9890
|
+
* While an answer is writing, the close is deferred and the answer decides:
|
|
9891
|
+
* `resolved` if the write landed, the deferred close if it did not. Success
|
|
9892
|
+
* is the adapter's own result, never the prompt's absence from the screen —
|
|
9893
|
+
* a prompt that does not vanish when answered (a multi-select form) simply
|
|
9894
|
+
* never reaches here, and is settled by the same adapter result (#721).
|
|
9895
|
+
*
|
|
9896
|
+
* ONLY this path defers. `replaced` from a different gate taking the screen,
|
|
9897
|
+
* `unavailable` from invalidateSession and `expired` all still go through
|
|
9898
|
+
* `transition` and still win, because none of them was caused by our write.
|
|
9899
|
+
*/
|
|
9900
|
+
providerClosed(promptId, reason) {
|
|
9901
|
+
const entry = this.byId.get(promptId);
|
|
9902
|
+
if (!entry) return null;
|
|
9903
|
+
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") return null;
|
|
9904
|
+
if (entry.answering) {
|
|
9905
|
+
entry.deferredClose = reason;
|
|
9906
|
+
return null;
|
|
9907
|
+
}
|
|
9908
|
+
return this.transition(promptId, "cancelled", reason);
|
|
9909
|
+
}
|
|
9910
|
+
/**
|
|
9911
|
+
* Run a provider write that may close the prompt as a side effect, so the
|
|
9912
|
+
* close it causes is deferred rather than applied. For callers outside this
|
|
9913
|
+
* class that write without going through `answer()` — the legacy permission
|
|
9914
|
+
* route. `performAnswer` manages the same two fields directly, because it
|
|
9915
|
+
* needs the deferred value in its own control flow.
|
|
9916
|
+
*
|
|
9917
|
+
* The write's own failure needs no unwinding here: pty-manager fires the
|
|
9918
|
+
* close as the last statement of a successful sendKeys, so a throw means no
|
|
9919
|
+
* close was ever deferred and the record is still open for the caller.
|
|
9920
|
+
*/
|
|
9921
|
+
whileAnswering(promptId, write) {
|
|
9922
|
+
const entry = this.byId.get(promptId);
|
|
9923
|
+
if (!entry) return write();
|
|
9924
|
+
entry.answering = true;
|
|
9925
|
+
try {
|
|
9926
|
+
return write();
|
|
9927
|
+
} finally {
|
|
9928
|
+
entry.answering = false;
|
|
9929
|
+
entry.deferredClose = void 0;
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9880
9932
|
invalidateSession(sessionId, reason = "session_ended") {
|
|
9881
9933
|
const transitioned = [];
|
|
9882
9934
|
for (const entry of this.bySession.get(sessionId)?.values() ?? []) {
|
|
@@ -9954,21 +10006,33 @@ var PromptRegistry = class {
|
|
|
9954
10006
|
const responseError = this.validateResponses(prompt, answer);
|
|
9955
10007
|
if (responseError) return { ok: false, code: responseError };
|
|
9956
10008
|
if (!entry.adapter) return { ok: false, code: "prompt_unavailable" };
|
|
10009
|
+
entry.answering = true;
|
|
9957
10010
|
let adapterResult;
|
|
10011
|
+
let threw = false;
|
|
9958
10012
|
try {
|
|
9959
10013
|
adapterResult = await entry.adapter({ prompt: copyPrompt(prompt), answer });
|
|
9960
10014
|
} catch {
|
|
9961
|
-
|
|
10015
|
+
threw = true;
|
|
10016
|
+
adapterResult = { ok: false, code: "provider_error" };
|
|
10017
|
+
} finally {
|
|
10018
|
+
entry.answering = false;
|
|
9962
10019
|
}
|
|
10020
|
+
const deferred = entry.deferredClose;
|
|
10021
|
+
entry.deferredClose = void 0;
|
|
10022
|
+
const settle = (outcome) => {
|
|
10023
|
+
if (deferred) this.providerClosed(prompt.promptId, deferred);
|
|
10024
|
+
return outcome;
|
|
10025
|
+
};
|
|
10026
|
+
if (threw) return settle({ ok: false, code: "provider_error" });
|
|
9963
10027
|
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") {
|
|
9964
|
-
return { ok: false, code: terminalError(entry.prompt.state) };
|
|
10028
|
+
return settle({ ok: false, code: terminalError(entry.prompt.state) });
|
|
9965
10029
|
}
|
|
9966
10030
|
if (entry.prompt.revision !== answer.revision) {
|
|
9967
|
-
return {
|
|
10031
|
+
return settle({
|
|
9968
10032
|
ok: false,
|
|
9969
10033
|
code: "prompt_revision_mismatch",
|
|
9970
10034
|
currentRevision: entry.prompt.revision
|
|
9971
|
-
};
|
|
10035
|
+
});
|
|
9972
10036
|
}
|
|
9973
10037
|
if (!adapterResult.ok) {
|
|
9974
10038
|
if (adapterResult.terminal) {
|
|
@@ -9978,7 +10042,7 @@ var PromptRegistry = class {
|
|
|
9978
10042
|
adapterResult.terminal.reason
|
|
9979
10043
|
);
|
|
9980
10044
|
}
|
|
9981
|
-
return { ok: false, code: adapterResult.code };
|
|
10045
|
+
return settle({ ok: false, code: adapterResult.code });
|
|
9982
10046
|
}
|
|
9983
10047
|
return { ok: true, prompt: this.transition(prompt.promptId, "resolved", "answered") };
|
|
9984
10048
|
}
|
|
@@ -11189,10 +11253,7 @@ var SessionHandlers = class {
|
|
|
11189
11253
|
if (gate === null) {
|
|
11190
11254
|
const prior2 = this.pendingPermission.get(sessionId);
|
|
11191
11255
|
if (!prior2) return;
|
|
11192
|
-
|
|
11193
|
-
if (prompt2?.state === "open" || prompt2?.state === "updated") {
|
|
11194
|
-
this.promptRegistry.transition(prompt2.promptId, "cancelled", "provider_closed");
|
|
11195
|
-
}
|
|
11256
|
+
if (prior2.promptId) this.promptRegistry.providerClosed(prior2.promptId, "provider_closed");
|
|
11196
11257
|
this.pendingPermission.delete(sessionId);
|
|
11197
11258
|
this.pendingPermissionKey.delete(sessionId);
|
|
11198
11259
|
this.broadcastToSession(sessionId, { type: "permission_cancelled", sessionId });
|
|
@@ -11417,7 +11478,13 @@ var SessionHandlers = class {
|
|
|
11417
11478
|
return;
|
|
11418
11479
|
}
|
|
11419
11480
|
try {
|
|
11420
|
-
this.
|
|
11481
|
+
this.promptRegistry.whileAnswering(
|
|
11482
|
+
gate.promptId ?? "",
|
|
11483
|
+
() => this.ptyManager.sendKeys(
|
|
11484
|
+
sessionId,
|
|
11485
|
+
option.answerKeys ?? permissionAnswerKeys(option.index)
|
|
11486
|
+
)
|
|
11487
|
+
);
|
|
11421
11488
|
} catch (err) {
|
|
11422
11489
|
const message = err instanceof Error ? err.message : "Failed to send answer";
|
|
11423
11490
|
json(res, 400, { ok: false, reason: message });
|