@yeaft/webchat-agent 0.1.727 → 0.1.730

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.
@@ -36,7 +36,7 @@ import { sendToServer, flushMessageBuffer } from './buffer.js';
36
36
  import { handleRestartAgent, handleUpgradeAgent } from './upgrade.js';
37
37
  import { loadMcpServers, updateMcpConfig } from '../mcp.js';
38
38
  import { getLlmConfig, updateLlmConfig, getUnifySettings, updateUnifySettings, getSearchSettings, updateSearchSettings, fetchTavilyUsage } from '../unify/config-api.js';
39
- import { handleUnifyGroupChat, handleUnifyModeSwitch, handleUnifyModelSwitch, resetUnifySession, handleUnifyLoadHistory, handleUnifyAbortThread, handleUnifyAbortAll, handleUnifyAbortTurn, handleUnifyVpSubscribe, handleUnifyVpCreate, handleUnifyVpUpdate, handleUnifyVpDelete, handleUnifyVpRead, handleUnifyFeatureMessage, handleUnifyFetchSummaryHistory, handleUnifyFeatureCrud, handleUnifyListGroups, handleUnifyCreateGroup, handleUnifyRenameGroup, handleUnifyUpdateGroup, handleUnifyArchiveGroup, handleUnifyDeleteGroup, handleUnifyAddMember, handleUnifyRemoveMember, handleUnifySetDefaultVp, handleUnifyDreamTrigger, broadcastLanguageChange } from '../unify/web-bridge.js';
39
+ import { handleUnifyGroupChat, handleUnifyModeSwitch, handleUnifyModelSwitch, resetUnifySession, handleUnifyLoadHistory, handleUnifyAbortThread, handleUnifyAbortAll, handleUnifyAbortTurn, handleUnifyVpSubscribe, handleUnifyVpCreate, handleUnifyVpUpdate, handleUnifyVpDelete, handleUnifyVpRead, handleUnifyFetchSummaryHistory, handleUnifyFeatureCrud, handleUnifyListGroups, handleUnifyCreateGroup, handleUnifyRenameGroup, handleUnifyUpdateGroup, handleUnifyArchiveGroup, handleUnifyDeleteGroup, handleUnifyAddMember, handleUnifyRemoveMember, handleUnifySetDefaultVp, handleUnifyDreamTrigger, broadcastLanguageChange } from '../unify/web-bridge.js';
40
40
 
41
41
  export async function handleMessage(msg) {
42
42
  switch (msg.type) {
@@ -456,13 +456,6 @@ export async function handleMessage(msg) {
456
456
  handleUnifyVpRead(msg);
457
457
  break;
458
458
 
459
- // task-334h (R6 §Δ28 / §Δ31.6): feature-scoped direct message echo.
460
- // Replaces the withdrawn R3 `unify_task_private_chat`. Agent validates,
461
- // stamps msgId + ts, and broadcasts the `feature_message` mirror back.
462
- case 'unify_feature_message':
463
- handleUnifyFeatureMessage(msg);
464
- break;
465
-
466
459
  // R6 G1a — feature summary history + feature affiliation CRUD.
467
460
  case 'unify_fetch_summary_history':
468
461
  await handleUnifyFetchSummaryHistory(msg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.727",
3
+ "version": "0.1.730",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -29,7 +29,6 @@ import { handleVpSubscribe } from './vp/vp-bridge.js';
29
29
  import { createVp, updateVp, deleteVp, readVp, VpCrudError } from './vp/vp-crud.js';
30
30
  import { scanVpLibrary } from './vp/vp-store.js';
31
31
  import { createRouter } from './routing/router.js';
32
- import { handleUnifyFeatureMessage as _handleUnifyFeatureMessage } from './feature-message.js';
33
32
  import {
34
33
  GroupCrudError,
35
34
  createGroupFromSpec,
@@ -637,10 +636,6 @@ export function handleUnifyVpDelete(msg) {
637
636
  }
638
637
  }
639
638
 
640
- export function handleUnifyFeatureMessage(msg) {
641
- _handleUnifyFeatureMessage(msg, sendUnifyEvent);
642
- }
643
-
644
639
  export function handleUnifyVpRead(msg) {
645
640
  const requestId = msg && msg.requestId;
646
641
  const vpId = msg && msg.vpId;
@@ -1,144 +0,0 @@
1
- /**
2
- * feature-message.js — R6 §Δ28 / §Δ31.6 feature-scoped direct messaging.
3
- *
4
- * Replaces the withdrawn R3 `unify_feature_private_chat` event with a simple
5
- * echo-able `feature_message` pair:
6
- *
7
- * inbound (web → agent): `unify_feature_message`
8
- * { type, groupId, featureId, vpId, text, mentions?, replyTo?, requestId? }
9
- * outbound (agent → web): `feature_message`
10
- * { type, groupId, featureId, vpId, msgId, text, mentions, replyTo,
11
- * ts, requestId? }
12
- *
13
- * This module owns only the *wire adapter* — the payload is validated,
14
- * stamped with msgId + ts, and broadcast back so the sender's UI and any
15
- * other connected views converge on the same record. Persistence + feature
16
- * ACL enforcement are deliberately deferred to task-334l (per PM dispatch:
17
- * "user_memory_* 实际 ingestion 归 334l"); the parallel feature-private
18
- * storage hook follows the same phasing.
19
- *
20
- * Invariants:
21
- * • Never throws on the WS hot path — bad payloads reply with a
22
- * `feature_message_rejected` event carrying a stable `code` string for
23
- * UI i18n (mirrors the vp_crud_result contract from 334-ui-g).
24
- * • The outbound event field order and keys are considered wire-frozen
25
- * per R6 §Δ31.6 table; additive fields only in future slices.
26
- */
27
-
28
- import { nextMsgId, isValidVpId } from './groups/ids.js';
29
-
30
- /** Known `reject` codes — kept stable so 334-ui-* can key i18n on them. */
31
- export const FEATURE_MESSAGE_REJECT_CODES = Object.freeze({
32
- MISSING_GROUP_ID: 'missing_group_id',
33
- MISSING_FEATURE_ID: 'missing_feature_id',
34
- MISSING_VP_ID: 'missing_vp_id',
35
- INVALID_VP_ID: 'invalid_vp_id',
36
- EMPTY_TEXT: 'empty_text',
37
- TEXT_TOO_LONG: 'text_too_long',
38
- });
39
-
40
- /** Soft body cap — matches the shard-entry cap used elsewhere in R6 (§Δ26.3). */
41
- export const MAX_TEXT_LENGTH = 16_384;
42
-
43
- /**
44
- * Pure validator. Returns `{ ok: true, payload }` or `{ ok: false, code }`.
45
- * No IO, no clock reads — safe to unit-test in isolation.
46
- *
47
- * @param {any} msg — raw WS message from the web client
48
- */
49
- export function validateFeatureMessage(msg) {
50
- if (!msg || typeof msg !== 'object') {
51
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.MISSING_GROUP_ID };
52
- }
53
- const { groupId, featureId, vpId, text } = msg;
54
- if (!groupId || typeof groupId !== 'string') {
55
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.MISSING_GROUP_ID };
56
- }
57
- if (!featureId || typeof featureId !== 'string') {
58
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.MISSING_FEATURE_ID };
59
- }
60
- if (!vpId || typeof vpId !== 'string') {
61
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.MISSING_VP_ID };
62
- }
63
- // Allow the reserved `user` sentinel as a speaker here — features can have
64
- // human-user messages alongside VP messages. Any other vpId must pass
65
- // the full shape check (rejects `all`, `system`, pure digits, etc.).
66
- if (vpId !== 'user' && !isValidVpId(vpId)) {
67
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.INVALID_VP_ID };
68
- }
69
- if (typeof text !== 'string' || text.length === 0) {
70
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.EMPTY_TEXT };
71
- }
72
- if (text.length > MAX_TEXT_LENGTH) {
73
- return { ok: false, code: FEATURE_MESSAGE_REJECT_CODES.TEXT_TOO_LONG };
74
- }
75
-
76
- const mentions = Array.isArray(msg.mentions)
77
- ? msg.mentions.filter(m => typeof m === 'string' && m.length > 0).slice(0, 32)
78
- : [];
79
- const replyTo = typeof msg.replyTo === 'string' && msg.replyTo.length > 0
80
- ? msg.replyTo
81
- : null;
82
-
83
- return {
84
- ok: true,
85
- payload: { groupId, featureId, vpId, text, mentions, replyTo },
86
- };
87
- }
88
-
89
- /**
90
- * Build the outbound `feature_message` event from a validated payload.
91
- * Exposed separately so tests can snapshot the wire shape without
92
- * needing a live send fn.
93
- *
94
- * @param {{groupId:string,featureId:string,vpId:string,text:string,mentions:string[],replyTo:?string}} payload
95
- * @param {{now?:()=>number, msgId?:()=>string, requestId?:string}} [opts]
96
- */
97
- export function buildFeatureMessageEvent(payload, opts = {}) {
98
- const now = typeof opts.now === 'function' ? opts.now : Date.now;
99
- const mkId = typeof opts.msgId === 'function' ? opts.msgId : nextMsgId;
100
- const evt = {
101
- type: 'feature_message',
102
- groupId: payload.groupId,
103
- featureId: payload.featureId,
104
- vpId: payload.vpId,
105
- msgId: mkId(),
106
- text: payload.text,
107
- mentions: payload.mentions,
108
- replyTo: payload.replyTo,
109
- ts: now(),
110
- };
111
- if (opts.requestId) evt.requestId = opts.requestId;
112
- return evt;
113
- }
114
-
115
- /**
116
- * Build the outbound `feature_message_rejected` event.
117
- * @param {string} code — one of FEATURE_MESSAGE_REJECT_CODES
118
- * @param {any} msg — original inbound msg (for requestId echo)
119
- */
120
- export function buildFeatureMessageRejected(code, msg) {
121
- const evt = { type: 'feature_message_rejected', code };
122
- if (msg && typeof msg.requestId === 'string') evt.requestId = msg.requestId;
123
- if (msg && typeof msg.groupId === 'string') evt.groupId = msg.groupId;
124
- if (msg && typeof msg.featureId === 'string') evt.featureId = msg.featureId;
125
- return evt;
126
- }
127
-
128
- /**
129
- * WS handler entry point. Validates, echoes, never throws.
130
- *
131
- * @param {any} msg
132
- * @param {(event:object)=>void} sendUnifyEvent
133
- * @param {{now?:()=>number, msgId?:()=>string}} [opts] — test seams
134
- */
135
- export function handleUnifyFeatureMessage(msg, sendUnifyEvent, opts = {}) {
136
- const result = validateFeatureMessage(msg);
137
- if (!result.ok) {
138
- try { sendUnifyEvent(buildFeatureMessageRejected(result.code, msg)); } catch { /* best-effort */ }
139
- return;
140
- }
141
- const requestId = msg && typeof msg.requestId === 'string' ? msg.requestId : undefined;
142
- const evt = buildFeatureMessageEvent(result.payload, { ...opts, requestId });
143
- try { sendUnifyEvent(evt); } catch { /* never crash WS pipeline */ }
144
- }