@coffer-org/plugin-webchat 7.2.0 → 7.3.0
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/{ChatWidget-BIPLpTMp.js → ChatWidget-DocoFt8q.js} +12 -1
- package/dist/runtime/format.js +9 -1
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/refresh-tool.d.ts +2 -0
- package/dist/runtime/refresh-tool.js +49 -0
- package/dist/runtime/send.js +2 -0
- package/dist/web.js +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as __fedReact from "react";
|
|
2
|
-
import { Button, Dialog, DialogContent, Icon, MarkdownView, fileSizeLabel, uploadFile, useMinWidth } from "@coffer-org/web-ui";
|
|
2
|
+
import { Button, Dialog, DialogContent, Icon, MarkdownView, fileSizeLabel, recordGone, refreshData, uploadFile, useMinWidth } from "@coffer-org/web-ui";
|
|
3
3
|
import { createContext, createElement, forwardRef, memo, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { useLocation } from "react-router-dom";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1051,6 +1051,12 @@ async function openChannel(convId, handlers, signal) {
|
|
|
1051
1051
|
parentMsgId: String(data["parentMsgId"] ?? ""),
|
|
1052
1052
|
suggestions: Array.isArray(data["suggestions"]) ? data["suggestions"] : null
|
|
1053
1053
|
});
|
|
1054
|
+
else if (frame.event === "refresh") handlers.onRefresh({
|
|
1055
|
+
...typeof data["library"] === "string" ? { library: data["library"] } : {},
|
|
1056
|
+
...typeof data["shelf"] === "string" ? { shelf: data["shelf"] } : {},
|
|
1057
|
+
...typeof data["id"] === "string" ? { id: data["id"] } : {},
|
|
1058
|
+
...data["gone"] === true ? { gone: true } : {}
|
|
1059
|
+
});
|
|
1054
1060
|
else if (frame.event === "error") handlers.onError({
|
|
1055
1061
|
message: data["message"] ?? null,
|
|
1056
1062
|
parentMsgId: typeof data["parentMsgId"] === "string" ? data["parentMsgId"] : null
|
|
@@ -1245,6 +1251,11 @@ function useChat() {
|
|
|
1245
1251
|
kind: "done",
|
|
1246
1252
|
data
|
|
1247
1253
|
}),
|
|
1254
|
+
onRefresh: ({ gone, ...scope }) => {
|
|
1255
|
+
if (cancelled) return;
|
|
1256
|
+
if (gone) recordGone(scope);
|
|
1257
|
+
else refreshData(scope);
|
|
1258
|
+
},
|
|
1248
1259
|
onError: (data) => dispatch({
|
|
1249
1260
|
kind: "error",
|
|
1250
1261
|
data
|
package/dist/runtime/format.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { frontendInstructions } from '@coffer-org/server/frontend-agent';
|
|
2
2
|
import { NEUTRAL_FORMAT } from '@coffer-org/markdown';
|
|
3
|
+
const LIVE_PAGE = [
|
|
4
|
+
'You are answering inside the app, in a panel over a page the person is reading.',
|
|
5
|
+
'That page does not reload itself. After you create, update, delete or restore a record,',
|
|
6
|
+
'call `refresh_open_page` — naming the record when you know which one — so what they see matches',
|
|
7
|
+
'what you just told them. If you DELETED the record, pass `deleted: true` with it, so the page',
|
|
8
|
+
'showing it returns to the list instead of sitting on something that is no longer there.',
|
|
9
|
+
'Skip the call when you only read.',
|
|
10
|
+
].join(' ');
|
|
3
11
|
export async function webChannelSystem() {
|
|
4
12
|
const site = await frontendInstructions('');
|
|
5
|
-
return [NEUTRAL_FORMAT, site].filter(Boolean).join('\n\n');
|
|
13
|
+
return [NEUTRAL_FORMAT, site, LIVE_PAGE].filter(Boolean).join('\n\n');
|
|
6
14
|
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PluginHooks } from '@coffer-org/server/plugin-hooks';
|
|
2
2
|
export type { ThreadSummary, HistoryMsg } from './actions.ts';
|
|
3
3
|
export { makeStreamingConnector } from './connector.ts';
|
|
4
|
+
export { makeRefreshTool } from './refresh-tool.ts';
|
|
4
5
|
export { getConversation as getSelection, setConversation as setSelection, } from '@coffer-org/server/conversation-store';
|
|
5
6
|
export { sendAction, pageContext } from './send.ts';
|
|
6
7
|
export declare const serverHooks: PluginHooks;
|
package/dist/runtime/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { initFanout, teardownFanout } from "./channel-registry.js";
|
|
|
6
6
|
const THREAD_TTL_MS = Number(process.env['WEBCHAT_THREAD_TTL_MS'] ?? 30 * 86_400_000);
|
|
7
7
|
let unregisterConnector;
|
|
8
8
|
export { makeStreamingConnector } from "./connector.js";
|
|
9
|
+
export { makeRefreshTool } from "./refresh-tool.js";
|
|
9
10
|
export { getConversation as getSelection, setConversation as setSelection, } from '@coffer-org/server/conversation-store';
|
|
10
11
|
export { sendAction, pageContext } from "./send.js";
|
|
11
12
|
export const serverHooks = {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getLogger } from '@coffer-org/sdk/logger';
|
|
2
|
+
import { broadcast, subscriberCount } from "./channel-registry.js";
|
|
3
|
+
const log = getLogger('webchat');
|
|
4
|
+
function str(value) {
|
|
5
|
+
return typeof value === 'string' && value.trim() ? value.trim() : '';
|
|
6
|
+
}
|
|
7
|
+
export function makeRefreshTool(conversationId) {
|
|
8
|
+
return {
|
|
9
|
+
tools: [
|
|
10
|
+
{
|
|
11
|
+
name: 'mcp__coffer__refresh_open_page',
|
|
12
|
+
description: 'Reload the data on the page the user currently has open in the browser. ' +
|
|
13
|
+
'Call it right after you create, update, delete or restore a record, so what they see ' +
|
|
14
|
+
'matches what you just changed — otherwise the page keeps showing the values it loaded ' +
|
|
15
|
+
'before your edit. Name the record you touched when you know it. ' +
|
|
16
|
+
'When you DELETED or trashed the record, pass deleted: true with its library, shelf and ' +
|
|
17
|
+
'id: the page showing it then returns to the list instead of sitting on a record that is ' +
|
|
18
|
+
'no longer there. ' +
|
|
19
|
+
'It is a display-only call: it changes no data, costs the user nothing, and is safe to ' +
|
|
20
|
+
'repeat. Do not call it when you only READ records.',
|
|
21
|
+
inputSchema: {
|
|
22
|
+
library: { type: 'string', description: 'Library of the record you changed, e.g. health' },
|
|
23
|
+
shelf: { type: 'string', description: 'Shelf of the record you changed, e.g. drug' },
|
|
24
|
+
id: { type: 'string', description: 'Id of the record you changed' },
|
|
25
|
+
deleted: {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
description: 'True when you deleted or trashed that record, so the page leaves it',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
handler: async (args) => {
|
|
31
|
+
const library = str(args['library']);
|
|
32
|
+
const shelf = str(args['shelf']);
|
|
33
|
+
const id = str(args['id']);
|
|
34
|
+
const gone = args['deleted'] === true && Boolean(id);
|
|
35
|
+
const scope = {
|
|
36
|
+
...(library ? { library } : {}),
|
|
37
|
+
...(shelf ? { shelf } : {}),
|
|
38
|
+
...(id ? { id } : {}),
|
|
39
|
+
...(gone ? { gone: true } : {}),
|
|
40
|
+
};
|
|
41
|
+
broadcast(conversationId, 'refresh', scope);
|
|
42
|
+
const viewers = subscriberCount(conversationId);
|
|
43
|
+
log.info(`refresh_open_page ${JSON.stringify(scope)} → ${viewers} viewer(s) on ${conversationId}`);
|
|
44
|
+
return { requested: true, gone, viewers };
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
package/dist/runtime/send.js
CHANGED
|
@@ -7,6 +7,7 @@ import { getConversation, setConversation, readAndTouchConversation, } from '@co
|
|
|
7
7
|
import { mayWrite, mayRead } from '@coffer-org/server/orchestrator';
|
|
8
8
|
import { policy } from "./config.js";
|
|
9
9
|
import { makeStreamingConnector } from "./connector.js";
|
|
10
|
+
import { makeRefreshTool } from "./refresh-tool.js";
|
|
10
11
|
import { broadcast, initFanout } from "./channel-registry.js";
|
|
11
12
|
import { webChannelSystem } from "./format.js";
|
|
12
13
|
import { loadReasoningDisplay } from "./settings.js";
|
|
@@ -87,6 +88,7 @@ export async function sendAction(body, caller, deps = {}) {
|
|
|
87
88
|
replyToMsgId: replyTo,
|
|
88
89
|
},
|
|
89
90
|
capabilities: CAPABILITIES,
|
|
91
|
+
toolProvider: makeRefreshTool(conversationId),
|
|
90
92
|
systemPrompt: { channel: [await webChannelSystem()] },
|
|
91
93
|
...(turnContext.length ? { turnContext } : {}),
|
|
92
94
|
...(agentId ? { agentId } : {}),
|
package/dist/web.js
CHANGED
|
@@ -11,7 +11,7 @@ import { definePluginUI } from "@coffer-org/web-ui";
|
|
|
11
11
|
var ui_default = definePluginUI({ slots: [{
|
|
12
12
|
slot: "overlay",
|
|
13
13
|
id: "webchat",
|
|
14
|
-
load: () => import("./ChatWidget-
|
|
14
|
+
load: () => import("./ChatWidget-DocoFt8q.js")
|
|
15
15
|
}] });
|
|
16
16
|
//#endregion
|
|
17
17
|
export { ui_default as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffer-org/plugin-webchat",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@coffer-org/markdown": "^7.4.0",
|
|
31
31
|
"@coffer-org/sdk": "^7.4.1",
|
|
32
|
-
"@coffer-org/server": "^7.
|
|
32
|
+
"@coffer-org/server": "^7.6.0",
|
|
33
33
|
"lucide-react": "^1.17.0"
|
|
34
34
|
},
|
|
35
35
|
"coffer": {
|