@yeaft/webchat-agent 0.1.505 → 0.1.506
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/connection/message-router.js +14 -1
- package/package.json +1 -1
- package/unify/session.js +8 -0
- package/unify/web-bridge.js +84 -0
|
@@ -25,7 +25,7 @@ import { sendToServer, flushMessageBuffer } from './buffer.js';
|
|
|
25
25
|
import { handleRestartAgent, handleUpgradeAgent } from './upgrade.js';
|
|
26
26
|
import { loadMcpServers, updateMcpConfig } from '../mcp.js';
|
|
27
27
|
import { getLlmConfig, updateLlmConfig, getUnifySettings, updateUnifySettings } from '../unify/config-api.js';
|
|
28
|
-
import { handleUnifyChat, handleUnifyModeSwitch, handleUnifyModelSwitch, resetUnifySession, handleUnifyLoadHistory, handleUnifyMergeThread, handleUnifyForkThread } from '../unify/web-bridge.js';
|
|
28
|
+
import { handleUnifyChat, handleUnifyModeSwitch, handleUnifyModelSwitch, resetUnifySession, handleUnifyLoadHistory, handleUnifyMergeThread, handleUnifyForkThread, handleUnifyAbortThread, handleUnifyAbortAll } from '../unify/web-bridge.js';
|
|
29
29
|
|
|
30
30
|
export async function handleMessage(msg) {
|
|
31
31
|
switch (msg.type) {
|
|
@@ -373,6 +373,19 @@ export async function handleMessage(msg) {
|
|
|
373
373
|
handleUnifyForkThread(msg);
|
|
374
374
|
break;
|
|
375
375
|
|
|
376
|
+
case 'unify_abort_thread':
|
|
377
|
+
// task-325c: user-initiated abort of a single thread's in-flight
|
|
378
|
+
// query. Payload `{ threadId }`. Silent no-op when the thread has
|
|
379
|
+
// no in-flight controller.
|
|
380
|
+
handleUnifyAbortThread(msg);
|
|
381
|
+
break;
|
|
382
|
+
|
|
383
|
+
case 'unify_abort_all':
|
|
384
|
+
// task-325c: user-initiated abort of ALL in-flight queries across
|
|
385
|
+
// every thread. Always emits `unify_aborted` ack.
|
|
386
|
+
handleUnifyAbortAll();
|
|
387
|
+
break;
|
|
388
|
+
|
|
376
389
|
// Expert roles definition (for ExpertPanel detail view)
|
|
377
390
|
case 'get_expert_roles': {
|
|
378
391
|
const { getExpertRolesDefinition } = await import('../expert-roles.js');
|
package/package.json
CHANGED
package/unify/session.js
CHANGED
|
@@ -269,5 +269,13 @@ export async function loadSession(options = {}) {
|
|
|
269
269
|
threadStore: getThreadStore(),
|
|
270
270
|
status,
|
|
271
271
|
shutdown,
|
|
272
|
+
// task-325c: user-initiated abort API. Delegates to web-bridge which
|
|
273
|
+
// owns the per-thread AbortController registry (`abortByThread`).
|
|
274
|
+
// Lazy-imported to avoid a hard cycle with web-bridge.js (which already
|
|
275
|
+
// imports this module to call loadSession).
|
|
276
|
+
async abort(opts = {}) {
|
|
277
|
+
const { abortUnifySession } = await import('./web-bridge.js');
|
|
278
|
+
return abortUnifySession(opts);
|
|
279
|
+
},
|
|
272
280
|
};
|
|
273
281
|
}
|
package/unify/web-bridge.js
CHANGED
|
@@ -848,6 +848,90 @@ export async function handleUnifyChat(msg) {
|
|
|
848
848
|
}
|
|
849
849
|
}
|
|
850
850
|
|
|
851
|
+
/**
|
|
852
|
+
* task-325c: user-initiated abort of an in-flight Unify query on ONE thread.
|
|
853
|
+
*
|
|
854
|
+
* Cancels the AbortController registered for `msg.threadId` (if any). Silent
|
|
855
|
+
* no-op when the thread has no in-flight round — users clicking Stop on an
|
|
856
|
+
* already-idle thread should not trigger an error bubble. Emits an
|
|
857
|
+
* `unify_aborted` event for UI acknowledgement and a fresh
|
|
858
|
+
* `thread_list_updated` so inflight pills clear immediately.
|
|
859
|
+
*
|
|
860
|
+
* Red line (PM): the `thread_list_updated` event name is preserved; no
|
|
861
|
+
* new per-thread abort signal leaks into `Engine.abort()`'s signature.
|
|
862
|
+
*
|
|
863
|
+
* @param {{ threadId?: string }} msg
|
|
864
|
+
* @returns {{ aborted: string[], all: boolean }}
|
|
865
|
+
*/
|
|
866
|
+
export function handleUnifyAbortThread(msg = {}) {
|
|
867
|
+
const aborted = [];
|
|
868
|
+
const threadId = msg && msg.threadId;
|
|
869
|
+
if (threadId) {
|
|
870
|
+
const ctrl = abortByThread.get(threadId);
|
|
871
|
+
if (ctrl) {
|
|
872
|
+
try { ctrl.abort(); } catch { /* best-effort */ }
|
|
873
|
+
abortByThread.delete(threadId);
|
|
874
|
+
aborted.push(threadId);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
sendUnifyEvent({ type: 'unify_aborted', aborted, all: false });
|
|
878
|
+
sendThreadListUpdate();
|
|
879
|
+
return { aborted, all: false };
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* task-325c: user-initiated abort of ALL in-flight Unify queries.
|
|
884
|
+
*
|
|
885
|
+
* Iterates every registered controller, aborts it, then clears the map.
|
|
886
|
+
* Always emits `unify_aborted` with `all:true` (even when nothing was
|
|
887
|
+
* running) so the UI can confirm the click landed.
|
|
888
|
+
*
|
|
889
|
+
* @returns {{ aborted: string[], all: boolean }}
|
|
890
|
+
*/
|
|
891
|
+
export function handleUnifyAbortAll() {
|
|
892
|
+
const aborted = [];
|
|
893
|
+
for (const [threadId, ctrl] of abortByThread.entries()) {
|
|
894
|
+
try { ctrl.abort(); } catch { /* best-effort */ }
|
|
895
|
+
aborted.push(threadId);
|
|
896
|
+
}
|
|
897
|
+
abortByThread.clear();
|
|
898
|
+
sendUnifyEvent({ type: 'unify_aborted', aborted, all: true });
|
|
899
|
+
sendThreadListUpdate();
|
|
900
|
+
return { aborted, all: true };
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Unified dispatcher bound onto `session.abort({ threadId?, all? })`.
|
|
905
|
+
* Routes to {@link handleUnifyAbortThread} or {@link handleUnifyAbortAll}
|
|
906
|
+
* per input. Kept exported so message-router and tests can call it too.
|
|
907
|
+
*
|
|
908
|
+
* @param {{ threadId?: string, all?: boolean }} [opts]
|
|
909
|
+
*/
|
|
910
|
+
export function abortUnifySession(opts = {}) {
|
|
911
|
+
if (opts && opts.all) return handleUnifyAbortAll();
|
|
912
|
+
if (opts && opts.threadId) return handleUnifyAbortThread({ threadId: opts.threadId });
|
|
913
|
+
// No payload — conservative default: abort nothing, just emit ack so
|
|
914
|
+
// callers see the no-op round-trip. Matches PM "don't accidentally
|
|
915
|
+
// nuke everything on a bare click".
|
|
916
|
+
sendUnifyEvent({ type: 'unify_aborted', aborted: [], all: false });
|
|
917
|
+
return { aborted: [], all: false };
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Test-only: seed / inspect the abort registry without spinning up a
|
|
922
|
+
* full session. Never use from production code — the prod registry is
|
|
923
|
+
* managed by handleUnifyChat's per-query controller lifecycle.
|
|
924
|
+
* @private
|
|
925
|
+
*/
|
|
926
|
+
export function __testSeedAbortController(threadId, ctrl) {
|
|
927
|
+
abortByThread.set(threadId, ctrl);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/** Test-only: returns the set of thread ids currently registered. */
|
|
931
|
+
export function __testGetRegisteredThreadIds() {
|
|
932
|
+
return [...abortByThread.keys()];
|
|
933
|
+
}
|
|
934
|
+
|
|
851
935
|
/**
|
|
852
936
|
* Handle mode switch from the web UI.
|
|
853
937
|
* DEPRECATED (task-297): Unify no longer has chat/work mode distinction.
|