@michengai/dsh-btw 0.1.23 → 0.1.24
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/CHANGELOG.md +5 -0
- package/CHANGELOG.zh-CN.md +5 -0
- package/lib/client.js +91 -13
- package/lib/index.js +2 -0
- package/lib/types/client/bubbles.d.ts +8 -0
- package/lib/types/locales.d.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.24] - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- Side questions are no longer offered in a subagent session. Typing `/btw` there explains that you should return to the main session, instead of leaving a dialog that cannot be closed (#7).
|
|
6
|
+
- Closing a side question that the host rejects because the session is owned by subagent routing no longer deletes an answer that is still on the way or already returned. A request that never started, or was cancelled before it produced an answer, can still be dismissed locally.
|
|
7
|
+
|
|
3
8
|
## [0.1.23] - 2026-10-15
|
|
4
9
|
|
|
5
10
|
- Relax hardcoded timeout: Replace the strict 90s timer with a 30-minute watchdog, supporting long chain-of-thought and max-reasoning models while safeguarding concurrency slots against stalled connections (#6).
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## [0.1.24] - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- 子代理会话不再提供旁问。在那里输入 `/btw` 会提示返回主会话使用,而不是留下关不掉的弹窗 (#7)。
|
|
6
|
+
- 宿主因子代理路由拒绝关闭时,不再删掉还在返回或已经返回的答案。尚未启动,或在产生答案前被取消的请求,仍可在本地关掉。
|
|
7
|
+
|
|
3
8
|
## [0.1.23] - 2026-10-15
|
|
4
9
|
|
|
5
10
|
- 放宽硬超时限制:默认超时由写死的 90s 调整为 30 分钟兜底看门狗,支持长思维链与深度推理模型充分思考;同时保留长连接死锁自动回收机制保护并发槽位 (#6)。
|
package/lib/client.js
CHANGED
|
@@ -519,6 +519,7 @@ var zh = {
|
|
|
519
519
|
"error.attachments": "\u65C1\u95EE\u53EA\u63A5\u53D7\u6587\u5B57\uFF0C\u56FE\u7247\u548C\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u8F93\u5165\u6846\u4E2D\u3002",
|
|
520
520
|
"error.removeAttachments": "\u65C1\u95EE\u53EA\u63A5\u53D7\u6587\u5B57\uFF0C\u8BF7\u5148\u79FB\u9664\u56FE\u7247\u548C\u6587\u4EF6\u3002",
|
|
521
521
|
"error.backend": "BTW \u540E\u7AEF\u5C1A\u672A\u542F\u7528\uFF0C\u8BF7\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002",
|
|
522
|
+
"error.subagent": "\u5B50\u4EE3\u7406\u4F1A\u8BDD\u6682\u4E0D\u652F\u6301\u65C1\u95EE\uFF0C\u8BF7\u8FD4\u56DE\u4E3B\u4F1A\u8BDD\u4F7F\u7528 /btw\u3002",
|
|
522
523
|
"error.empty": "\u8BF7\u8F93\u5165\u65C1\u95EE\u5185\u5BB9\u3002",
|
|
523
524
|
"error.length": `\u65C1\u95EE\u6700\u591A\u652F\u6301 ${MAX_QUESTION_LENGTH} \u4E2A\u5B57\u7B26\u3002`,
|
|
524
525
|
"error.capacity": "\u6B63\u5728\u5904\u7406\u7684\u65C1\u95EE\u8F83\u591A\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
@@ -572,6 +573,7 @@ var en = {
|
|
|
572
573
|
"error.attachments": "Side questions accept text only. Your images and files remain in the input.",
|
|
573
574
|
"error.removeAttachments": "Side questions accept text only. Remove the images and files first.",
|
|
574
575
|
"error.backend": "The BTW backend is unavailable. Check the plugin configuration.",
|
|
576
|
+
"error.subagent": "Side questions are not supported in subagent sessions. Use /btw in the main session.",
|
|
575
577
|
"error.empty": "Enter a side question.",
|
|
576
578
|
"error.length": `Side questions are limited to ${MAX_QUESTION_LENGTH.toLocaleString("en-US")} characters.`,
|
|
577
579
|
"error.capacity": "Too many side questions are running. Try again shortly.",
|
|
@@ -604,6 +606,8 @@ var CLOSE_COMMAND = "btw-close";
|
|
|
604
606
|
|
|
605
607
|
// src/client/bubbles.ts
|
|
606
608
|
var MAX_BUBBLES_PER_SESSION = 20;
|
|
609
|
+
var SideRequestNotStartedError = class extends Error {
|
|
610
|
+
};
|
|
607
611
|
var BubbleStore = class {
|
|
608
612
|
constructor(transport, t = translate()) {
|
|
609
613
|
this.transport = transport;
|
|
@@ -613,6 +617,9 @@ var BubbleStore = class {
|
|
|
613
617
|
listeners = /* @__PURE__ */ new Set();
|
|
614
618
|
active = /* @__PURE__ */ new Map();
|
|
615
619
|
closing = /* @__PURE__ */ new Map();
|
|
620
|
+
notStarted = /* @__PURE__ */ new Set();
|
|
621
|
+
runEnd = /* @__PURE__ */ new Map();
|
|
622
|
+
closeFenced = /* @__PURE__ */ new Set();
|
|
616
623
|
admitting = /* @__PURE__ */ new Set();
|
|
617
624
|
disposed = false;
|
|
618
625
|
getSnapshot = () => this.snapshot;
|
|
@@ -649,12 +656,43 @@ var BubbleStore = class {
|
|
|
649
656
|
const id = crypto.randomUUID();
|
|
650
657
|
const controller = new AbortController();
|
|
651
658
|
this.active.set(id, controller);
|
|
659
|
+
this.runEnd.set(id, "pending");
|
|
652
660
|
this.publish([...this.snapshot, { id, sessionId, question, ...reference === void 0 ? {} : { reference }, answer: "", phase: "answering" }]);
|
|
653
661
|
void Promise.resolve().then(() => reference === void 0 ? this.transport.run(sessionId, id, question, controller.signal) : this.transport.run(sessionId, id, question, controller.signal, reference)).then((result) => {
|
|
654
|
-
if (
|
|
655
|
-
|
|
662
|
+
if (result.kind === "success") {
|
|
663
|
+
this.runEnd.set(id, "success");
|
|
664
|
+
if (!this.snapshot.some((item) => item.id === id)) return;
|
|
665
|
+
const failedClose = this.closeFenced.has(id) || Boolean(this.snapshot.find((item) => item.id === id)?.closeFailed);
|
|
666
|
+
this.update(id, { phase: failedClose ? "error" : this.closing.has(id) ? "closing" : "done", answer: result.text, ...failedClose ? {} : { error: void 0 } });
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (controller.signal.aborted) {
|
|
670
|
+
if (this.runEnd.get(id) === "pending") this.runEnd.set(id, "aborted");
|
|
671
|
+
this.dropIfCloseCannotFinish(id);
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
this.runEnd.set(id, "failed");
|
|
675
|
+
if (!this.closing.has(id)) this.update(id, { phase: "error", answer: "", error: result.text });
|
|
656
676
|
}).catch((error) => {
|
|
657
|
-
if (
|
|
677
|
+
if (this.runEnd.get(id) === "success") return;
|
|
678
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
679
|
+
if (error instanceof SideRequestNotStartedError && this.snapshot.some((item) => item.id === id)) {
|
|
680
|
+
this.runEnd.set(id, "not-started");
|
|
681
|
+
this.notStarted.add(id);
|
|
682
|
+
if (this.closeFenced.has(id) || this.closing.has(id)) {
|
|
683
|
+
this.remove(id);
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
this.update(id, { phase: "error", error: message });
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
if (controller.signal.aborted) {
|
|
690
|
+
if (this.runEnd.get(id) === "pending") this.runEnd.set(id, "aborted");
|
|
691
|
+
this.dropIfCloseCannotFinish(id);
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
this.runEnd.set(id, "failed");
|
|
695
|
+
if (!this.closing.has(id)) this.update(id, { phase: "error", error: message });
|
|
658
696
|
}).finally(() => {
|
|
659
697
|
this.active.delete(id);
|
|
660
698
|
});
|
|
@@ -665,12 +703,28 @@ var BubbleStore = class {
|
|
|
665
703
|
if (existing) return existing;
|
|
666
704
|
const item = this.snapshot.find((bubble) => bubble.id === id);
|
|
667
705
|
if (!item) return Promise.resolve();
|
|
706
|
+
if (this.notStarted.has(id)) {
|
|
707
|
+
this.remove(id);
|
|
708
|
+
return Promise.resolve();
|
|
709
|
+
}
|
|
668
710
|
this.update(id, { phase: "closing", error: void 0, closeFailed: false });
|
|
669
711
|
this.active.get(id)?.abort();
|
|
670
712
|
const operation = Promise.resolve().then(() => this.transport.close(item.sessionId, id)).then((result) => {
|
|
671
713
|
if (result.kind === "error") throw new Error(result.text);
|
|
672
|
-
this.
|
|
714
|
+
this.remove(id);
|
|
673
715
|
}).catch((error) => {
|
|
716
|
+
if (this.notStarted.has(id) || this.runEnd.get(id) === "not-started") {
|
|
717
|
+
this.remove(id);
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (error instanceof SideRequestNotStartedError) {
|
|
721
|
+
this.closeFenced.add(id);
|
|
722
|
+
const end = this.runEnd.get(id);
|
|
723
|
+
if (end === "aborted" || end === "not-started") {
|
|
724
|
+
this.remove(id);
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
674
728
|
this.update(id, { phase: "error", closeFailed: true, error: error instanceof Error ? error.message : String(error) });
|
|
675
729
|
}).finally(() => {
|
|
676
730
|
this.closing.delete(id);
|
|
@@ -683,6 +737,17 @@ var BubbleStore = class {
|
|
|
683
737
|
this.disposed = true;
|
|
684
738
|
await Promise.all(this.snapshot.map((item) => this.close(item.id)));
|
|
685
739
|
}
|
|
740
|
+
dropIfCloseCannotFinish(id) {
|
|
741
|
+
if (!this.closeFenced.has(id)) return;
|
|
742
|
+
const end = this.runEnd.get(id);
|
|
743
|
+
if (end === "not-started" || end === "aborted") this.remove(id);
|
|
744
|
+
}
|
|
745
|
+
remove(id) {
|
|
746
|
+
this.notStarted.delete(id);
|
|
747
|
+
this.runEnd.delete(id);
|
|
748
|
+
this.closeFenced.delete(id);
|
|
749
|
+
this.publish(this.snapshot.filter((item) => item.id !== id));
|
|
750
|
+
}
|
|
686
751
|
update(id, patch2) {
|
|
687
752
|
this.publish(this.snapshot.map((item) => item.id === id ? { ...item, ...patch2 } : item));
|
|
688
753
|
}
|
|
@@ -13793,7 +13858,7 @@ function sessionIdOf(session) {
|
|
|
13793
13858
|
if (session && typeof session === "object" && "sessionId" in session) return String(session.sessionId);
|
|
13794
13859
|
return String(session);
|
|
13795
13860
|
}
|
|
13796
|
-
function attachOfficialBtw(commandUi, claim, t) {
|
|
13861
|
+
function attachOfficialBtw(commandUi, claim, t, isSubagent) {
|
|
13797
13862
|
const live = commandUi;
|
|
13798
13863
|
if (!live) return () => {
|
|
13799
13864
|
};
|
|
@@ -13803,7 +13868,7 @@ function attachOfficialBtw(commandUi, claim, t) {
|
|
|
13803
13868
|
live.candidates = async (...args) => {
|
|
13804
13869
|
const rows = await original.apply(live, args);
|
|
13805
13870
|
if (!Array.isArray(rows)) return rows;
|
|
13806
|
-
return rows.map((row) => {
|
|
13871
|
+
return rows.filter((row) => !(isSubagent(sessionIdOf(args[0])) && row && typeof row === "object" && "name" in row && row.name === "btw")).map((row) => {
|
|
13807
13872
|
if (!row || typeof row !== "object" || !("name" in row) || row.name !== "btw") return row;
|
|
13808
13873
|
const item = row;
|
|
13809
13874
|
return {
|
|
@@ -13821,14 +13886,14 @@ function attachOfficialBtw(commandUi, claim, t) {
|
|
|
13821
13886
|
}
|
|
13822
13887
|
if (typeof live.dispatch === "function") {
|
|
13823
13888
|
const original = live.dispatch.bind(live);
|
|
13824
|
-
live.dispatch = (pick) => pick.candidate?.name === "btw" ? claim(sessionIdOf(pick.session)) : original(pick);
|
|
13889
|
+
live.dispatch = (pick) => pick.candidate?.name === "btw" ? isSubagent(sessionIdOf(pick.session)) ? void 0 : claim(sessionIdOf(pick.session)) : original(pick);
|
|
13825
13890
|
restore.push(() => {
|
|
13826
13891
|
live.dispatch = original;
|
|
13827
13892
|
});
|
|
13828
13893
|
}
|
|
13829
13894
|
if (typeof live.matchSpace === "function") {
|
|
13830
13895
|
const original = live.matchSpace.bind(live);
|
|
13831
|
-
live.matchSpace = (session, token) => token === "/btw" ? claim(sessionIdOf(session)) : original(session, token);
|
|
13896
|
+
live.matchSpace = (session, token) => token === "/btw" ? isSubagent(sessionIdOf(session)) ? void 0 : claim(sessionIdOf(session)) : original(session, token);
|
|
13832
13897
|
restore.push(() => {
|
|
13833
13898
|
live.matchSpace = original;
|
|
13834
13899
|
});
|
|
@@ -13837,6 +13902,7 @@ function attachOfficialBtw(commandUi, claim, t) {
|
|
|
13837
13902
|
const original = live.matchEnter.bind(live);
|
|
13838
13903
|
live.matchEnter = async (session, line, signal, envelope) => {
|
|
13839
13904
|
if (!/^\/btw(?:\s|$)/.test(line.trim())) return original(session, line, signal, envelope);
|
|
13905
|
+
if (isSubagent(sessionIdOf(session))) throw new Error(t("error.subagent"));
|
|
13840
13906
|
if (envelope?.attachments || envelope?.images) throw new Error(t("error.removeAttachments"));
|
|
13841
13907
|
return claim(sessionIdOf(session));
|
|
13842
13908
|
};
|
|
@@ -13848,6 +13914,7 @@ function attachOfficialBtw(commandUi, claim, t) {
|
|
|
13848
13914
|
const original = live.execute.bind(live);
|
|
13849
13915
|
live.execute = async (session, line, attachments) => {
|
|
13850
13916
|
if (!/^\/btw(?:\s|$)/.test(line)) return original(session, line, attachments);
|
|
13917
|
+
if (isSubagent(sessionIdOf(session))) return { kind: "error", text: t("error.subagent") };
|
|
13851
13918
|
if (Array.isArray(attachments) && attachments.length) return { kind: "error", text: t("error.attachments") };
|
|
13852
13919
|
const outcome = claim(sessionIdOf(session));
|
|
13853
13920
|
if (!outcome || typeof outcome !== "object" || !("claim" in outcome)) return { kind: "error", text: t("error.backend") };
|
|
@@ -13868,9 +13935,19 @@ function apply(ctx) {
|
|
|
13868
13935
|
const t = ctx.locale.bind(NS);
|
|
13869
13936
|
const slots = ctx.get("slots");
|
|
13870
13937
|
const remote = ctx.get("remote");
|
|
13938
|
+
const sessions = ctx.get("sessions");
|
|
13939
|
+
const isSubagent = (id) => Boolean(sessions.subagentAddress?.(id)) || sessions.list?.getSnapshot().byId[id]?.origin === "subagent";
|
|
13871
13940
|
const execute = async (session, line, signal) => {
|
|
13872
13941
|
const response = await remote.commands.execute(session, line, [], signal);
|
|
13873
|
-
if (!response.ok)
|
|
13942
|
+
if (!response.ok) {
|
|
13943
|
+
const failure = response.error;
|
|
13944
|
+
const code4 = failure.code;
|
|
13945
|
+
const details = failure.details;
|
|
13946
|
+
const reason = details && typeof details === "object" && "reason" in details && typeof details.reason === "string" ? details.reason : void 0;
|
|
13947
|
+
const ownedBySubagent = (code4 === "agent-busy" || code4 === "session/agent-busy") && (reason === "use subagent delivery for this child session" || failure.message === `session "${session}" is owned by subagent routing`);
|
|
13948
|
+
if (ownedBySubagent) throw new SideRequestNotStartedError(t("error.subagent"));
|
|
13949
|
+
throw new Error(failure.message);
|
|
13950
|
+
}
|
|
13874
13951
|
if (!response.value) throw new Error(t("error.backend"));
|
|
13875
13952
|
return { kind: response.value.result.kind, text: response.value.result.text ?? "" };
|
|
13876
13953
|
};
|
|
@@ -13880,11 +13957,12 @@ function apply(ctx) {
|
|
|
13880
13957
|
}, t);
|
|
13881
13958
|
const claim = (sessionId) => ({ claim: {
|
|
13882
13959
|
name: "btw",
|
|
13883
|
-
token: "/btw",
|
|
13960
|
+
token: "/btw ",
|
|
13884
13961
|
get hint() {
|
|
13885
13962
|
return t("command.hint");
|
|
13886
13963
|
},
|
|
13887
13964
|
submit: async (args, _actx, attachments) => {
|
|
13965
|
+
if (isSubagent(sessionId)) return { kind: "error", text: t("error.subagent") };
|
|
13888
13966
|
if (attachments.length) return { kind: "error", text: t("error.attachments") };
|
|
13889
13967
|
try {
|
|
13890
13968
|
await store.ask(sessionId, args.trim());
|
|
@@ -13894,8 +13972,8 @@ function apply(ctx) {
|
|
|
13894
13972
|
}
|
|
13895
13973
|
}
|
|
13896
13974
|
} });
|
|
13897
|
-
if (typeof ctx.inject === "function") ctx.inject(["commandUi"], (scope) => attachOfficialBtw(scope.get("commandUi"), (sessionId) => claim(sessionId), t));
|
|
13898
|
-
else ctx.effect(() => attachOfficialBtw(ctx.get("commandUi"), (sessionId) => claim(sessionId), t));
|
|
13975
|
+
if (typeof ctx.inject === "function") ctx.inject(["commandUi"], (scope) => attachOfficialBtw(scope.get("commandUi"), (sessionId) => claim(sessionId), t, isSubagent));
|
|
13976
|
+
else ctx.effect(() => attachOfficialBtw(ctx.get("commandUi"), (sessionId) => claim(sessionId), t, isSubagent));
|
|
13899
13977
|
ctx.effect(() => {
|
|
13900
13978
|
const style = document.createElement("style");
|
|
13901
13979
|
style.dataset.plugin = "@michengai/dsh-btw";
|
|
@@ -13907,7 +13985,7 @@ function apply(ctx) {
|
|
|
13907
13985
|
});
|
|
13908
13986
|
ctx.effect(() => () => store.dispose());
|
|
13909
13987
|
function Dock(props) {
|
|
13910
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(SelectionAsk, { key: props.session.sessionId, store, sessionId: props.session.sessionId, t: props.t, addToConversation: (reference) => {
|
|
13988
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, !props.session.subagent && !isSubagent(props.session.sessionId) && /* @__PURE__ */ import_react7.default.createElement(SelectionAsk, { key: props.session.sessionId, store, sessionId: props.session.sessionId, t: props.t, addToConversation: (reference) => {
|
|
13911
13989
|
const session = ctx.get("sessions").scope(props.session.sessionId);
|
|
13912
13990
|
if (!session) throw new Error(props.t("error.backend"));
|
|
13913
13991
|
addQuoteToComposer(ctx.conversation.input.for(session), reference, props.t);
|
package/lib/index.js
CHANGED
|
@@ -42,6 +42,7 @@ var zh = {
|
|
|
42
42
|
"error.attachments": "\u65C1\u95EE\u53EA\u63A5\u53D7\u6587\u5B57\uFF0C\u56FE\u7247\u548C\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u8F93\u5165\u6846\u4E2D\u3002",
|
|
43
43
|
"error.removeAttachments": "\u65C1\u95EE\u53EA\u63A5\u53D7\u6587\u5B57\uFF0C\u8BF7\u5148\u79FB\u9664\u56FE\u7247\u548C\u6587\u4EF6\u3002",
|
|
44
44
|
"error.backend": "BTW \u540E\u7AEF\u5C1A\u672A\u542F\u7528\uFF0C\u8BF7\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\u3002",
|
|
45
|
+
"error.subagent": "\u5B50\u4EE3\u7406\u4F1A\u8BDD\u6682\u4E0D\u652F\u6301\u65C1\u95EE\uFF0C\u8BF7\u8FD4\u56DE\u4E3B\u4F1A\u8BDD\u4F7F\u7528 /btw\u3002",
|
|
45
46
|
"error.empty": "\u8BF7\u8F93\u5165\u65C1\u95EE\u5185\u5BB9\u3002",
|
|
46
47
|
"error.length": `\u65C1\u95EE\u6700\u591A\u652F\u6301 ${MAX_QUESTION_LENGTH} \u4E2A\u5B57\u7B26\u3002`,
|
|
47
48
|
"error.capacity": "\u6B63\u5728\u5904\u7406\u7684\u65C1\u95EE\u8F83\u591A\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
@@ -95,6 +96,7 @@ var en = {
|
|
|
95
96
|
"error.attachments": "Side questions accept text only. Your images and files remain in the input.",
|
|
96
97
|
"error.removeAttachments": "Side questions accept text only. Remove the images and files first.",
|
|
97
98
|
"error.backend": "The BTW backend is unavailable. Check the plugin configuration.",
|
|
99
|
+
"error.subagent": "Side questions are not supported in subagent sessions. Use /btw in the main session.",
|
|
98
100
|
"error.empty": "Enter a side question.",
|
|
99
101
|
"error.length": `Side questions are limited to ${MAX_QUESTION_LENGTH.toLocaleString("en-US")} characters.`,
|
|
100
102
|
"error.capacity": "Too many side questions are running. Try again shortly.",
|
|
@@ -14,6 +14,9 @@ export interface SideTransport {
|
|
|
14
14
|
run(session: string, id: string, question: string, signal: AbortSignal, reference?: string): Promise<SideResult>;
|
|
15
15
|
close(session: string, id: string): Promise<SideResult>;
|
|
16
16
|
}
|
|
17
|
+
/** 宿主在进入 handler 前明确拒绝启动;没有后台任务需要清理。 */
|
|
18
|
+
export declare class SideRequestNotStartedError extends Error {
|
|
19
|
+
}
|
|
17
20
|
/** 仅内存 UI 状态;关闭请求与答案返回按请求身份分别收敛。 */
|
|
18
21
|
export declare class BubbleStore {
|
|
19
22
|
private readonly transport;
|
|
@@ -22,6 +25,9 @@ export declare class BubbleStore {
|
|
|
22
25
|
private readonly listeners;
|
|
23
26
|
private readonly active;
|
|
24
27
|
private readonly closing;
|
|
28
|
+
private readonly notStarted;
|
|
29
|
+
private readonly runEnd;
|
|
30
|
+
private readonly closeFenced;
|
|
25
31
|
private readonly admitting;
|
|
26
32
|
private disposed;
|
|
27
33
|
constructor(transport: SideTransport, t?: BtwTranslate);
|
|
@@ -31,6 +37,8 @@ export declare class BubbleStore {
|
|
|
31
37
|
ask(sessionId: string, question: string, reference?: string): Promise<string>;
|
|
32
38
|
close(id: string): Promise<void>;
|
|
33
39
|
dispose(): Promise<void>;
|
|
40
|
+
private dropIfCloseCannotFinish;
|
|
41
|
+
private remove;
|
|
34
42
|
private update;
|
|
35
43
|
private publish;
|
|
36
44
|
}
|
package/lib/types/locales.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-btw",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "DSH 一次性只读旁问插件:基于当前上下文回答,独立气泡,不执行工具 · One-shot read-only side-ask plugin: answers from current context in an independent bubble, no tool execution",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|