@songsid/agend 2.3.0-beta.2 → 2.3.0-beta.3
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/agent-whats-new.js +2 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.js +10 -5
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/claude-code.d.ts +2 -2
- package/dist/backend/claude-code.js +5 -4
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/types.d.ts +5 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/mcp-tools.js +4 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +8 -3
- package/dist/classic-channel-manager.js +10 -3
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/delivery-outbox.js +5 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-manager.d.ts +68 -3
- package/dist/fleet-manager.js +247 -41
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-traffic.d.ts +38 -0
- package/dist/fleet-traffic.js +96 -0
- package/dist/fleet-traffic.js.map +1 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +13 -5
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +39 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +398 -0
- package/dist/locale.js +6 -4
- package/dist/locale.js.map +1 -1
- package/dist/memory-hogs.d.ts +27 -0
- package/dist/memory-hogs.js +124 -0
- package/dist/memory-hogs.js.map +1 -0
- package/dist/outbound-handlers.d.ts +2 -0
- package/dist/outbound-handlers.js +40 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +88 -0
- package/dist/outbound-schemas.js +50 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +1 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.js +16 -0
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-permissions.js +4 -0
- package/dist/tool-permissions.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/ui/app-effects.js +33 -9
- package/dist/ui/chat-effects.js +62 -4
- package/dist/ui/chat-strings.js +40 -4
- package/dist/ui/chat-thread.js +13 -5
- package/dist/ui/effect-trial-panel.js +19 -16
- package/dist/ui/fleet-canvas-layout.js +111 -0
- package/dist/ui/fleet-canvas.js +489 -0
- package/dist/ui/fleet-org.js +27 -12
- package/dist/ui/fleet-traffic.js +224 -0
- package/dist/ui/panel-chat.js +8 -2
- package/dist/ui/panel-details.js +2 -1
- package/dist/ui/panel-fleet.js +17 -5
- package/dist/ui/panel-settings.js +3 -2
- package/dist/ui/preview.js +3 -2
- package/dist/ui/settings-appearance.js +34 -18
- package/dist/ui/settings-dialogs.js +3 -6
- package/dist/ui/settings-effects.js +4 -3
- package/dist/ui/settings-learn.js +25 -0
- package/dist/ui/settings-model.js +6 -2
- package/dist/ui/settings-mods.js +4 -3
- package/dist/ui/settings-owner-effects.js +8 -8
- package/dist/ui/settings-strings.js +34 -38
- package/dist/ui/shared/app-i18n.js +2 -2
- package/dist/ui/shared/app-prefs.js +1 -1
- package/dist/ui/shared/app-shell.js +23 -1
- package/dist/ui/shared/app-store.js +12 -1
- package/dist/ui/shared/app-stream.js +2 -1
- package/dist/ui/shared/app.css +152 -10
- package/dist/ui/shared/effect-app-runtime.js +1 -1
- package/dist/ui/shared/effect-frame.js +10 -5
- package/dist/ui/shared/effect-geometry.js +24 -9
- package/dist/ui/shared/effect-policy.js +2 -1
- package/dist/ui/shared/effect-registry.js +71 -17
- package/dist/ui/shared/effect-trial-shadow.js +62 -0
- package/dist/ui/shared/effect-trial-stage.js +15 -9
- package/dist/ui/shared/effect-trial.css +40 -0
- package/dist/ui/shared/identity-card.js +5 -2
- package/dist/ui/shared/identity-color.js +3 -3
- package/dist/ui/shared/instance-nav.js +20 -4
- package/dist/ui/shared/panel-view.js +2 -2
- package/dist/ui/shared/view-strings.js +16 -0
- package/dist/view-api.d.ts +21 -0
- package/dist/view-api.js +28 -0
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +5 -6
- package/dist/web-api.js +57 -10
- package/dist/web-api.js.map +1 -1
- package/dist/web-appearance-view.d.ts +10 -0
- package/dist/web-appearance-view.js +77 -8
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-auth.js +1 -1
- package/dist/web-auth.js.map +1 -1
- package/dist/web-effect-trials.d.ts +2 -2
- package/dist/web-effect-trials.js +3 -3
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-guest-access.d.ts +67 -0
- package/dist/web-guest-access.js +126 -0
- package/dist/web-guest-access.js.map +1 -0
- package/dist/web-identity-palette.d.ts +1 -1
- package/dist/web-identity-palette.js +2 -2
- package/dist/web-identity-palette.js.map +1 -1
- package/dist/web-mod-store.d.ts +5 -0
- package/dist/web-mod-store.js +6 -0
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-prefs.d.ts +8 -0
- package/dist/web-prefs.js +9 -0
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +6 -2
- package/dist/web-preview.js +4 -2
- package/dist/web-preview.js.map +1 -1
- package/dist/web-session.d.ts +15 -7
- package/dist/web-session.js +25 -8
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-tools.d.ts +69 -0
- package/dist/web-settings-tools.js +247 -0
- package/dist/web-settings-tools.js.map +1 -0
- package/package.json +1 -1
package/dist/web-api.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { webHumanOrigin } from "./human-delivery-receipts.js";
|
|
2
|
+
import { guestFrameData, guestPollBody, guestRequestOf, guestStatus } from "./web-guest-access.js";
|
|
2
3
|
import { withSpawnHoldReply } from "./spawn-hold-reply.js";
|
|
3
4
|
import { binaryProbe } from "./binary-probe.js";
|
|
4
5
|
import { settingsRequestExecution, settingsWrite, isSettingsReplay } from "./settings-request-capability.js";
|
|
@@ -97,11 +98,27 @@ const safeInstanceSegment = (name) => /^[^\\/\x00]+$/.test(name) && name !== "."
|
|
|
97
98
|
* the eviction the dead entry leaks forever, and without the try/catch a
|
|
98
99
|
* single dead client breaks delivery to every client iterated after it.
|
|
99
100
|
*/
|
|
101
|
+
/** #1920 phase 1b: the open streams that are a guest's, and whose — each event is projected for them (guestFrameData). */
|
|
102
|
+
const streamGuests = new WeakMap();
|
|
100
103
|
export function broadcastSseEvent(clients, event, data, onError, id) {
|
|
101
104
|
const payload = sseFrame(event, data, id);
|
|
102
105
|
const dead = [];
|
|
103
106
|
for (const client of clients) {
|
|
104
107
|
try {
|
|
108
|
+
// An admin's stream gets these bytes; a guest's, the event as projected for its scope now, or nothing (no id: it
|
|
109
|
+
// never replays chat, so a cursor of the admin's stream is not its to hold).
|
|
110
|
+
const guest = streamGuests.get(client);
|
|
111
|
+
if (guest) {
|
|
112
|
+
// The exact session that opened it ended (revoked, expired, rotated away): nothing more, and the stream goes.
|
|
113
|
+
if (!guest.current()) {
|
|
114
|
+
dead.push(client);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const shown = guestFrameData(event, data, guest.scope());
|
|
118
|
+
if (shown !== undefined)
|
|
119
|
+
client.write(sseFrame(event, shown));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
105
122
|
client.write(payload);
|
|
106
123
|
}
|
|
107
124
|
catch (err) {
|
|
@@ -382,7 +399,7 @@ function handleEffectTrials(req, res, url, ctx, path, method) {
|
|
|
382
399
|
css = value;
|
|
383
400
|
}
|
|
384
401
|
catch { /* unavailable is never off */ }
|
|
385
|
-
// CSS
|
|
402
|
+
// CSS is diagnostic for Try; its host-owned shadow shell isolates controls and local paint.
|
|
386
403
|
const actor = Object.freeze({ via: "session", surface: "local", tier: "admin", sessionHash: v.session.idHash, epoch: v.session.handle, person, ownerCss: css });
|
|
387
404
|
return { actor, record: v.session, sessions };
|
|
388
405
|
};
|
|
@@ -978,6 +995,12 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
978
995
|
// that arrived while the stream was silent is not skipped by the cursor this answer hands out (#1251
|
|
979
996
|
// review). The page keeps one entry per boot+id, so what it already loaded from /ui/history is not doubled.
|
|
980
997
|
if (method === "GET" && path === "/ui/poll") {
|
|
998
|
+
// #1920: a guest's poll is projected for its scope (web-guest-access.ts) — the same rule as its stream.
|
|
999
|
+
const guest = guestRequestOf(req);
|
|
1000
|
+
if (guest) {
|
|
1001
|
+
json(res, 200, guestPollBody(ctx.getUiStatus(), guest.scope(), Date.now()));
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
981
1004
|
const history = ctx.webChatHistory;
|
|
982
1005
|
const after = url.searchParams.get("after");
|
|
983
1006
|
const fresh = after === null || after === ""; // a cursor that is not ours in shape still gets nothing
|
|
@@ -1013,9 +1036,15 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
1013
1036
|
});
|
|
1014
1037
|
// #1823 (#1830 review): with the status, the server's clock — now and with every heartbeat — that the page counts a
|
|
1015
1038
|
// poll down by (one write: the frames a connect sends are unchanged in number).
|
|
1016
|
-
|
|
1039
|
+
// #1920: a guest's stream: its projected status now and with each heartbeat, then only what guestFrameData lets
|
|
1040
|
+
// through — no replay, no ticks, prompts or Needs you.
|
|
1041
|
+
const guest = guestRequestOf(req);
|
|
1042
|
+
if (guest)
|
|
1043
|
+
streamGuests.set(res, guest);
|
|
1044
|
+
const statusFrame = () => `event: status\ndata: ${JSON.stringify(guest ? guestStatus(ctx.getUiStatus(), guest.scope()) : ctx.getUiStatus())}\n\n`;
|
|
1045
|
+
res.write(`${statusFrame()}${sseClock()}`);
|
|
1017
1046
|
// An EventSource that reconnects says what it last saw: send what it missed, before anything new.
|
|
1018
|
-
const lastSeen = parseLastEventId(req.headers["last-event-id"]);
|
|
1047
|
+
const lastSeen = guest ? null : parseLastEventId(req.headers["last-event-id"]);
|
|
1019
1048
|
if (lastSeen !== null && ctx.webChatHistory) {
|
|
1020
1049
|
const history = ctx.webChatHistory;
|
|
1021
1050
|
for (const m of history.replayFor(lastSeen))
|
|
@@ -1023,20 +1052,22 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
1023
1052
|
}
|
|
1024
1053
|
// Ticks change messages already sent and carry no cursor: every (re)connect gets where each one is now, so a
|
|
1025
1054
|
// report that fell into a gap is not lost until a reload (#1253 review). No id: it is not a message.
|
|
1026
|
-
if (ctx.webChatHistory)
|
|
1055
|
+
if (!guest && ctx.webChatHistory)
|
|
1027
1056
|
res.write(`event: deliveries\ndata: ${JSON.stringify(ctx.webChatHistory.deliveries())}\n\n`);
|
|
1028
1057
|
// The same for the fleet prompts (C4): one posted, answered or expired during a gap is caught up here.
|
|
1029
|
-
if (ctx.listWebPrompts)
|
|
1058
|
+
if (!guest && ctx.listWebPrompts)
|
|
1030
1059
|
res.write(`event: prompts\ndata: ${JSON.stringify(ctx.listWebPrompts())}\n\n`);
|
|
1031
1060
|
// #1386: and "Needs you" as it is now; changes follow as `needs` events.
|
|
1032
|
-
if (ctx.needsYouItems)
|
|
1061
|
+
if (!guest && ctx.needsYouItems)
|
|
1033
1062
|
res.write(`event: needs\ndata: ${JSON.stringify({ items: ctx.needsYouItems() })}\n\n`);
|
|
1034
1063
|
ctx.sseClients.add(res);
|
|
1035
1064
|
const interval = setInterval(() => {
|
|
1036
1065
|
// A stream authorized once must not outlive the authorization. Re-checked
|
|
1037
1066
|
// without counting as activity, or an open tab would keep an idle session
|
|
1038
1067
|
// alive forever; a revoked, expired or rotated-away session ends here.
|
|
1039
|
-
|
|
1068
|
+
// #2049 review: a guest's stream also needs the exact session that opened it — another cookie on the same request
|
|
1069
|
+
// still authenticating does not keep a revoked device's stream (with its scope) alive.
|
|
1070
|
+
if (!isWebRequestAuthorized(req, url, ctx.webToken, ctx.webSessions, { touch: false }) || (guest && !guest.current())) {
|
|
1040
1071
|
// Close the connection too, not just the response: an ended response leaves the socket idle in
|
|
1041
1072
|
// keep-alive, still held open by whoever's session just ended.
|
|
1042
1073
|
const socket = req.socket;
|
|
@@ -1049,7 +1080,7 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
1049
1080
|
}
|
|
1050
1081
|
try {
|
|
1051
1082
|
// Every open dashboard tab, every 10 s: the status of every instance, serialized on the fleet's loop (#1235).
|
|
1052
|
-
res.write(measureSyncWork("web.sseStatus",
|
|
1083
|
+
res.write(measureSyncWork("web.sseStatus", statusFrame) + sseClock());
|
|
1053
1084
|
}
|
|
1054
1085
|
catch {
|
|
1055
1086
|
cleanup();
|
|
@@ -1138,6 +1169,16 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
1138
1169
|
const fileMatch = path.match(/^\/ui\/file\/([^/]+)$/);
|
|
1139
1170
|
if (method === "GET" && fileMatch) {
|
|
1140
1171
|
const id = fileMatch[1];
|
|
1172
|
+
// #1920: a guest gets a file only when its stored instance is in scope — "no such file" otherwise, like an unknown id
|
|
1173
|
+
// (an id from another instance's chat is useless).
|
|
1174
|
+
const guest = guestRequestOf(req);
|
|
1175
|
+
if (guest) {
|
|
1176
|
+
const served = isFileId(id) ? ctx.webFiles?.servedFile?.(id) ?? null : null;
|
|
1177
|
+
if (!served || !guest.scope().has(served.instance)) {
|
|
1178
|
+
json(res, 404, { error: "No such file" });
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1141
1182
|
// #1589: audio and video, played in the page — one byte range at a time (206), by id only, never a whole video in
|
|
1142
1183
|
// memory. Every other type is answered exactly as before.
|
|
1143
1184
|
const media = isFileId(id) ? ctx.webFiles?.mediaOf?.(id) ?? null : null;
|
|
@@ -2131,6 +2172,12 @@ export function handleWebRequest(req, res, url, ctx) {
|
|
|
2131
2172
|
json(res, 200, ctx.orgChart?.() ?? { general: [], teams: [], instances: {} });
|
|
2132
2173
|
return true;
|
|
2133
2174
|
}
|
|
2175
|
+
// #1918: the org canvas's traffic on opening, and the public link's (which has no stream) on its poll cadence. The
|
|
2176
|
+
// fleet works it out at most once every two seconds and caps it, whoever asks how often.
|
|
2177
|
+
if (method === "GET" && path === "/ui/traffic") {
|
|
2178
|
+
json(res, 200, ctx.trafficSnapshot?.() ?? { now: new Date().toISOString(), items: [] });
|
|
2179
|
+
return true;
|
|
2180
|
+
}
|
|
2134
2181
|
if (method === "GET" && path === "/ui/teams") {
|
|
2135
2182
|
const teams = ctx.fleetConfig?.teams ?? {};
|
|
2136
2183
|
json(res, 200, { teams });
|
|
@@ -2389,8 +2436,8 @@ function handleSendMessage(req, res, ctx) {
|
|
|
2389
2436
|
&& !ctx.isClassicInstance?.(instance) && syncAdapter && groupId && topicId != null;
|
|
2390
2437
|
// Add no runtime credentials or local attachment paths to the display copy.
|
|
2391
2438
|
const preview = webEchoPreview(message, files.map(f => f.name));
|
|
2392
|
-
// ClassicBot echo (#1320 part B): same ordering lane,
|
|
2393
|
-
//
|
|
2439
|
+
// ClassicBot echo (#1320 part B): same ordering lane, each room's setting (#2054: on unless it says false, or
|
|
2440
|
+
// the fleet-wide switch is off for a room that is unset) resolved at send time inside sendClassicWebEcho.
|
|
2394
2441
|
const canClassicEcho = ctx.isClassicInstance?.(instance) === true && !!ctx.sendClassicWebEcho;
|
|
2395
2442
|
const settleClassicEcho = canClassicEcho ? ctx.reserveWebChannelEcho?.(instance, async () => {
|
|
2396
2443
|
await ctx.sendClassicWebEcho(instance, formatWebChannelEcho(person.name, preview, t("web.echo_full_text")), person.name);
|