dsh-input-traffic 0.2.9 → 0.2.10-beta.1
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.ja.md +78 -0
- package/CHANGELOG.ko.md +78 -0
- package/CHANGELOG.md +92 -0
- package/INSTALL.ja.md +151 -0
- package/INSTALL.ko.md +151 -0
- package/INSTALL.md +152 -0
- package/INSTALL.zh.md +151 -0
- package/README.en.md +25 -1
- package/README.ja.md +187 -0
- package/README.ko.md +181 -0
- package/README.md +37 -3
- package/dsh.plugin.json +13 -0
- package/lib/client.js +1433 -1419
- package/lib/client.js.map +1 -1
- package/lib/types/client/freeze-button.d.ts +16 -9
- package/lib/types/client/freeze-button.d.ts.map +1 -1
- package/lib/types/client/freeze-button.js +86 -85
- package/lib/types/client/freeze-button.js.map +1 -1
- package/lib/types/client/index.d.ts +47 -24
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +117 -103
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/locales.d.ts +63 -59
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +211 -107
- package/lib/types/client/locales.js.map +1 -1
- package/package.json +15 -7
|
@@ -1,86 +1,87 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* Session freeze/resume control, mounted in the composer's right tool row
|
|
4
|
-
* (`conversation.input.right`) so it is reachable before anything queues.
|
|
5
|
-
*
|
|
6
|
-
* Peak-hour pause semantics: freeze does NOT interrupt the running turn —it
|
|
7
|
-
* finishes naturally. The queued messages are detached (removed, preserved in
|
|
8
|
-
* the shared store), so the driver finds no pending work and stops after the
|
|
9
|
-
* current turn. Resume re-submits the preserved texts, waking the driver and
|
|
10
|
-
* continuing the queue.
|
|
11
|
-
*
|
|
12
|
-
* dsh-session-guard 协作(D8 fail-open):
|
|
13
|
-
* - 冻结 = 前端摘队列(本插件)+ composer block(阻止新输入漏进对话) + 尽力调服务端
|
|
14
|
-
* sessionGuard.stopNextTurn(停掉 session 下一回合;session-guard 未装时静默跳过)。
|
|
15
|
-
* - 解冻 = 清 composer block + **先** await sessionGuard.resume(让被打断回合的自然
|
|
16
|
-
* 下一步先发生),**再**重投队列(later 级条目因此排在自然 next turn 之后,不再插队)。
|
|
17
|
-
* - 本插件只做冻结增强,不承担重试/暂停决策(归后端,D9)。
|
|
18
|
-
*/
|
|
19
|
-
import { useSyncExternalStore } from 'react';
|
|
20
|
-
import { freezeStore } from "./freeze-store.js";
|
|
21
|
-
import { sessionGuardResume, sessionGuardStopNextTurn } from "./session-guard-bridge.js";
|
|
22
|
-
import css from './freeze-button.module.css';
|
|
23
|
-
/**
|
|
24
|
-
* Freeze/resume toggle for the peak-hour scenario.
|
|
25
|
-
* @param props - slot props; the session snapshot drives the detach list.
|
|
26
|
-
*/
|
|
27
|
-
export function FreezeButton({
|
|
28
|
-
// The freeze store is keyed by session: read the owning session's snapshot.
|
|
29
|
-
const sid = sessionId ?? '';
|
|
30
|
-
const { frozen } = useSyncExternalStore(freezeStore.subscribe, () => freezeStore.getSnapshot(sid));
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
freezeStore.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Session freeze/resume control, mounted in the composer's right tool row
|
|
4
|
+
* (`conversation.input.right`) so it is reachable before anything queues.
|
|
5
|
+
*
|
|
6
|
+
* Peak-hour pause semantics: freeze does NOT interrupt the running turn —it
|
|
7
|
+
* finishes naturally. The queued messages are detached (removed, preserved in
|
|
8
|
+
* the shared store), so the driver finds no pending work and stops after the
|
|
9
|
+
* current turn. Resume re-submits the preserved texts, waking the driver and
|
|
10
|
+
* continuing the queue.
|
|
11
|
+
*
|
|
12
|
+
* dsh-session-guard 协作(D8 fail-open):
|
|
13
|
+
* - 冻结 = 前端摘队列(本插件)+ composer block(阻止新输入漏进对话) + 尽力调服务端
|
|
14
|
+
* sessionGuard.stopNextTurn(停掉 session 下一回合;session-guard 未装时静默跳过)。
|
|
15
|
+
* - 解冻 = 清 composer block + **先** await sessionGuard.resume(让被打断回合的自然
|
|
16
|
+
* 下一步先发生),**再**重投队列(later 级条目因此排在自然 next turn 之后,不再插队)。
|
|
17
|
+
* - 本插件只做冻结增强,不承担重试/暂停决策(归后端,D9)。
|
|
18
|
+
*/
|
|
19
|
+
import { useSyncExternalStore } from 'react';
|
|
20
|
+
import { freezeStore } from "./freeze-store.js";
|
|
21
|
+
import { sessionGuardResume, sessionGuardStopNextTurn } from "./session-guard-bridge.js";
|
|
22
|
+
import css from './freeze-button.module.css';
|
|
23
|
+
/**
|
|
24
|
+
* Freeze/resume toggle for the peak-hour scenario.
|
|
25
|
+
* @param props - slot props; the session snapshot drives the detach list.
|
|
26
|
+
*/
|
|
27
|
+
export function FreezeButton({ useSession, updateQueue, cancel, send, sendSteer, sessionId, setComposerBlock, notify, t }) {
|
|
28
|
+
// The freeze store is keyed by session: read the owning session's snapshot.
|
|
29
|
+
const sid = sessionId ?? '';
|
|
30
|
+
const { frozen } = useSyncExternalStore(freezeStore.subscribe, () => freezeStore.getSnapshot(sid));
|
|
31
|
+
const queue = useSession(s => s.queue);
|
|
32
|
+
const freeze = async () => {
|
|
33
|
+
// Detach every pending input row — queued (next-turn) and already-steered
|
|
34
|
+
// (next-step) alike — so nothing stays in the live queue while frozen.
|
|
35
|
+
// Steered rows keep their next intent as a safe_point plan for resume.
|
|
36
|
+
const rows = queue.filter(row => row.placement === 'queued' || row.placement === 'steering');
|
|
37
|
+
// Preserve plain-text copies; non-text rows cannot be re-sent and are
|
|
38
|
+
// released by the freeze (documented limitation).
|
|
39
|
+
const pending = rows.flatMap(row => row.text === null ? [] : [{ text: row.text, tier: row.placement === 'steering' ? 'safe_point' : 'queue' }]);
|
|
40
|
+
// Detach every pending row: the running turn finishes naturally, then the
|
|
41
|
+
// driver finds no pending work and stops.
|
|
42
|
+
await Promise.all(rows.map(row => updateQueue(row.id, { kind: 'remove' }).catch(() => undefined)));
|
|
43
|
+
freezeStore.set(sid, { frozen: true, pending });
|
|
44
|
+
// Raise the composer block: while frozen the composer is inert, so plain
|
|
45
|
+
// Enter can never leak a new message into the conversation (busyEnter
|
|
46
|
+
// only gates busy sessions; an idle/paused session would send directly).
|
|
47
|
+
setComposerBlock?.(t('steer.frozenInput'));
|
|
48
|
+
// 服务端:停掉 session 下一回合(fail-open,session-guard 未装则静默)。
|
|
49
|
+
if (sessionId !== undefined)
|
|
50
|
+
void sessionGuardStopNextTurn(sessionId);
|
|
51
|
+
};
|
|
52
|
+
const resume = async () => {
|
|
53
|
+
const pending = freezeStore.getSnapshot(sid).pending;
|
|
54
|
+
freezeStore.set(sid, { frozen: false, pending: [] });
|
|
55
|
+
setComposerBlock?.(undefined);
|
|
56
|
+
try {
|
|
57
|
+
// 先恢复服务端会话:被打断回合的自然下一步(deferredTools 续跑)先发生。
|
|
58
|
+
// 之后再重投队列 —— later 级条目经 send 进入 next-turn,排在自然 next turn
|
|
59
|
+
// 之后;safe_point/force 仍按各自语义插队。顺序倒置会让 later 抢在自然
|
|
60
|
+
// next turn 前被消费(idle 态 send 立即唤醒新回合)。
|
|
61
|
+
if (sessionId !== undefined)
|
|
62
|
+
await sessionGuardResume(sessionId);
|
|
63
|
+
// Re-submit the preserved queue in FIFO order honoring each entry's
|
|
64
|
+
// planned insertion tier: force (red) interrupts the current run first,
|
|
65
|
+
// safe_point (yellow) steers into the next step, queue (green) flows
|
|
66
|
+
// through the wake-and-continue chain.
|
|
67
|
+
for (const entry of pending) {
|
|
68
|
+
if (entry.tier === 'force')
|
|
69
|
+
await cancel();
|
|
70
|
+
if (entry.tier === 'safe_point' && sendSteer !== undefined)
|
|
71
|
+
await sendSteer(entry.text);
|
|
72
|
+
else
|
|
73
|
+
await send(entry.text);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
notify('error', t('steer.resumeFailed'));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return (_jsx("button", { type: "button", className: css.freeze, "aria-label": frozen ? t('steer.resume') : t('steer.freeze'), "aria-pressed": frozen || undefined, title: frozen ? t('steer.frozen') : undefined, onClick: () => {
|
|
81
|
+
if (frozen)
|
|
82
|
+
void resume();
|
|
83
|
+
else
|
|
84
|
+
void freeze();
|
|
85
|
+
}, children: _jsx("span", { className: css.label, children: frozen ? t('steer.resume') : t('steer.freeze') }) }));
|
|
86
|
+
}
|
|
86
87
|
//# sourceMappingURL=freeze-button.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"freeze-button.js","sourceRoot":"","sources":["../../../src/client/freeze-button.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AACxF,OAAO,GAAG,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"freeze-button.js","sourceRoot":"","sources":["../../../src/client/freeze-button.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,48 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-input-traffic —browser half.
|
|
3
|
-
*
|
|
4
|
-
* The whole takeover lives here:
|
|
5
|
-
* 1. registers the `steer` dictionaries;
|
|
6
|
-
* 2. pins `ui-conversation.busyEnter` to `queue` (plain Enter = green later)
|
|
7
|
-
* so the hidden official row cannot leak a stale queue/steer preference;
|
|
8
|
-
* 3. shadows the official queue dock (`conversation.input.dock` cell id
|
|
9
|
-
* `queue`, priority -1) with the three-tier planning strip;
|
|
10
|
-
* 4. shadows the official busy-Enter settings row (`settings.general.item`
|
|
11
|
-
* cell id `composer-enter`, priority -1) with a null render.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
/**
|
|
2
|
+
* dsh-input-traffic —browser half.
|
|
3
|
+
*
|
|
4
|
+
* The whole takeover lives here:
|
|
5
|
+
* 1. registers the `steer` dictionaries;
|
|
6
|
+
* 2. pins `ui-conversation.busyEnter` to `queue` (plain Enter = green later)
|
|
7
|
+
* so the hidden official row cannot leak a stale queue/steer preference;
|
|
8
|
+
* 3. shadows the official queue dock (`conversation.input.dock` cell id
|
|
9
|
+
* `queue`, priority -1) with the three-tier planning strip;
|
|
10
|
+
* 4. shadows the official busy-Enter settings row (`settings.general.item`
|
|
11
|
+
* cell id `composer-enter`, priority -1) with a null render.
|
|
12
|
+
*
|
|
13
|
+
* ORDERING (why the dock registers at QUEUE_DOCK_ORDER instead of the
|
|
14
|
+
* official dock's 20): a list slot's DISPLAY position is decided by `order`
|
|
15
|
+
* alone — `ui-renderer/src/client/scoped-slots.tsx` maps the shadowing
|
|
16
|
+
* winners to rows and then sorts them by `order` (both 0.1.1 and 0.1.2) —
|
|
17
|
+
* while `priority` only decides which entry wins a shared cell id. Keeping
|
|
18
|
+
* the official 20 therefore left the strip above any later contributor
|
|
19
|
+
* (dsh-perm-gate's notice registers order 30), which pushed that notice
|
|
20
|
+
* between the queue strip and the composer card. A deliberately high order
|
|
21
|
+
* keeps the strip adjacent to the card; priority stays -1 so the cell
|
|
22
|
+
* takeover still holds.
|
|
23
|
+
*
|
|
24
|
+
* All @deepseek-ai/* imports are type-only: collaboration happens through
|
|
25
|
+
* cordis services and slot registration only (client bundle purity).
|
|
26
|
+
*/
|
|
27
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
28
|
+
/**
|
|
29
|
+
* Display order of the queue strip inside `conversation.input.dock`.
|
|
30
|
+
*
|
|
31
|
+
* List rows render sorted by `order` ascending, so a value above every other
|
|
32
|
+
* contributor keeps the strip as the bottom-most entry of the band — directly
|
|
33
|
+
* on top of the composer card. Known contributors in both 0.1.1-rc.2 and
|
|
34
|
+
* 0.1.2-rc.1: `todo` 0, `goal` 10, official `queue` 20, `dsh-perm-gate.notice`
|
|
35
|
+
* 30. DSH has no "last" slot semantics, so this is a convention, not a
|
|
36
|
+
* structural guarantee: a third party registering a larger value could still
|
|
37
|
+
* land below us.
|
|
38
|
+
*/
|
|
39
|
+
export declare const QUEUE_DOCK_ORDER = 1000;
|
|
40
|
+
/** Services required by the browser half. */
|
|
41
|
+
export declare const inject: string[];
|
|
42
|
+
/**
|
|
43
|
+
* Client plugin body: dictionaries, busy-Enter pinning, and the two slot
|
|
44
|
+
* shadowings.
|
|
45
|
+
* @param ctx - client root context.
|
|
46
|
+
*/
|
|
47
|
+
export declare function apply(ctx: ClientContext): void;
|
|
25
48
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,wCAAwC,CAAA;AAgBtF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAA;AAkBpC,6CAA6C;AAC7C,eAAO,MAAM,MAAM,UAAmE,CAAA;AAEtF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAyE9C"}
|
|
@@ -1,104 +1,118 @@
|
|
|
1
|
-
import { NS, en, zh } from "./locales.js";
|
|
2
|
-
import { SteerQueueDock } from "./steer-queue-dock.js";
|
|
3
|
-
import { FreezeButton } from "./freeze-button.js";
|
|
4
|
-
import { HideEnterRow } from "./hide-enter-row.js";
|
|
5
|
-
/** Durable conversation settings namespace owned by ui-conversation. */
|
|
6
|
-
const CONVERSATION_SETTINGS_NAMESPACE = 'ui-conversation';
|
|
7
|
-
/** Busy-Enter field inside that namespace; the plugin pins it to queue. */
|
|
8
|
-
const BUSY_ENTER_FIELD = 'busyEnter';
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
1
|
+
import { NS, en, zh } from "./locales.js";
|
|
2
|
+
import { SteerQueueDock } from "./steer-queue-dock.js";
|
|
3
|
+
import { FreezeButton } from "./freeze-button.js";
|
|
4
|
+
import { HideEnterRow } from "./hide-enter-row.js";
|
|
5
|
+
/** Durable conversation settings namespace owned by ui-conversation. */
|
|
6
|
+
const CONVERSATION_SETTINGS_NAMESPACE = 'ui-conversation';
|
|
7
|
+
/** Busy-Enter field inside that namespace; the plugin pins it to queue. */
|
|
8
|
+
const BUSY_ENTER_FIELD = 'busyEnter';
|
|
9
|
+
/**
|
|
10
|
+
* Display order of the queue strip inside `conversation.input.dock`.
|
|
11
|
+
*
|
|
12
|
+
* List rows render sorted by `order` ascending, so a value above every other
|
|
13
|
+
* contributor keeps the strip as the bottom-most entry of the band — directly
|
|
14
|
+
* on top of the composer card. Known contributors in both 0.1.1-rc.2 and
|
|
15
|
+
* 0.1.2-rc.1: `todo` 0, `goal` 10, official `queue` 20, `dsh-perm-gate.notice`
|
|
16
|
+
* 30. DSH has no "last" slot semantics, so this is a convention, not a
|
|
17
|
+
* structural guarantee: a third party registering a larger value could still
|
|
18
|
+
* land below us.
|
|
19
|
+
*/
|
|
20
|
+
export const QUEUE_DOCK_ORDER = 1000;
|
|
21
|
+
/**
|
|
22
|
+
* Deliver one plain-text message into the session's next step. The exposed
|
|
23
|
+
* conversation `send` verb only queues into the next turn, so resume steers
|
|
24
|
+
* through the session face's steer-mode prompt instead (no harness change).
|
|
25
|
+
* @param ctx - root context (resolves the session face behind the scope).
|
|
26
|
+
* @param actx - agent-scoped context of the owning session.
|
|
27
|
+
* @param text - message text to deliver.
|
|
28
|
+
*/
|
|
29
|
+
function steerPrompt(actx, text) {
|
|
30
|
+
// steer-mode prompt 面在本版(main@0.2.8)契约中未声明;resume 落到 conversation.send
|
|
31
|
+
// (排队到下一轮)交付 safe_point 文本,与 feature 分支语义对齐但取当前可用 API。
|
|
32
|
+
const conversation = actx.get('conversation');
|
|
33
|
+
if (conversation === undefined)
|
|
34
|
+
return Promise.reject(new Error('steer resume: conversation service unavailable'));
|
|
35
|
+
return conversation.send(text);
|
|
36
|
+
}
|
|
37
|
+
/** Services required by the browser half. */
|
|
38
|
+
export const inject = ['slots', 'locale', 'sessions', 'conversation', 'settingsScope'];
|
|
39
|
+
/**
|
|
40
|
+
* Client plugin body: dictionaries, busy-Enter pinning, and the two slot
|
|
41
|
+
* shadowings.
|
|
42
|
+
* @param ctx - client root context.
|
|
43
|
+
*/
|
|
44
|
+
export function apply(ctx) {
|
|
45
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-input-traffic: dictionaries');
|
|
46
|
+
// Take over the busy-Enter behavior: plain Enter stays queue-later while
|
|
47
|
+
// the official row is hidden. Pinning here also repairs a persisted `steer`
|
|
48
|
+
// preference that would otherwise keep working invisibly behind the hidden
|
|
49
|
+
// row. Best-effort: a memory-mode host simply accepts it locally.
|
|
50
|
+
const conversationSettings = ctx.settingsScope.bind({
|
|
51
|
+
namespace: CONVERSATION_SETTINGS_NAMESPACE,
|
|
52
|
+
});
|
|
53
|
+
void conversationSettings.set(BUSY_ENTER_FIELD, 'queue');
|
|
54
|
+
// Shadow the official queue dock with the three-tier planning strip. The
|
|
55
|
+
// high `order` keeps it the bottom-most entry of the band (see the file
|
|
56
|
+
// header); `priority: -1` is what wins the official `queue` cell.
|
|
57
|
+
ctx.slots.inject('conversation.input.dock', () => ctx.slots.register({
|
|
58
|
+
name: 'conversation.input.dock',
|
|
59
|
+
id: 'queue',
|
|
60
|
+
order: QUEUE_DOCK_ORDER,
|
|
61
|
+
priority: -1,
|
|
62
|
+
locale: NS,
|
|
63
|
+
inject: (sessionId) => {
|
|
64
|
+
const actx = ctx.sessions.scope(sessionId);
|
|
65
|
+
if (actx === undefined)
|
|
66
|
+
throw new Error(`steer dock: session "${sessionId}" resolved no scope`);
|
|
67
|
+
const conversation = actx.get('conversation');
|
|
68
|
+
if (conversation === undefined)
|
|
69
|
+
throw new Error('steer dock: conversation service unavailable');
|
|
70
|
+
return {
|
|
71
|
+
updateQueue: (itemId, action) => conversation.updateQueue(itemId, action),
|
|
72
|
+
cancel: () => conversation.cancel(),
|
|
73
|
+
send: (text) => conversation.send(text),
|
|
74
|
+
setDraft: (text) => { conversation.input.for(actx).actions.setDraft(text); },
|
|
75
|
+
notify: (level, text) => { conversation.input.for(actx).notify(level, text); },
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
}, SteerQueueDock));
|
|
79
|
+
// Composer-right freeze/resume control (reachable before anything queues).
|
|
80
|
+
ctx.slots.inject('conversation.input.right', () => ctx.slots.register({
|
|
81
|
+
name: 'conversation.input.right',
|
|
82
|
+
id: 'steer-freeze',
|
|
83
|
+
order: 30,
|
|
84
|
+
locale: NS,
|
|
85
|
+
inject: (sessionId) => {
|
|
86
|
+
const actx = ctx.sessions.scope(sessionId);
|
|
87
|
+
if (actx === undefined)
|
|
88
|
+
throw new Error(`steer freeze: session "${sessionId}" resolved no scope`);
|
|
89
|
+
const conversation = actx.get('conversation');
|
|
90
|
+
if (conversation === undefined)
|
|
91
|
+
throw new Error('steer freeze: conversation service unavailable');
|
|
92
|
+
return {
|
|
93
|
+
updateQueue: (itemId, action) => conversation.updateQueue(itemId, action),
|
|
94
|
+
cancel: () => conversation.cancel(),
|
|
95
|
+
send: (text) => conversation.send(text),
|
|
96
|
+
// safe_point 恢复经 conversation.send 排队到下一轮(本版契约无 steer prompt 面)。
|
|
97
|
+
sendSteer: (text) => steerPrompt(actx, text),
|
|
98
|
+
sessionId: String(sessionId),
|
|
99
|
+
setDraft: (text) => { conversation.input.for(actx).actions.setDraft(text); },
|
|
100
|
+
notify: (level, text) => { conversation.input.for(actx).notify(level, text); },
|
|
101
|
+
// 冻结期间 raise composer block:composer 变 inert(回车/发送按钮全部失效),
|
|
102
|
+
// 输入不会漏进对话;恢复时清除。block 不锁 input.right(恢复按钮仍可点)。
|
|
103
|
+
setComposerBlock: (reason) => {
|
|
104
|
+
conversation.blocks.set(sessionId, reason === undefined ? undefined : { reason });
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
}, FreezeButton));
|
|
109
|
+
// Hide the official busy-Enter settings row (null render wins the cell).
|
|
110
|
+
ctx.slots.inject('settings.general.item', () => ctx.slots.register({
|
|
111
|
+
name: 'settings.general.item',
|
|
112
|
+
id: 'composer-enter',
|
|
113
|
+
order: 20,
|
|
114
|
+
priority: -1,
|
|
115
|
+
locale: NS,
|
|
116
|
+
}, HideEnterRow));
|
|
117
|
+
}
|
|
104
118
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
|