@cat-factory/app 0.46.5 → 0.46.7
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.
|
@@ -49,6 +49,13 @@ export function createApiClient(): WretchInstance {
|
|
|
49
49
|
const apiBase = useRuntimeConfig().public.apiBase
|
|
50
50
|
return wretch(apiBase).middlewares([
|
|
51
51
|
(next) => async (url, opts) => {
|
|
52
|
+
// Tag every request with this tab's stable connection id (matched to the `?cid=` on
|
|
53
|
+
// the realtime WebSocket) so the backend can skip echoing a board mutation's coarse
|
|
54
|
+
// event back to the connection that caused it — see `utils/connectionId.ts`.
|
|
55
|
+
opts.headers = {
|
|
56
|
+
...(opts.headers as Record<string, string> | undefined),
|
|
57
|
+
'X-Connection-Id': connectionId(),
|
|
58
|
+
}
|
|
52
59
|
const token = useAuthStore().token
|
|
53
60
|
if (token) {
|
|
54
61
|
opts.headers = {
|
|
@@ -119,7 +119,11 @@ export function useWorkspaceStream() {
|
|
|
119
119
|
// A workspace switch (or stop()) may have happened while awaiting the mint.
|
|
120
120
|
if (stopped || workspace.workspaceId !== workspaceId) return
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
// Carry this tab's stable connection id so the backend can suppress echoing a board
|
|
123
|
+
// mutation's coarse event back to the connection that caused it (same id the api
|
|
124
|
+
// client sends as `X-Connection-Id`) — see `utils/connectionId.ts`.
|
|
125
|
+
const cid = `cid=${encodeURIComponent(connectionId())}`
|
|
126
|
+
const query = ticket ? `?ticket=${encodeURIComponent(ticket)}&${cid}` : `?${cid}`
|
|
123
127
|
socket = new WebSocket(`${wsBase}/workspaces/${workspaceId}/events${query}`)
|
|
124
128
|
|
|
125
129
|
socket.onopen = () => {
|
package/app/stores/ui.ts
CHANGED
|
@@ -411,7 +411,7 @@ export const useUiStore = defineStore('ui', () => {
|
|
|
411
411
|
// panel opened outside the hubs never grows a dead Back control, and so switching from
|
|
412
412
|
// one hub's panel to the other's clears the stale marker.
|
|
413
413
|
function resetHubReturn() {
|
|
414
|
-
|
|
414
|
+
cameFromIntegrations.value = false
|
|
415
415
|
cameFromPersonal.value = false
|
|
416
416
|
}
|
|
417
417
|
function openIntegrations() {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable per-tab connection id, generated once on first use. It rides on every REST
|
|
3
|
+
* request (the `X-Connection-Id` header, added in the api client) AND on the realtime
|
|
4
|
+
* WebSocket connect (`?cid=`), so the backend can recognise the connection that caused a
|
|
5
|
+
* board mutation and skip echoing the resulting coarse `board` event back to it.
|
|
6
|
+
*
|
|
7
|
+
* Without this, a client consumes the WebSocket event for its OWN move and runs a
|
|
8
|
+
* debounced full board refresh; a snapshot fetched mid-flight (between two rapid drags)
|
|
9
|
+
* carries a stale position, so the block snaps back to where it was after the previous
|
|
10
|
+
* move. Suppressing the self-echo leaves the originating client on its optimistic state +
|
|
11
|
+
* its own REST response (already the freshest), while other clients still refresh.
|
|
12
|
+
*/
|
|
13
|
+
let cached: string | null = null
|
|
14
|
+
|
|
15
|
+
export function connectionId(): string {
|
|
16
|
+
if (cached) return cached
|
|
17
|
+
cached =
|
|
18
|
+
globalThis.crypto?.randomUUID?.() ??
|
|
19
|
+
`cid-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`
|
|
20
|
+
return cached
|
|
21
|
+
}
|
package/nuxt.config.ts
CHANGED
|
@@ -81,6 +81,24 @@ export default defineNuxtConfig({
|
|
|
81
81
|
join(layerDir, 'app/assets/css/main.css'),
|
|
82
82
|
],
|
|
83
83
|
|
|
84
|
+
// Force Vite to pre-bundle `fast-querystring` (a CommonJS dep reached via
|
|
85
|
+
// @toad-contracts/frontend-http-client). Left un-optimized, Vite serves its raw CJS
|
|
86
|
+
// from @fs where cjs-module-lexer can't see the named `stringify` export (the module
|
|
87
|
+
// uses a `module.exports = x; module.exports.stringify = …` reassignment), so the SPA
|
|
88
|
+
// throws at runtime:
|
|
89
|
+
// SyntaxError: … fast-querystring/lib/index.js does not provide an export named 'stringify'
|
|
90
|
+
// Pre-bundling makes esbuild emit an ESM wrapper with proper CJS interop.
|
|
91
|
+
//
|
|
92
|
+
// This config is resolved from the CONSUMER app's root (the deployment that `extends`
|
|
93
|
+
// this layer), where — under pnpm's strict layout — only this layer (`@cat-factory/app`)
|
|
94
|
+
// is hoisted; `frontend-http-client`/`fast-querystring` are not. So anchor the nested
|
|
95
|
+
// `a > b > c` specifier at `@cat-factory/app` and let Vite resolve each hop from there.
|
|
96
|
+
vite: {
|
|
97
|
+
optimizeDeps: {
|
|
98
|
+
include: ['@cat-factory/app > @toad-contracts/frontend-http-client > fast-querystring'],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
|
|
84
102
|
app: {
|
|
85
103
|
head: {
|
|
86
104
|
title: 'Agent Architecture Board',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.46.
|
|
3
|
+
"version": "0.46.7",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|