@agent-native/core 0.14.4 → 0.14.5
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/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +13 -2
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +18 -5
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +8 -45
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareButton.spec.js +13 -31
- package/dist/client/sharing/ShareButton.spec.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +35 -2
- package/dist/server/ssr-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-data-builder.d.ts","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEhE,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,4BAA4B;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAyCvD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC;IACD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,EACF;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACpC;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,IAAI,CA2HP;
|
|
1
|
+
{"version":3,"file":"thread-data-builder.d.ts","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEhE,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,4BAA4B;IACpC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,KAAK,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAyCvD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC;IACD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,MAAM,EACF;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACpC;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,IAAI,CA2HP;AAgHD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,GAAG,EACjB,YAAY,EAAE,GAAG,OAmDlB;AAqFD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,GAAG;IACF,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAcA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,GAAG,GAAG,CAoBtE;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,gBAAgB,GAC7B,GAAG,CA+BL;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAyBA"}
|
|
@@ -176,7 +176,7 @@ function isTerminalAssistantStatus(status) {
|
|
|
176
176
|
return type === "complete" || type === "incomplete";
|
|
177
177
|
}
|
|
178
178
|
function normalizeAttachmentIdentity(attachments) {
|
|
179
|
-
if (!Array.isArray(attachments))
|
|
179
|
+
if (!Array.isArray(attachments) || attachments.length === 0)
|
|
180
180
|
return undefined;
|
|
181
181
|
return attachments.map((att) => ({
|
|
182
182
|
type: att?.type,
|
|
@@ -192,11 +192,22 @@ function messageIdentityKeys(message) {
|
|
|
192
192
|
const runId = getMessageRunId(message);
|
|
193
193
|
if (runId)
|
|
194
194
|
keys.push(`run:${runId}`);
|
|
195
|
+
// Normalize attachments through `normalizeAttachmentIdentity` so an
|
|
196
|
+
// explicit empty `[]` (assistant-ui's default for messages with no
|
|
197
|
+
// attachments) and an omitted/undefined `attachments` field hash to the
|
|
198
|
+
// same fingerprint. Without this, every user message ended up duplicated
|
|
199
|
+
// in `chat_threads`: one copy from `saveThreadData` (runtime export
|
|
200
|
+
// includes `attachments: []`) and one from `persistSubmittedUserMessage`
|
|
201
|
+
// → `buildUserMessage` (omits the field entirely). The merge couldn't
|
|
202
|
+
// dedupe them because their fingerprints differed by exactly one
|
|
203
|
+
// `[]` vs `undefined`. (Repro on slides prod: every user turn produced
|
|
204
|
+
// a `client_user → assistant → server_user` triple instead of a
|
|
205
|
+
// `user → assistant` pair.)
|
|
195
206
|
try {
|
|
196
207
|
keys.push(`fingerprint:${JSON.stringify({
|
|
197
208
|
role: message?.role,
|
|
198
209
|
content: message?.content,
|
|
199
|
-
attachments: message?.attachments,
|
|
210
|
+
attachments: normalizeAttachmentIdentity(message?.attachments),
|
|
200
211
|
})}`);
|
|
201
212
|
}
|
|
202
213
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-data-builder.js","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"AAmBA,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAE3C,SAAS,2BAA2B,CAAC,KAIpC;IACC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACtC,OAAO,CACL,KAAK,CAAC,WAAW,KAAK,IAAI;QAC1B,IAAI,KAAK,uBAAuB;QAChC,IAAI,KAAK,yBAAyB;QAClC,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,SAAS;QAClB,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,cAAc;QACvB,IAAI,KAAK,8BAA8B;QACvC,IAAI,KAAK,kBAAkB;QAC3B,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvB,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC7B,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/B,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC7B,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACvC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CACpB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAkB,EAClB,KAAc,EACd,UAAwC,EAAE;IAW1C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,QAAQ,GAKD,IAAI,CAAC;IAChB,IAAI,mCAAmC,GAAG,KAAK,CAAC;IAEhD,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACnB,eAAe,GAAG,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,MAAM,EAAE,eAAe,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAA2B,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW;gBACjB,UAAU;gBACV,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,SAAS;gBACjC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC9B,IAAI;aACL,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxB,IACE,IAAI,CAAC,IAAI,KAAK,WAAW;oBACzB,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI;oBAC5B,IAAI,CAAC,MAAM,KAAK,SAAS,EACzB,CAAC;oBACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;oBACjC,MAAM;gBACR,CAAC;YACH,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,wEAAwE;YACxE,wEAAwE;YACxE,IAAI,OAAO,CAAC,4BAA4B,EAAE,CAAC;gBACzC,mCAAmC,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACnC,IAAI,OAAO,CAAC,4BAA4B,EAAE,CAAC;gBACzC,mCAAmC,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IACE,OAAO,CAAC,4BAA4B;gBACpC,2BAA2B,CAAC,KAAK,CAAC,EAClC,CAAC;gBACD,mCAAmC,GAAG,IAAI,CAAC;gBAC3C,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC3D,SAAS;YACX,CAAC;YACD,QAAQ,GAAG;gBACT,OAAO,EAAE,KAAK,CAAC,KAAK;gBACpB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1D,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC;YACF,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YACvE,SAAS;QACX,CAAC;QAED,wDAAwD;IAC1D,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,mCAAmC;QAAE,OAAO,IAAI,CAAC;IAE7E,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,IAAI,KAAK;QAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;IAClC,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,MAAM,GAAG;YAChB,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5B;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,UAAU,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,MAAM,EAAE,QAAQ;YACd,CAAC,CAAC,EAAE,IAAI,EAAE,YAAqB,EAAE,MAAM,EAAE,OAAgB,EAAE;YAC3D,CAAC,CAAC,EAAE,IAAI,EAAE,UAAmB,EAAE,MAAM,EAAE,MAAe,EAAE;QAC1D,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAU;IAClC,OAAO,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,OAAY;IACnC,MAAM,IAAI,GAAG,OAAO,EAAE,QAAQ,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC;IACxE,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IACxD,OAAO,OAAO,IAAI,IAAI,IAAI,OAAO,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,OAAgB;IACnC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACX,MAAM,CACL,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CACtE;SACA,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAe;IAChD,MAAM,IAAI,GAAI,MAAyC,EAAE,IAAI,CAAC;IAC9D,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,YAAY,CAAC;AACtD,CAAC;AAED,SAAS,2BAA2B,CAAC,WAAoB;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAC;IAClD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;QACpC,IAAI,EAAE,GAAG,EAAE,IAAI;QACf,IAAI,EAAE,GAAG,EAAE,IAAI;QACf,WAAW,EAAE,GAAG,EAAE,WAAW;KAC9B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAY;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,OAAO,EAAE,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IAErC,IAAI,CAAC;QACH,IAAI,CAAC,IAAI,CACP,eAAe,IAAI,CAAC,SAAS,CAAC;YAC5B,IAAI,EAAE,OAAO,EAAE,IAAI;YACnB,OAAO,EAAE,OAAO,EAAE,OAAO;YACzB,WAAW,EAAE,OAAO,EAAE,WAAW;SAClC,CAAC,EAAE,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;IACD,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CACP,oBAAoB,IAAI,CAAC,SAAS,CAAC;gBACjC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,WAAW,EAAE,2BAA2B,CAAC,OAAO,CAAC,WAAW,CAAC;aAC9D,CAAC,EAAE,CACL,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,CAAM,EAAE,CAAM;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,wBAAwB,CAAC,aAAkB,EAAE,aAAkB;IACtE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACjD,IACE,QAAQ,EAAE,IAAI,KAAK,WAAW;QAC9B,QAAQ,EAAE,IAAI,KAAK,WAAW;QAC9B,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC3C,CAAC,yBAAyB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC5C,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CAC1C,YAAiB,EACjB,YAAiB;IAEjB,MAAM,MAAM,GACV,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,IACE,YAAY;QACZ,OAAO,YAAY,KAAK,QAAQ;QAChC,YAAY,CAAC,cAAc,KAAK,SAAS;QACzC,MAAM,CAAC,cAAc,KAAK,SAAS,EACnC,CAAC;QACD,MAAM,CAAC,cAAc,GAAG,YAAY,CAAC,cAAc,CAAC;IACtD,CAAC;IAED,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC;QAC5D,CAAC,CAAC,YAAY,CAAC,QAAQ;QACvB,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QACrD,CAAC,CAAC,MAAM,CAAC,QAAQ;QACjB,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,CAAC,gBAAgB,IAAI,CAAC,gBAAgB;QAAE,OAAO,MAAM,CAAC;IAE1D,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAC1C,CAAC,KAAU,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CACtE,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,YAAY,GAAU,EAAE,CAAC;IAE/B,KAAK,MAAM,aAAa,IAAI,gBAAgB,EAAE,CAAC;QAC7C,MAAM,YAAY,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;QAC1E,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAC7C,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CACxE,CAAC;QAEF,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QAED,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAChC,YAAY,CAAC,IAAI,CACf,wBAAwB,CAAC,aAAa,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC,CACzE,CAAC;IACJ,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,CAAC,QAAQ,GAAG,YAAY,CAAC;IAC/B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,4BAA4B,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACtB,qDAAqD,CACtD,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,MAAM,SAAS,GAAG,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,SAAS,CAAC,MAAM,IAAI,2BAA2B;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,2BAA2B,CAAC;IAC/D,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,2BAA2B,CAAC,mCAAmC,2BAA2B,CAAC,cAAc,EAAE,gBAAgB,OAAO,CAAC,cAAc,EAAE,mDAAmD,CAAC;AACtO,CAAC;AAED,SAAS,sBAAsB,CAC7B,GAAwB,EACxB,IAAY;IAEZ,MAAM,KAAK,GAAG;QACZ,SAAS,yBAAyB,CAAC,GAAG,CAAC,IAAI,IAAI,YAAY,CAAC,GAAG;QAC/D,GAAG,CAAC,WAAW;YACb,CAAC,CAAC,gBAAgB,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG;YAC/D,CAAC,CAAC,IAAI;QACR,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;KAClE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,eAAe,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,wBAAwB,CAAC,IAAI,CAAC,iBAAiB,CAAC;AAC7F,CAAC;AAED,SAAS,sBAAsB,CAC7B,WAA8C,EAC9C,KAAyB;IAEzB,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAClB,MAAM,EAAE,GAAG,UAAU,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,eAAe,KAAK,EAAE,CAAC;QAC/D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;aAC9C,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACb,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,QAAQ,EAAE,GAAG,CAAC,WAAW;wBACzB,QAAQ,EAAE,GAAG,CAAC,IAAI;qBACnB;iBACF;aACF,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO;gBACL,EAAE;gBACF,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC5B,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;iBAC9D;aACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAKhC;IAQC,MAAM,WAAW,GAAG,sBAAsB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzE,OAAO;QACL,EAAE,EAAE,eAAe,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;QAC7C,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE;QACvC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,QAAQ,EAAE;YACR,MAAM,EAAE;gBACN,cAAc,EAAE,IAAI,CAAC,KAAK;aAC3B;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAS,EAAE,OAAoB;IAC/D,MAAM,QAAQ,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,QAAQ,CAAC,QAAQ,GAAG,EAAE,CAAC;IAE9D,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;QAChE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC;IAC/D,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,QAAQ,GACZ,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,0BAA0B,CACjC,WAAgB,EAChB,YAA8B;IAE9B,MAAM,WAAW,GAAG,WAAW,EAAE,OAAO,CAAC;IACzC,IAAI,qBAAqB,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAEpE,MAAM,UAAU,GAAG,WAAW,EAAE,MAAM,CAAC;IACvC,IAAI,UAAU,IAAI,CAAC,yBAAyB,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,yBAAyB,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,OAAO,CAAC,QAAQ,IAAI,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAS,EACT,YAA8B;IAE9B,MAAM,QAAQ,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,QAAQ,CAAC,QAAQ,GAAG,EAAE,CAAC;IAE9D,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,EAAE,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC;IAE/D,IACE,QAAQ,KAAK,WAAW;QACxB,0BAA0B,CAAC,OAAO,EAAE,YAAY,CAAC,EACjD,CAAC;QACD,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS;YACtC,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE;YACzC,CAAC,CAAC,YAAY,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,QAAQ,GACZ,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC1B,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAChE,EAAE,EAAE,IAAI,IAAI,CAAC;YACjB,CAAC,CAAC,IAAI,CAAC;QACX,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAS;IAIzC,MAAM,IAAI,GAAG,IAAI,EAAE,QAAQ,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAC3C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAEpC,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,6FAA6F;QAC7F,MAAM,GAAG,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC1C,CAAC,CAAC,GAAG,CAAC,OAAO;iBACR,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBACrC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBACvB,IAAI,CAAC,GAAG,CAAC;YACd,CAAC,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC/B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,EAAE,CAAC;QACT,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK;gBAAE,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC","sourcesContent":["import type { AgentChatAttachment, RunEvent } from \"./types.js\";\n\ninterface ContentPart {\n type: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n argsText?: string;\n args?: Record<string, string>;\n result?: string;\n}\n\ninterface BuildAssistantMessageOptions {\n suppressInternalContinuation?: boolean;\n}\n\ntype AssistantMessage = NonNullable<ReturnType<typeof buildAssistantMessage>>;\ntype UserMessage = ReturnType<typeof buildUserMessage>;\n\nconst MAX_STORED_ATTACHMENT_CHARS = 60_000;\n\nfunction isInternalContinuationError(event: {\n error: string;\n errorCode?: string;\n recoverable?: boolean;\n}): boolean {\n const code = String(event.errorCode ?? \"\").toLowerCase();\n const msg = event.error.toLowerCase();\n return (\n event.recoverable === true ||\n code === \"builder_gateway_error\" ||\n code === \"builder_gateway_timeout\" ||\n code === \"stale_run\" ||\n code === \"timeout\" ||\n code === \"timeout_error\" ||\n code === \"http_408\" ||\n code === \"http_429\" ||\n code === \"http_500\" ||\n code === \"http_502\" ||\n code === \"http_503\" ||\n code === \"http_504\" ||\n code === \"rate_limited\" ||\n code === \"too_many_concurrent_requests\" ||\n code === \"overloaded_error\" ||\n msg.includes(\"timeout\") ||\n msg.includes(\"gateway error\") ||\n msg.includes(\"gateway timeout\") ||\n msg.includes(\"inactivity timeout\") ||\n msg.includes(\"stream ended\") ||\n msg.includes(\"stream closed\") ||\n msg.includes(\"temporarily unavailable\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\") ||\n msg.includes(\"529\")\n );\n}\n\n/**\n * Reconstruct an assistant-ui message from raw agent run events.\n * Mirrors the client-side processEvent logic so the server can persist\n * the assistant's response even if the frontend is disconnected.\n */\nexport function buildAssistantMessage(\n events: RunEvent[],\n runId?: string,\n options: BuildAssistantMessageOptions = {},\n): {\n id: string;\n createdAt: Date;\n role: \"assistant\";\n content: ContentPart[];\n status:\n | { type: \"complete\"; reason: \"stop\" }\n | { type: \"incomplete\"; reason: \"error\" };\n metadata: Record<string, unknown>;\n} | null {\n const content: ContentPart[] = [];\n let toolCallCounter = 0;\n let runError: {\n message: string;\n errorCode?: string;\n details?: string;\n recoverable?: boolean;\n } | null = null;\n let endedAtInternalContinuationBoundary = false;\n\n const appendText = (text: string) => {\n const last = content[content.length - 1];\n if (last && last.type === \"text\") {\n last.text = (last.text ?? \"\") + text;\n } else {\n content.push({ type: \"text\", text });\n }\n };\n\n for (const { event } of events) {\n if (event.type === \"clear\") {\n content.length = 0;\n toolCallCounter = 0;\n continue;\n }\n\n if (event.type === \"text\") {\n appendText(event.text ?? \"\");\n continue;\n }\n\n if (event.type === \"tool_start\") {\n const toolCallId = `tc_${++toolCallCounter}`;\n const args = (event.input ?? {}) as Record<string, string>;\n content.push({\n type: \"tool-call\",\n toolCallId,\n toolName: event.tool ?? \"unknown\",\n argsText: JSON.stringify(args),\n args,\n });\n continue;\n }\n\n if (event.type === \"tool_done\") {\n for (let i = content.length - 1; i >= 0; i--) {\n const part = content[i];\n if (\n part.type === \"tool-call\" &&\n part.toolName === event.tool &&\n part.result === undefined\n ) {\n part.result = event.result ?? \"\";\n break;\n }\n }\n continue;\n }\n\n if (event.type === \"loop_limit\") {\n // Older servers emitted this as a user-visible terminal event. Treat it\n // as an internal continuation boundary when rebuilding persisted turns.\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"auto_continue\") {\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"error\") {\n if (\n options.suppressInternalContinuation &&\n isInternalContinuationError(event)\n ) {\n endedAtInternalContinuationBoundary = true;\n continue;\n }\n if (event.errorCode === \"run_timeout\" && event.recoverable) {\n continue;\n }\n runError = {\n message: event.error,\n ...(event.errorCode ? { errorCode: event.errorCode } : {}),\n ...(event.details ? { details: event.details } : {}),\n ...(event.recoverable ? { recoverable: event.recoverable } : {}),\n };\n appendText(`${content.length > 0 ? \"\\n\\n\" : \"\"}Error: ${event.error}`);\n continue;\n }\n\n // done, missing_api_key — terminal signals, not content\n }\n\n if (content.length === 0 || endedAtInternalContinuationBoundary) return null;\n\n const metadata: Record<string, unknown> = {};\n if (runId) metadata.runId = runId;\n if (runError) {\n metadata.custom = {\n runError: {\n ...runError,\n ...(runId ? { runId } : {}),\n },\n };\n }\n\n return {\n id: `server-${runId ?? Date.now()}`,\n createdAt: new Date(),\n role: \"assistant\",\n content,\n status: runError\n ? { type: \"incomplete\" as const, reason: \"error\" as const }\n : { type: \"complete\" as const, reason: \"stop\" as const },\n metadata,\n };\n}\n\nfunction getStoredMessage(entry: any): any {\n return entry?.message ?? entry;\n}\n\nfunction getMessageRunId(message: any): string | undefined {\n const meta = message?.metadata;\n const direct = meta?.runId;\n const custom = meta?.custom?.runId;\n const errorRun = meta?.custom?.runError?.runId ?? meta?.runError?.runId;\n if (typeof direct === \"string\") return direct;\n if (typeof custom === \"string\") return custom;\n if (typeof errorRun === \"string\") return errorRun;\n return undefined;\n}\n\nfunction messageContentIsEmpty(content: unknown): boolean {\n if (Array.isArray(content)) return content.length === 0;\n return content == null || content === \"\";\n}\n\nfunction messageText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter(\n (part: any) => part?.type === \"text\" && typeof part.text === \"string\",\n )\n .map((part: any) => part.text)\n .join(\"\");\n}\n\nfunction isTerminalAssistantStatus(status: unknown): boolean {\n const type = (status as { type?: unknown } | undefined)?.type;\n return type === \"complete\" || type === \"incomplete\";\n}\n\nfunction normalizeAttachmentIdentity(attachments: unknown): unknown {\n if (!Array.isArray(attachments)) return undefined;\n return attachments.map((att: any) => ({\n type: att?.type,\n name: att?.name,\n contentType: att?.contentType,\n }));\n}\n\nfunction messageIdentityKeys(message: any): string[] {\n const keys: string[] = [];\n if (typeof message?.id === \"string\" && message.id) {\n keys.push(`id:${message.id}`);\n }\n const runId = getMessageRunId(message);\n if (runId) keys.push(`run:${runId}`);\n\n try {\n keys.push(\n `fingerprint:${JSON.stringify({\n role: message?.role,\n content: message?.content,\n attachments: message?.attachments,\n })}`,\n );\n } catch {\n // Best effort. id/runId usually exist for persisted assistant-ui rows.\n }\n if (message?.role === \"user\") {\n try {\n keys.push(\n `user-fingerprint:${JSON.stringify({\n role: message.role,\n content: message.content,\n attachments: normalizeAttachmentIdentity(message.attachments),\n })}`,\n );\n } catch {\n // Same best-effort behavior as the full fingerprint.\n }\n }\n return keys;\n}\n\nfunction messagesMatch(a: any, b: any): boolean {\n const bKeys = new Set(messageIdentityKeys(b));\n return messageIdentityKeys(a).some((key) => bKeys.has(key));\n}\n\nfunction chooseMergedMessageEntry(existingEntry: any, incomingEntry: any): any {\n const existing = getStoredMessage(existingEntry);\n const incoming = getStoredMessage(incomingEntry);\n if (\n existing?.role === \"assistant\" &&\n incoming?.role === \"assistant\" &&\n isTerminalAssistantStatus(existing?.status) &&\n !isTerminalAssistantStatus(incoming?.status)\n ) {\n return existingEntry;\n }\n return incomingEntry;\n}\n\n/**\n * Merge an incoming client-side full-thread save over the current SQL copy.\n *\n * The browser exports and PUTs the whole assistant-ui repository. If a server\n * completion save lands first, an older browser export can otherwise replace\n * `thread_data` wholesale and delete the assistant message the server just\n * reconstructed from run events. Preserve server-only messages while still\n * accepting client-only messages and metadata.\n */\nexport function mergeThreadDataForClientSave(\n existingRepo: any,\n incomingRepo: any,\n) {\n const merged =\n incomingRepo && typeof incomingRepo === \"object\" ? incomingRepo : {};\n if (\n existingRepo &&\n typeof existingRepo === \"object\" &&\n existingRepo.queuedMessages !== undefined &&\n merged.queuedMessages === undefined\n ) {\n merged.queuedMessages = existingRepo.queuedMessages;\n }\n\n const existingMessages = Array.isArray(existingRepo?.messages)\n ? existingRepo.messages\n : null;\n const incomingMessages = Array.isArray(merged.messages)\n ? merged.messages\n : null;\n if (!existingMessages || !incomingMessages) return merged;\n\n const incomingKeySets = incomingMessages.map(\n (entry: any) => new Set(messageIdentityKeys(getStoredMessage(entry))),\n );\n const usedIncoming = new Set<number>();\n const nextMessages: any[] = [];\n\n for (const existingEntry of existingMessages) {\n const existingKeys = messageIdentityKeys(getStoredMessage(existingEntry));\n const incomingIndex = incomingKeySets.findIndex(\n (keys, index) =>\n !usedIncoming.has(index) && existingKeys.some((key) => keys.has(key)),\n );\n\n if (incomingIndex === -1) {\n nextMessages.push(existingEntry);\n continue;\n }\n\n usedIncoming.add(incomingIndex);\n nextMessages.push(\n chooseMergedMessageEntry(existingEntry, incomingMessages[incomingIndex]),\n );\n }\n\n for (let index = 0; index < incomingMessages.length; index++) {\n if (!usedIncoming.has(index)) nextMessages.push(incomingMessages[index]);\n }\n\n merged.messages = nextMessages;\n return merged;\n}\n\nfunction escapeAttachmentAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction unwrapTextAttachmentEnvelope(text: string): string {\n const match = text.match(\n /^<attachment\\b[^>]*>\\n?([\\s\\S]*?)\\n?<\\/attachment>$/,\n );\n return match ? match[1] : text;\n}\n\nfunction truncateStoredAttachment(text: string): string {\n const unwrapped = unwrapTextAttachmentEnvelope(text);\n if (unwrapped.length <= MAX_STORED_ATTACHMENT_CHARS) return unwrapped;\n const omitted = unwrapped.length - MAX_STORED_ATTACHMENT_CHARS;\n return `${unwrapped.slice(0, MAX_STORED_ATTACHMENT_CHARS)}\\n\\n[Attachment truncated after ${MAX_STORED_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from persisted chat history.]`;\n}\n\nfunction textAttachmentEnvelope(\n att: AgentChatAttachment,\n text: string,\n): string {\n const attrs = [\n `name=\"${escapeAttachmentAttribute(att.name || \"attachment\")}\"`,\n att.contentType\n ? `contentType=\"${escapeAttachmentAttribute(att.contentType)}\"`\n : null,\n att.type ? `type=\"${escapeAttachmentAttribute(att.type)}\"` : null,\n ].filter(Boolean);\n return `<attachment ${attrs.join(\" \")}>\\n${truncateStoredAttachment(text)}\\n</attachment>`;\n}\n\nfunction buildStoredAttachments(\n attachments: AgentChatAttachment[] | undefined,\n runId: string | undefined,\n): any[] {\n return (attachments ?? [])\n .map((att, index) => {\n const id = `server-${runId ?? Date.now()}-attachment-${index}`;\n if (att.type === \"image\" && att.data) {\n return {\n id,\n type: \"image\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [{ type: \"image\", image: att.data }],\n };\n }\n if (att.data) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n {\n type: \"file\",\n data: att.data,\n mimeType: att.contentType,\n filename: att.name,\n },\n ],\n };\n }\n if (typeof att.text === \"string\" && att.text.length > 0) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n { type: \"text\", text: textAttachmentEnvelope(att, att.text) },\n ],\n };\n }\n return null;\n })\n .filter(Boolean);\n}\n\nexport function buildUserMessage(opts: {\n text: string;\n attachments?: AgentChatAttachment[];\n runId?: string;\n createdAt?: Date;\n}): {\n id: string;\n createdAt: Date;\n role: \"user\";\n content: ContentPart[];\n attachments?: any[];\n metadata: Record<string, unknown>;\n} {\n const attachments = buildStoredAttachments(opts.attachments, opts.runId);\n return {\n id: `server-user-${opts.runId ?? Date.now()}`,\n createdAt: opts.createdAt ?? new Date(),\n role: \"user\",\n content: [{ type: \"text\", text: opts.text }],\n ...(attachments.length > 0 ? { attachments } : {}),\n metadata: {\n custom: {\n submittedRunId: opts.runId,\n },\n },\n };\n}\n\nexport function upsertUserMessage(repo: any, userMsg: UserMessage): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n if (lastMsg?.role === \"user\" && messagesMatch(lastMsg, userMsg)) {\n return nextRepo;\n }\n\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n if (isWrapped) {\n const parentId =\n lastIndex >= 0 ? (getStoredMessage(lastEntry)?.id ?? null) : null;\n nextRepo.messages.push({ message: userMsg, parentId });\n } else {\n nextRepo.messages.push(userMsg);\n }\n return nextRepo;\n}\n\nfunction shouldReplaceLastAssistant(\n lastMessage: any,\n assistantMsg: AssistantMessage,\n): boolean {\n const lastContent = lastMessage?.content;\n if (messageContentIsEmpty(lastContent)) return true;\n\n const lastRunId = getMessageRunId(lastMessage);\n const nextRunId = getMessageRunId(assistantMsg);\n if (lastRunId && nextRunId && lastRunId === nextRunId) return true;\n if (lastRunId && nextRunId && lastRunId !== nextRunId) return false;\n\n const lastStatus = lastMessage?.status;\n if (lastStatus && !isTerminalAssistantStatus(lastStatus)) return true;\n\n try {\n if (JSON.stringify(lastContent) === JSON.stringify(assistantMsg.content)) {\n return true;\n }\n } catch {\n // Fall through to the text-prefix check.\n }\n\n const lastText = messageText(lastContent).trim();\n const nextText = messageText(assistantMsg.content).trim();\n if (isTerminalAssistantStatus(lastStatus)) return false;\n return Boolean(lastText && nextText && nextText.startsWith(lastText));\n}\n\n/**\n * Merge the server-reconstructed assistant message into persisted\n * assistant-ui thread data.\n *\n * The browser periodically saves thread data while a run is still streaming.\n * That can leave the last assistant message non-empty but partial/pending.\n * Completion must replace that same-run partial message instead of treating\n * any assistant content as proof that the frontend already saved the final\n * turn.\n */\nexport function upsertAssistantMessage(\n repo: any,\n assistantMsg: AssistantMessage,\n): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n const lastRole = lastMsg?.role;\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n\n if (\n lastRole === \"assistant\" &&\n shouldReplaceLastAssistant(lastMsg, assistantMsg)\n ) {\n nextRepo.messages[lastIndex] = isWrapped\n ? { ...lastEntry, message: assistantMsg }\n : assistantMsg;\n return nextRepo;\n }\n\n if (isWrapped) {\n const parentId =\n nextRepo.messages.length > 0\n ? (getStoredMessage(nextRepo.messages[nextRepo.messages.length - 1])\n ?.id ?? null)\n : null;\n nextRepo.messages.push({ message: assistantMsg, parentId });\n } else {\n nextRepo.messages.push(assistantMsg);\n }\n return nextRepo;\n}\n\n/**\n * Extract title and preview from a thread runtime export.\n * Isomorphic — works on both server and client.\n */\nexport function extractThreadMeta(repo: any): {\n title: string;\n preview: string;\n} {\n const msgs = repo?.messages;\n if (!Array.isArray(msgs) || msgs.length === 0)\n return { title: \"\", preview: \"\" };\n\n let title = \"\";\n let preview = \"\";\n for (const entry of msgs) {\n // Support both wrapped ({ message: { role, content } }) and flat ({ role, content }) formats\n const msg = entry?.message ?? entry;\n if (msg.role !== \"user\") continue;\n const textParts = Array.isArray(msg.content)\n ? msg.content\n .filter((p: any) => p.type === \"text\")\n .map((p: any) => p.text)\n .join(\" \")\n : typeof msg.content === \"string\"\n ? msg.content\n : \"\";\n if (textParts.trim()) {\n if (!title) title = textParts.trim().slice(0, 80);\n preview = textParts.trim().slice(0, 120);\n }\n }\n return { title, preview };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"thread-data-builder.js","sourceRoot":"","sources":["../../src/agent/thread-data-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentChatAttachment, RunEvent } from \"./types.js\";\n\ninterface ContentPart {\n type: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n argsText?: string;\n args?: Record<string, string>;\n result?: string;\n}\n\ninterface BuildAssistantMessageOptions {\n suppressInternalContinuation?: boolean;\n}\n\ntype AssistantMessage = NonNullable<ReturnType<typeof buildAssistantMessage>>;\ntype UserMessage = ReturnType<typeof buildUserMessage>;\n\nconst MAX_STORED_ATTACHMENT_CHARS = 60_000;\n\nfunction isInternalContinuationError(event: {\n error: string;\n errorCode?: string;\n recoverable?: boolean;\n}): boolean {\n const code = String(event.errorCode ?? \"\").toLowerCase();\n const msg = event.error.toLowerCase();\n return (\n event.recoverable === true ||\n code === \"builder_gateway_error\" ||\n code === \"builder_gateway_timeout\" ||\n code === \"stale_run\" ||\n code === \"timeout\" ||\n code === \"timeout_error\" ||\n code === \"http_408\" ||\n code === \"http_429\" ||\n code === \"http_500\" ||\n code === \"http_502\" ||\n code === \"http_503\" ||\n code === \"http_504\" ||\n code === \"rate_limited\" ||\n code === \"too_many_concurrent_requests\" ||\n code === \"overloaded_error\" ||\n msg.includes(\"timeout\") ||\n msg.includes(\"gateway error\") ||\n msg.includes(\"gateway timeout\") ||\n msg.includes(\"inactivity timeout\") ||\n msg.includes(\"stream ended\") ||\n msg.includes(\"stream closed\") ||\n msg.includes(\"temporarily unavailable\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\") ||\n msg.includes(\"529\")\n );\n}\n\n/**\n * Reconstruct an assistant-ui message from raw agent run events.\n * Mirrors the client-side processEvent logic so the server can persist\n * the assistant's response even if the frontend is disconnected.\n */\nexport function buildAssistantMessage(\n events: RunEvent[],\n runId?: string,\n options: BuildAssistantMessageOptions = {},\n): {\n id: string;\n createdAt: Date;\n role: \"assistant\";\n content: ContentPart[];\n status:\n | { type: \"complete\"; reason: \"stop\" }\n | { type: \"incomplete\"; reason: \"error\" };\n metadata: Record<string, unknown>;\n} | null {\n const content: ContentPart[] = [];\n let toolCallCounter = 0;\n let runError: {\n message: string;\n errorCode?: string;\n details?: string;\n recoverable?: boolean;\n } | null = null;\n let endedAtInternalContinuationBoundary = false;\n\n const appendText = (text: string) => {\n const last = content[content.length - 1];\n if (last && last.type === \"text\") {\n last.text = (last.text ?? \"\") + text;\n } else {\n content.push({ type: \"text\", text });\n }\n };\n\n for (const { event } of events) {\n if (event.type === \"clear\") {\n content.length = 0;\n toolCallCounter = 0;\n continue;\n }\n\n if (event.type === \"text\") {\n appendText(event.text ?? \"\");\n continue;\n }\n\n if (event.type === \"tool_start\") {\n const toolCallId = `tc_${++toolCallCounter}`;\n const args = (event.input ?? {}) as Record<string, string>;\n content.push({\n type: \"tool-call\",\n toolCallId,\n toolName: event.tool ?? \"unknown\",\n argsText: JSON.stringify(args),\n args,\n });\n continue;\n }\n\n if (event.type === \"tool_done\") {\n for (let i = content.length - 1; i >= 0; i--) {\n const part = content[i];\n if (\n part.type === \"tool-call\" &&\n part.toolName === event.tool &&\n part.result === undefined\n ) {\n part.result = event.result ?? \"\";\n break;\n }\n }\n continue;\n }\n\n if (event.type === \"loop_limit\") {\n // Older servers emitted this as a user-visible terminal event. Treat it\n // as an internal continuation boundary when rebuilding persisted turns.\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"auto_continue\") {\n if (options.suppressInternalContinuation) {\n endedAtInternalContinuationBoundary = true;\n }\n continue;\n }\n\n if (event.type === \"error\") {\n if (\n options.suppressInternalContinuation &&\n isInternalContinuationError(event)\n ) {\n endedAtInternalContinuationBoundary = true;\n continue;\n }\n if (event.errorCode === \"run_timeout\" && event.recoverable) {\n continue;\n }\n runError = {\n message: event.error,\n ...(event.errorCode ? { errorCode: event.errorCode } : {}),\n ...(event.details ? { details: event.details } : {}),\n ...(event.recoverable ? { recoverable: event.recoverable } : {}),\n };\n appendText(`${content.length > 0 ? \"\\n\\n\" : \"\"}Error: ${event.error}`);\n continue;\n }\n\n // done, missing_api_key — terminal signals, not content\n }\n\n if (content.length === 0 || endedAtInternalContinuationBoundary) return null;\n\n const metadata: Record<string, unknown> = {};\n if (runId) metadata.runId = runId;\n if (runError) {\n metadata.custom = {\n runError: {\n ...runError,\n ...(runId ? { runId } : {}),\n },\n };\n }\n\n return {\n id: `server-${runId ?? Date.now()}`,\n createdAt: new Date(),\n role: \"assistant\",\n content,\n status: runError\n ? { type: \"incomplete\" as const, reason: \"error\" as const }\n : { type: \"complete\" as const, reason: \"stop\" as const },\n metadata,\n };\n}\n\nfunction getStoredMessage(entry: any): any {\n return entry?.message ?? entry;\n}\n\nfunction getMessageRunId(message: any): string | undefined {\n const meta = message?.metadata;\n const direct = meta?.runId;\n const custom = meta?.custom?.runId;\n const errorRun = meta?.custom?.runError?.runId ?? meta?.runError?.runId;\n if (typeof direct === \"string\") return direct;\n if (typeof custom === \"string\") return custom;\n if (typeof errorRun === \"string\") return errorRun;\n return undefined;\n}\n\nfunction messageContentIsEmpty(content: unknown): boolean {\n if (Array.isArray(content)) return content.length === 0;\n return content == null || content === \"\";\n}\n\nfunction messageText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter(\n (part: any) => part?.type === \"text\" && typeof part.text === \"string\",\n )\n .map((part: any) => part.text)\n .join(\"\");\n}\n\nfunction isTerminalAssistantStatus(status: unknown): boolean {\n const type = (status as { type?: unknown } | undefined)?.type;\n return type === \"complete\" || type === \"incomplete\";\n}\n\nfunction normalizeAttachmentIdentity(attachments: unknown): unknown {\n if (!Array.isArray(attachments) || attachments.length === 0) return undefined;\n return attachments.map((att: any) => ({\n type: att?.type,\n name: att?.name,\n contentType: att?.contentType,\n }));\n}\n\nfunction messageIdentityKeys(message: any): string[] {\n const keys: string[] = [];\n if (typeof message?.id === \"string\" && message.id) {\n keys.push(`id:${message.id}`);\n }\n const runId = getMessageRunId(message);\n if (runId) keys.push(`run:${runId}`);\n\n // Normalize attachments through `normalizeAttachmentIdentity` so an\n // explicit empty `[]` (assistant-ui's default for messages with no\n // attachments) and an omitted/undefined `attachments` field hash to the\n // same fingerprint. Without this, every user message ended up duplicated\n // in `chat_threads`: one copy from `saveThreadData` (runtime export\n // includes `attachments: []`) and one from `persistSubmittedUserMessage`\n // → `buildUserMessage` (omits the field entirely). The merge couldn't\n // dedupe them because their fingerprints differed by exactly one\n // `[]` vs `undefined`. (Repro on slides prod: every user turn produced\n // a `client_user → assistant → server_user` triple instead of a\n // `user → assistant` pair.)\n try {\n keys.push(\n `fingerprint:${JSON.stringify({\n role: message?.role,\n content: message?.content,\n attachments: normalizeAttachmentIdentity(message?.attachments),\n })}`,\n );\n } catch {\n // Best effort. id/runId usually exist for persisted assistant-ui rows.\n }\n if (message?.role === \"user\") {\n try {\n keys.push(\n `user-fingerprint:${JSON.stringify({\n role: message.role,\n content: message.content,\n attachments: normalizeAttachmentIdentity(message.attachments),\n })}`,\n );\n } catch {\n // Same best-effort behavior as the full fingerprint.\n }\n }\n return keys;\n}\n\nfunction messagesMatch(a: any, b: any): boolean {\n const bKeys = new Set(messageIdentityKeys(b));\n return messageIdentityKeys(a).some((key) => bKeys.has(key));\n}\n\nfunction chooseMergedMessageEntry(existingEntry: any, incomingEntry: any): any {\n const existing = getStoredMessage(existingEntry);\n const incoming = getStoredMessage(incomingEntry);\n if (\n existing?.role === \"assistant\" &&\n incoming?.role === \"assistant\" &&\n isTerminalAssistantStatus(existing?.status) &&\n !isTerminalAssistantStatus(incoming?.status)\n ) {\n return existingEntry;\n }\n return incomingEntry;\n}\n\n/**\n * Merge an incoming client-side full-thread save over the current SQL copy.\n *\n * The browser exports and PUTs the whole assistant-ui repository. If a server\n * completion save lands first, an older browser export can otherwise replace\n * `thread_data` wholesale and delete the assistant message the server just\n * reconstructed from run events. Preserve server-only messages while still\n * accepting client-only messages and metadata.\n */\nexport function mergeThreadDataForClientSave(\n existingRepo: any,\n incomingRepo: any,\n) {\n const merged =\n incomingRepo && typeof incomingRepo === \"object\" ? incomingRepo : {};\n if (\n existingRepo &&\n typeof existingRepo === \"object\" &&\n existingRepo.queuedMessages !== undefined &&\n merged.queuedMessages === undefined\n ) {\n merged.queuedMessages = existingRepo.queuedMessages;\n }\n\n const existingMessages = Array.isArray(existingRepo?.messages)\n ? existingRepo.messages\n : null;\n const incomingMessages = Array.isArray(merged.messages)\n ? merged.messages\n : null;\n if (!existingMessages || !incomingMessages) return merged;\n\n const incomingKeySets = incomingMessages.map(\n (entry: any) => new Set(messageIdentityKeys(getStoredMessage(entry))),\n );\n const usedIncoming = new Set<number>();\n const nextMessages: any[] = [];\n\n for (const existingEntry of existingMessages) {\n const existingKeys = messageIdentityKeys(getStoredMessage(existingEntry));\n const incomingIndex = incomingKeySets.findIndex(\n (keys, index) =>\n !usedIncoming.has(index) && existingKeys.some((key) => keys.has(key)),\n );\n\n if (incomingIndex === -1) {\n nextMessages.push(existingEntry);\n continue;\n }\n\n usedIncoming.add(incomingIndex);\n nextMessages.push(\n chooseMergedMessageEntry(existingEntry, incomingMessages[incomingIndex]),\n );\n }\n\n for (let index = 0; index < incomingMessages.length; index++) {\n if (!usedIncoming.has(index)) nextMessages.push(incomingMessages[index]);\n }\n\n merged.messages = nextMessages;\n return merged;\n}\n\nfunction escapeAttachmentAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\nfunction unwrapTextAttachmentEnvelope(text: string): string {\n const match = text.match(\n /^<attachment\\b[^>]*>\\n?([\\s\\S]*?)\\n?<\\/attachment>$/,\n );\n return match ? match[1] : text;\n}\n\nfunction truncateStoredAttachment(text: string): string {\n const unwrapped = unwrapTextAttachmentEnvelope(text);\n if (unwrapped.length <= MAX_STORED_ATTACHMENT_CHARS) return unwrapped;\n const omitted = unwrapped.length - MAX_STORED_ATTACHMENT_CHARS;\n return `${unwrapped.slice(0, MAX_STORED_ATTACHMENT_CHARS)}\\n\\n[Attachment truncated after ${MAX_STORED_ATTACHMENT_CHARS.toLocaleString()} characters; ${omitted.toLocaleString()} characters omitted from persisted chat history.]`;\n}\n\nfunction textAttachmentEnvelope(\n att: AgentChatAttachment,\n text: string,\n): string {\n const attrs = [\n `name=\"${escapeAttachmentAttribute(att.name || \"attachment\")}\"`,\n att.contentType\n ? `contentType=\"${escapeAttachmentAttribute(att.contentType)}\"`\n : null,\n att.type ? `type=\"${escapeAttachmentAttribute(att.type)}\"` : null,\n ].filter(Boolean);\n return `<attachment ${attrs.join(\" \")}>\\n${truncateStoredAttachment(text)}\\n</attachment>`;\n}\n\nfunction buildStoredAttachments(\n attachments: AgentChatAttachment[] | undefined,\n runId: string | undefined,\n): any[] {\n return (attachments ?? [])\n .map((att, index) => {\n const id = `server-${runId ?? Date.now()}-attachment-${index}`;\n if (att.type === \"image\" && att.data) {\n return {\n id,\n type: \"image\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [{ type: \"image\", image: att.data }],\n };\n }\n if (att.data) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n {\n type: \"file\",\n data: att.data,\n mimeType: att.contentType,\n filename: att.name,\n },\n ],\n };\n }\n if (typeof att.text === \"string\" && att.text.length > 0) {\n return {\n id,\n type: \"file\",\n name: att.name,\n contentType: att.contentType,\n status: { type: \"complete\" },\n content: [\n { type: \"text\", text: textAttachmentEnvelope(att, att.text) },\n ],\n };\n }\n return null;\n })\n .filter(Boolean);\n}\n\nexport function buildUserMessage(opts: {\n text: string;\n attachments?: AgentChatAttachment[];\n runId?: string;\n createdAt?: Date;\n}): {\n id: string;\n createdAt: Date;\n role: \"user\";\n content: ContentPart[];\n attachments?: any[];\n metadata: Record<string, unknown>;\n} {\n const attachments = buildStoredAttachments(opts.attachments, opts.runId);\n return {\n id: `server-user-${opts.runId ?? Date.now()}`,\n createdAt: opts.createdAt ?? new Date(),\n role: \"user\",\n content: [{ type: \"text\", text: opts.text }],\n ...(attachments.length > 0 ? { attachments } : {}),\n metadata: {\n custom: {\n submittedRunId: opts.runId,\n },\n },\n };\n}\n\nexport function upsertUserMessage(repo: any, userMsg: UserMessage): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n if (lastMsg?.role === \"user\" && messagesMatch(lastMsg, userMsg)) {\n return nextRepo;\n }\n\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n if (isWrapped) {\n const parentId =\n lastIndex >= 0 ? (getStoredMessage(lastEntry)?.id ?? null) : null;\n nextRepo.messages.push({ message: userMsg, parentId });\n } else {\n nextRepo.messages.push(userMsg);\n }\n return nextRepo;\n}\n\nfunction shouldReplaceLastAssistant(\n lastMessage: any,\n assistantMsg: AssistantMessage,\n): boolean {\n const lastContent = lastMessage?.content;\n if (messageContentIsEmpty(lastContent)) return true;\n\n const lastRunId = getMessageRunId(lastMessage);\n const nextRunId = getMessageRunId(assistantMsg);\n if (lastRunId && nextRunId && lastRunId === nextRunId) return true;\n if (lastRunId && nextRunId && lastRunId !== nextRunId) return false;\n\n const lastStatus = lastMessage?.status;\n if (lastStatus && !isTerminalAssistantStatus(lastStatus)) return true;\n\n try {\n if (JSON.stringify(lastContent) === JSON.stringify(assistantMsg.content)) {\n return true;\n }\n } catch {\n // Fall through to the text-prefix check.\n }\n\n const lastText = messageText(lastContent).trim();\n const nextText = messageText(assistantMsg.content).trim();\n if (isTerminalAssistantStatus(lastStatus)) return false;\n return Boolean(lastText && nextText && nextText.startsWith(lastText));\n}\n\n/**\n * Merge the server-reconstructed assistant message into persisted\n * assistant-ui thread data.\n *\n * The browser periodically saves thread data while a run is still streaming.\n * That can leave the last assistant message non-empty but partial/pending.\n * Completion must replace that same-run partial message instead of treating\n * any assistant content as proof that the frontend already saved the final\n * turn.\n */\nexport function upsertAssistantMessage(\n repo: any,\n assistantMsg: AssistantMessage,\n): any {\n const nextRepo = repo && typeof repo === \"object\" ? repo : {};\n if (!Array.isArray(nextRepo.messages)) nextRepo.messages = [];\n\n const lastIndex = nextRepo.messages.length - 1;\n const lastEntry = lastIndex >= 0 ? nextRepo.messages[lastIndex] : undefined;\n const lastMsg = getStoredMessage(lastEntry);\n const lastRole = lastMsg?.role;\n const isWrapped = Boolean(lastEntry && \"message\" in lastEntry);\n\n if (\n lastRole === \"assistant\" &&\n shouldReplaceLastAssistant(lastMsg, assistantMsg)\n ) {\n nextRepo.messages[lastIndex] = isWrapped\n ? { ...lastEntry, message: assistantMsg }\n : assistantMsg;\n return nextRepo;\n }\n\n if (isWrapped) {\n const parentId =\n nextRepo.messages.length > 0\n ? (getStoredMessage(nextRepo.messages[nextRepo.messages.length - 1])\n ?.id ?? null)\n : null;\n nextRepo.messages.push({ message: assistantMsg, parentId });\n } else {\n nextRepo.messages.push(assistantMsg);\n }\n return nextRepo;\n}\n\n/**\n * Extract title and preview from a thread runtime export.\n * Isomorphic — works on both server and client.\n */\nexport function extractThreadMeta(repo: any): {\n title: string;\n preview: string;\n} {\n const msgs = repo?.messages;\n if (!Array.isArray(msgs) || msgs.length === 0)\n return { title: \"\", preview: \"\" };\n\n let title = \"\";\n let preview = \"\";\n for (const entry of msgs) {\n // Support both wrapped ({ message: { role, content } }) and flat ({ role, content }) formats\n const msg = entry?.message ?? entry;\n if (msg.role !== \"user\") continue;\n const textParts = Array.isArray(msg.content)\n ? msg.content\n .filter((p: any) => p.type === \"text\")\n .map((p: any) => p.text)\n .join(\" \")\n : typeof msg.content === \"string\"\n ? msg.content\n : \"\";\n if (textParts.trim()) {\n if (!title) title = textParts.trim().slice(0, 80);\n preview = textParts.trim().slice(0, 120);\n }\n }\n return { title, preview };\n}\n"]}
|
|
@@ -10,15 +10,28 @@ export interface ShareButtonProps {
|
|
|
10
10
|
* button next to an iframe use this to disable the iframe's pointer events
|
|
11
11
|
* while the popover is open, so popover hover/clicks aren't swallowed. */
|
|
12
12
|
onOpenChange?: (open: boolean) => void;
|
|
13
|
-
/** Optional public/share URL shown as a copyable link in the popover.
|
|
13
|
+
/** Optional public/share URL shown as a copyable link in the popover.
|
|
14
|
+
* This is treated as the primary "Copy link" target — same convention
|
|
15
|
+
* as Google Docs' Share dialog, which copies the editor URL. */
|
|
14
16
|
shareUrl?: string;
|
|
15
|
-
/** Optional label for the copyable link section. */
|
|
17
|
+
/** Optional label for the primary copyable link section. */
|
|
16
18
|
shareUrlLabel?: string;
|
|
17
|
-
/** Optional helper text for the copyable link section. */
|
|
19
|
+
/** Optional helper text for the primary copyable link section. */
|
|
18
20
|
shareUrlDescription?: ReactNode;
|
|
19
|
-
/**
|
|
21
|
+
/** Optional secondary copyable link (e.g. a presentation / read-only
|
|
22
|
+
* surface for the same resource). Anyone with at least viewer access
|
|
23
|
+
* can open it — access is enforced on the resource itself, not the
|
|
24
|
+
* URL shape, so we never gate this behind visibility. */
|
|
25
|
+
secondaryShareUrl?: string;
|
|
26
|
+
/** Optional label for the secondary copyable link. */
|
|
27
|
+
secondaryShareUrlLabel?: string;
|
|
28
|
+
/** Optional helper text for the secondary copyable link. */
|
|
29
|
+
secondaryShareUrlDescription?: ReactNode;
|
|
30
|
+
/** @deprecated No longer enforced — access is checked on the resource,
|
|
31
|
+
* not the URL shape, mirroring Google Slides. Kept for callsite
|
|
32
|
+
* compatibility; the prop is now a no-op. */
|
|
20
33
|
shareUrlRequiresPublic?: boolean;
|
|
21
|
-
/**
|
|
34
|
+
/** @deprecated See `shareUrlRequiresPublic`. No longer rendered. */
|
|
22
35
|
shareUrlUnavailableDescription?: ReactNode;
|
|
23
36
|
/** Optional template-specific copy for the visibility picker. */
|
|
24
37
|
visibilityCopy?: Partial<Record<Visibility, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareButton.d.ts","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAqBf,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;oDACgD;IAChD,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B;;+EAE2E;IAC3E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC
|
|
1
|
+
{"version":3,"file":"ShareButton.d.ts","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAqBf,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;oDACgD;IAChD,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B;;+EAE2E;IAC3E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;qEAEiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAChC;;;8DAG0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,4DAA4D;IAC5D,4BAA4B,CAAC,EAAE,SAAS,CAAC;IACzC;;kDAE8C;IAC9C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,oEAAoE;IACpE,8BAA8B,CAAC,EAAE,SAAS,CAAC;IAC3C,iEAAiE;IACjE,cAAc,CAAC,EAAE,OAAO,CACtB,MAAM,CAAC,UAAU,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAC7D,CAAC;IACF,2EAA2E;IAC3E,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,KAAK,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AAkF/C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CAiIlD"}
|
|
@@ -336,14 +336,10 @@ function SharePanel(props) {
|
|
|
336
336
|
? s.principalId
|
|
337
337
|
: displayName(s.principalId, orgMembers), org: s.principalType === "org" }), _jsx("span", { className: "flex-1 min-w-0 truncate", children: s.principalType === "org"
|
|
338
338
|
? s.principalId
|
|
339
|
-
: displayName(s.principalId, orgMembers) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: cap(s.role) })), canManage ? (_jsx("button", { type: "button", "aria-label": "Remove", onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: "No one has access yet." })) : null] }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: "General access" }), _jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy }), _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground", children: meta.description })] })] }), props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, props.shareUrl ? (_jsx(CopyLinkField, { value: props.shareUrl, label: props.shareUrlLabel, description: props.shareUrlDescription,
|
|
340
|
-
(canManage
|
|
341
|
-
? "Make general access public before copying this link."
|
|
342
|
-
: "This link is not public. Ask an owner or admin to make it public."), unavailableActionLabel: canManage ? "Make public and copy" : "Not public", unavailableActionBusyLabel: "Making public...", onUnavailableAction: canManage ? () => onVisibilityChange("public") : undefined })) : null, _jsx("div", { className: "mt-2 flex justify-end", children: _jsx("button", { type: "button", onClick: handleDone, className: BUTTON_PRIMARY_SM, children: "Done" }) })] }));
|
|
339
|
+
: displayName(s.principalId, orgMembers) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: cap(s.role) })), canManage ? (_jsx("button", { type: "button", "aria-label": "Remove", onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: "No one has access yet." })) : null] }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: "General access" }), _jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy }), _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground", children: meta.description })] })] }), props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, props.shareUrl ? (_jsx(CopyLinkField, { value: props.shareUrl, label: props.shareUrlLabel, description: props.shareUrlDescription })) : null, props.secondaryShareUrl ? (_jsx(CopyLinkField, { value: props.secondaryShareUrl, label: props.secondaryShareUrlLabel, description: props.secondaryShareUrlDescription })) : null, _jsx("div", { className: "mt-2 flex justify-end", children: _jsx("button", { type: "button", onClick: handleDone, className: BUTTON_PRIMARY_SM, children: "Done" }) })] }));
|
|
343
340
|
}
|
|
344
|
-
function CopyLinkField({ value, label = "Share link", description,
|
|
341
|
+
function CopyLinkField({ value, label = "Share link", description, }) {
|
|
345
342
|
const [copied, setCopied] = useState(false);
|
|
346
|
-
const [busy, setBusy] = useState(false);
|
|
347
343
|
const resetRef = useRef(undefined);
|
|
348
344
|
useEffect(() => {
|
|
349
345
|
return () => {
|
|
@@ -351,52 +347,19 @@ function CopyLinkField({ value, label = "Share link", description, unavailable =
|
|
|
351
347
|
clearTimeout(resetRef.current);
|
|
352
348
|
};
|
|
353
349
|
}, []);
|
|
354
|
-
const markCopied = () => {
|
|
355
|
-
setCopied(true);
|
|
356
|
-
if (resetRef.current)
|
|
357
|
-
clearTimeout(resetRef.current);
|
|
358
|
-
resetRef.current = setTimeout(() => setCopied(false), 1400);
|
|
359
|
-
};
|
|
360
|
-
const copyValue = async () => {
|
|
361
|
-
await navigator.clipboard.writeText(value);
|
|
362
|
-
markCopied();
|
|
363
|
-
};
|
|
364
350
|
const handleCopy = async () => {
|
|
365
351
|
try {
|
|
366
|
-
await
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
};
|
|
372
|
-
const handleUnavailableAction = async () => {
|
|
373
|
-
if (!onUnavailableAction)
|
|
374
|
-
return;
|
|
375
|
-
setBusy(true);
|
|
376
|
-
try {
|
|
377
|
-
await onUnavailableAction();
|
|
378
|
-
await copyValue();
|
|
352
|
+
await navigator.clipboard.writeText(value);
|
|
353
|
+
setCopied(true);
|
|
354
|
+
if (resetRef.current)
|
|
355
|
+
clearTimeout(resetRef.current);
|
|
356
|
+
resetRef.current = setTimeout(() => setCopied(false), 1400);
|
|
379
357
|
}
|
|
380
358
|
catch {
|
|
381
359
|
setCopied(false);
|
|
382
360
|
}
|
|
383
|
-
finally {
|
|
384
|
-
setBusy(false);
|
|
385
|
-
}
|
|
386
361
|
};
|
|
387
|
-
|
|
388
|
-
? "Link available after general access is Public"
|
|
389
|
-
: value;
|
|
390
|
-
return (_jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: label }), description ? (_jsx("div", { className: "mb-2 text-xs text-muted-foreground", children: description })) : null, unavailable && unavailableDescription ? (_jsx("div", { className: "mb-2 rounded-md border border-border bg-muted/35 px-3 py-2 text-xs text-muted-foreground", children: unavailableDescription })) : null, _jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("input", { readOnly: true, disabled: unavailable, value: inputValue, "aria-disabled": unavailable, className: cn("h-9 min-w-0 flex-1 rounded-md border border-input px-3 text-sm text-muted-foreground outline-none", unavailable ? "cursor-not-allowed bg-muted/40" : "bg-background"), onFocus: (event) => {
|
|
391
|
-
if (!unavailable)
|
|
392
|
-
event.currentTarget.select();
|
|
393
|
-
} }), _jsxs("button", { type: "button", onClick: unavailable ? handleUnavailableAction : handleCopy, disabled: unavailable && !onUnavailableAction, className: "inline-flex h-9 shrink-0 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm font-medium text-foreground hover:bg-accent", children: [copied ? _jsx(IconCheck, { size: 15 }) : _jsx(IconCopy, { size: 15 }), busy
|
|
394
|
-
? unavailableActionBusyLabel
|
|
395
|
-
: unavailable
|
|
396
|
-
? unavailableActionLabel
|
|
397
|
-
: copied
|
|
398
|
-
? "Copied"
|
|
399
|
-
: "Copy"] })] })] }));
|
|
362
|
+
return (_jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-2 text-sm font-semibold", children: label }), description ? (_jsx("div", { className: "mb-2 text-xs text-muted-foreground", children: description })) : null, _jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("input", { readOnly: true, value: value, className: "h-9 min-w-0 flex-1 rounded-md border border-input bg-background px-3 text-sm text-muted-foreground outline-none", onFocus: (event) => event.currentTarget.select() }), _jsxs("button", { type: "button", onClick: handleCopy, className: "inline-flex h-9 shrink-0 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm font-medium text-foreground hover:bg-accent", children: [copied ? _jsx(IconCheck, { size: 15 }) : _jsx(IconCopy, { size: 15 }), copied ? "Copied" : "Copy"] })] })] }));
|
|
400
363
|
}
|
|
401
364
|
// ---------------------------------------------------------------------------
|
|
402
365
|
// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareButton.js","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAEL,SAAS,EACT,OAAO,EACP,MAAM,EACN,QAAQ,GAET,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,SAAS,EACT,SAAS,EACT,eAAe,EACf,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAiDjD,2EAA2E;AAC3E,uEAAuE;AACvE,MAAM,WAAW,GACf,0VAA0V,CAAC;AAC7V,MAAM,iBAAiB,GAAG,EAAE,CAC1B,WAAW,EACX,wQAAwQ,CACzQ,CAAC;AACF,MAAM,iBAAiB,GAAG,EAAE,CAC1B,WAAW,EACX,iEAAiE,CAClE,CAAC;AACF,MAAM,iBAAiB,GAAG,EAAE,CAC1B,WAAW,EACX,gFAAgF,CACjF,CAAC;AACF,MAAM,qBAAqB,GACzB,sGAAsG,CAAC;AAEzG,MAAM,QAAQ,GAGV;IACF,OAAO,EAAE;QACP,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,kCAAkC;QAC/C,IAAI,EAAE,QAAQ;KACf;IACD,GAAG,EAAE;QACH,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,sCAAsC;QACnD,IAAI,EAAE,YAAY;KACnB;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,+BAA+B;QAC5C,IAAI,EAAE,SAAS;KAChB;CACF,CAAC;AAEF,SAAS,cAAc,CACrB,UAAsB,EACtB,IAAyC;IAEzC,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC;IACpC,OAAO;QACL,GAAG,IAAI;QACP,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK;QACpC,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW;KACvD,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAChB;IACE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;IAC7D,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;IAC7D;QACE,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,OAAO;QACd,WAAW,EAAE,4BAA4B;KAC1C;CACF,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,IAAI,CACL,CAAC;IACF,MAAM,mBAAmB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,gBAAgB,GAAG,OAAO,CAC9B,GAAG,EAAE,CAAC,CAAC;QACL,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC,EACF,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC,CACvC,CAAC;IACF,MAAM,aAAa,GAAG,OAAO,CAC3B,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,sBAAsB,EAAE,gBAAgB,CAAU,EACnE,CAAC,gBAAgB,CAAC,CACnB,CAAC;IACF,MAAM,aAAa,GAAG,iBAAiB,CAAC,yBAAyB,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,cAAc,CAChC,sBAAsB,EACtB,gBAAgB,CACjB,CAAC;IACF,MAAM,gBAAgB,GAAG,CAAC,CAAU,EAAE,EAAE;QACtC,OAAO,CAAC,CAAC,CAAC,CAAC;QACX,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,iBAAiB,KAAK,IAAI;YAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IAC7D,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,UAAsB,EAAE,EAAE;QACxD,WAAW,CAAC,YAAY,CAAiB,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAC/D,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CACtC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,IAAgB,EAAiB,EAAE;QACjE,MAAM,SAAS,GAAG,EAAE,mBAAmB,CAAC,OAAO,CAAC;QAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAiB,aAAa,CAAC,CAAC;QACzE,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC3B,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,aAAa,CAAC,MAAM,CAClB;gBACE,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,UAAU,EAAE,IAAI;aACV,EACR;gBACE,SAAS,EAAE,CAAC,MAAW,EAAE,EAAE;oBACzB,IAAI,SAAS,KAAK,mBAAmB,CAAC,OAAO,EAAE,CAAC;wBAC9C,sBAAsB,CACnB,MAAM,EAAE,UAAqC,IAAI,IAAI,CACvD,CAAC;oBACJ,CAAC;oBACD,WAAW;yBACR,OAAO,EAAE;yBACT,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;yBACrB,KAAK,CAAC,MAAM,CAAC;yBACb,OAAO,CAAC,GAAG,EAAE;wBACZ,IAAI,SAAS,KAAK,mBAAmB,CAAC,OAAO,EAAE,CAAC;4BAC9C,oBAAoB,CAAC,IAAI,CAAC,CAAC;wBAC7B,CAAC;oBACH,CAAC,CAAC,CAAC;gBACP,CAAC;gBACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBACjB,IAAI,SAAS,KAAK,mBAAmB,CAAC,OAAO,EAAE,CAAC;wBAC9C,oBAAoB,CAAC,IAAI,CAAC,CAAC;wBAC3B,IAAI,QAAQ,EAAE,CAAC;4BACb,WAAW,CAAC,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;wBACpD,CAAC;6BAAM,CAAC;4BACN,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;wBAC7D,CAAC;oBACH,CAAC;oBACD,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;aACF,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,qEAAqE;IACrE,sEAAsE;IACtE,mEAAmE;IACnE,sEAAsE;IACtE,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,KAAK,SAAS,CAAC;IAC9C,MAAM,gBAAgB,GACnB,WAAW,CAAC,IAAI,EAAE,UAAgC,IAAI,SAAS,CAAC;IACnE,MAAM,iBAAiB,GAAG,iBAAiB,IAAI,gBAAgB,CAAC;IAChE,MAAM,WAAW,GACf,iBAAiB,KAAK,QAAQ;QAC5B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,iBAAiB,KAAK,KAAK;YAC3B,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,QAAQ,CAAC;IAEjB,OAAO,CACL,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,aACjD,KAAC,cAAc,IAAC,OAAO,kBACrB,kBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,iBAAiB,aAC/C,MAAM,CAAC,CAAC,CAAC,CACR,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAI,CAC7C,CAAC,CAAC,CAAC,CACF,oCAEE,SAAS,EAAC,wDAAwD,GAClE,CACH,EACD,mCAAkB,IACX,GACM,EACjB,KAAC,cAAc,IACb,KAAK,EAAC,KAAK,EACX,UAAU,EAAE,CAAC,EACb,SAAS,EAAE,EAAE,CACX,uDAAuD,EACvD,qBAAqB,CACtB,EACD,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,YAE1C,KAAC,UAAU,OACL,KAAK,EACT,WAAW,EAAE,WAAW,EACxB,kBAAkB,EAAE,iBAAiB,EACrC,kBAAkB,EAAE,sBAAsB,EAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,GACtC,GACa,IACT,CACX,CAAC;AACJ,CAAC;AAOD,SAAS,aAAa;IACpB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAc,EAAE,CAAC,CAAC;IACxD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,KAAK,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC;aACjD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACrC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,SAAS,IAAI,CAAC,IAAI;gBAAE,OAAO;YAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,UAAU,CACR,IAAI;iBACD,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBAChB,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAClD,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;aAClD,CAAC,CAAC;iBACF,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CACrC,CAAC;QACJ,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnB,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CACjB,KAKC;IAED,MAAM,EACJ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,GACR,GAAG,KAAK,CAAC;IAEV,MAAM,KAAK,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;IAEtD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO,QAAQ,CAAC,CAAC;IACjD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,UAAU,GAAG,sBAAsB,YAAY,IAAI,UAAU,EAAE,CAAC;IAEtE,8CAA8C;IAC9C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,EAAE,CAAC,CAAC;IAC5D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IAC7E,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAuB,EAAE,CAAC,CAAC;IAC7E,sEAAsE;IACtE,oEAAoE;IACpE,wEAAwE;IACxE,wEAAwE;IACxE,yDAAyD;IACzD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IACjE,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,EAAE,CAChC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,CAAC,CAAS,EAAE,EAAE,CAClC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE;QACnB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEL,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,OAAO,EAAE,CAAC;QACtB,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,KAAK,SAAS,CAAC;IACrC,MAAM,UAAU,GACd,kBAAkB,IAAK,IAAI,EAAE,UAAgC,IAAI,SAAS,CAAC;IAC7E,MAAM,SAAS,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IACnE,MAAM,IAAI,GAAG,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAE9D,MAAM,YAAY,GAAG,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GAAY;QACtB,GAAG,YAAY;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;aAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,GAAG,WAAW;KACf,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,IAAgB,EAAE,EAAE;QAC5C,IAAI,IAAI,KAAK,UAAU;YAAE,OAAO;QAChC,KAAK,kBAAkB,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,UAAU,GAAU;YACxB,EAAE,EAAE,WAAW,OAAO,EAAE;YACxB,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,OAAO;YACpB,IAAI;SACL,CAAC;QACF,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5B,6EAA6E;QAC7E,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO;QAC5B,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;QAC1C,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,WAAW,CAAC,CAAC,CAAC,CAAC;QACf,KAAK,CAAC,MAAM,CACV;YACE,YAAY;YACZ,UAAU;YACV,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,OAAO;YACpB,IAAI;YACJ,MAAM,EAAE,YAAY;YACpB,WAAW,EAAE,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC;SACzC,EACR;YACE,SAAS,EAAE,GAAG,EAAE;gBACd,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;oBAC9B,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC/D,aAAa,CAAC,CAAC,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC/D,aAAa,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;SACF,CACF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,CAAQ,EAAE,IAAU,EAAE,EAAE;QAChD,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO;QAC5B,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,mEAAmE;QACnE,sEAAsE;QACtE,sEAAsE;QACtE,oCAAoC;QACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO;QAC5B,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACrD,WAAW,CAAC,CAAC,CAAC,CAAC;QACf,mEAAmE;QACnE,yEAAyE;QACzE,KAAK,CAAC,MAAM,CACV;YACE,YAAY;YACZ,UAAU;YACV,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,KAAK;SACP,EACR;YACE,SAAS,EAAE,GAAG,EAAE;gBACd,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;oBAC9B,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE;wBACxB,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;wBACjC,OAAO,IAAI,CAAC;oBACd,CAAC,CAAC,CAAC;oBACH,aAAa,CAAC,CAAC,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,gBAAgB,CAAC,CAAC,IAAI,EAAE,EAAE;oBACxB,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;oBACjC,OAAO,IAAI,CAAC;gBACd,CAAC,CAAC,CAAC;gBACH,aAAa,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;SACF,CACF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,CAAQ,EAAE,EAAE;QAChC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,uEAAuE;QACvE,wEAAwE;QACxE,iEAAiE;QACjE,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO;QAC5B,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,WAAW,CAAC,CAAC,CAAC,CAAC;QACf,OAAO,CAAC,MAAM,CACZ;YACE,YAAY;YACZ,UAAU;YACV,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,WAAW,EAAE,CAAC,CAAC,WAAW;SACpB,EACR;YACE,SAAS,EAAE,GAAG,EAAE;gBACd,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;oBAC9B,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE;wBACzB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;wBAC3B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;wBACf,OAAO,IAAI,CAAC;oBACd,CAAC,CAAC,CAAC;oBACH,aAAa,CAAC,CAAC,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE;oBACzB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;oBAC3B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBACf,OAAO,IAAI,CAAC;gBACd,CAAC,CAAC,CAAC;gBACH,aAAa,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;SACF,CACF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,SAAS,IAAI,cAAc;YAAE,SAAS,EAAE,CAAC;QAC7C,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,aAAa;QAC7B,CAAC,CAAC,UAAU,aAAa,GAAG;QAC5B,CAAC,CAAC,SAAS,YAAY,EAAE,CAAC;IAE5B,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,0BACE,cACE,SAAS,EAAC,uCAAuC,EACjD,KAAK,EAAE,SAAS,YAEf,SAAS,GACN,EACN,cAAK,SAAS,EAAC,4CAA4C,GAAG,EAC9D,cAAK,SAAS,EAAC,4BAA4B,mCAAyB,EACpE,cAAK,SAAS,EAAC,4CAA4C,GAAG,EAC9D,cAAK,SAAS,EAAC,4BAA4B,+BAAqB,EAChE,cAAK,SAAS,EAAC,4CAA4C,GAAG,EAC9D,cAAK,SAAS,EAAC,uBAAuB,YACpC,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,qBAE3D,GACL,IACF,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,0BACE,cAAK,SAAS,EAAC,uCAAuC,EAAC,KAAK,EAAE,SAAS,YACpE,SAAS,GACN,EAEL,SAAS,CAAC,CAAC,CAAC,CACX,eAAK,SAAS,EAAC,gBAAgB,aAC7B,eAAK,SAAS,EAAC,0BAA0B,aACvC,gBACE,IAAI,EAAC,OAAO,EACZ,WAAW,EAAC,qBAAqB,EACjC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;oCACf,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;wCAAE,SAAS,EAAE,CAAC;gCACrC,CAAC,EACD,IAAI,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EACpD,YAAY,EAAC,KAAK,EAClB,SAAS,EAAC,iOAAiO,GAC3O,EACD,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACvB,mBAAU,EAAE,EAAE,UAAU,YACrB,UAAU;qCACR,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,IAAI,EAAE,UAAU;oCACxC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,aAAa,KAAK,MAAM;wCAC1B,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,KAAK,CAC5B,CACJ;qCACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACV,iBAEE,KAAK,EAAE,CAAC,CAAC,KAAK,EACd,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS,IAFrB,CAAC,CAAC,KAAK,CAGZ,CACH,CAAC,GACK,CACZ,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,UAAU,IAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAI,IAC1C,EACL,cAAc,CAAC,CAAC,CAAC,CAChB,iBAAO,SAAS,EAAC,8DAA8D,aAC7E,gBACE,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAClD,SAAS,EAAC,6CAA6C,GACvD,qBAEI,CACT,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC,CAAC,CAAC,IAAI,EAER,cAAK,SAAS,EAAC,4BAA4B,mCAAyB,EACpE,cAAI,SAAS,EAAC,4CAA4C,aACvD,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAClB,cAAI,SAAS,EAAC,6CAA6C,aACzD,KAAC,MAAM,IAAC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,GAAI,EAC3D,eAAM,SAAS,EAAC,yBAAyB,YACtC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,GACpC,EACP,eAAM,SAAS,EAAC,+BAA+B,sBAAa,IACzD,CACN,CAAC,CAAC,CAAC,IAAI,EACP,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACjB,cAEE,SAAS,EAAE,EAAE,CACX,6CAA6C,EAC7C,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,YAAY,CACvC,aAED,KAAC,MAAM,IACL,KAAK,EACH,CAAC,CAAC,aAAa,KAAK,KAAK;oCACvB,CAAC,CAAC,CAAC,CAAC,WAAW;oCACf,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,EAE5C,GAAG,EAAE,CAAC,CAAC,aAAa,KAAK,KAAK,GAC9B,EACF,eAAM,SAAS,EAAC,yBAAyB,YACtC,CAAC,CAAC,aAAa,KAAK,KAAK;oCACxB,CAAC,CAAC,CAAC,CAAC,WAAW;oCACf,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,GACrC,EACN,SAAS,CAAC,CAAC,CAAC,CACX,KAAC,UAAU,IACT,KAAK,EAAE,CAAC,CAAC,IAAI,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EACvC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAChC,KAAK,SACL,CACH,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,+BAA+B,YAC5C,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GACP,CACR,EACA,SAAS,CAAC,CAAC,CAAC,CACX,iBACE,IAAI,EAAC,QAAQ,gBACF,QAAQ,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAC9B,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAChC,SAAS,EAAE,iBAAiB,YAE5B,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GAChB,CACV,CAAC,CAAC,CAAC,IAAI,KAzCH,KAAK,CAAC,CAAC,CAAC,CA0CV,CACN,CAAC,EACD,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CACrC,aAAI,SAAS,EAAC,2CAA2C,uCAEpD,CACN,CAAC,CAAC,CAAC,IAAI,IACL,EAEL,cAAK,SAAS,EAAC,4BAA4B,+BAAqB,EAChE,eAAK,SAAS,EAAC,8BAA8B,aAC3C,oCAEE,SAAS,EAAC,sGAAsG,YAEhH,KAAC,IAAI,CAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAI,GACrC,EACP,eAAK,SAAS,EAAC,gBAAgB,aAC7B,KAAC,gBAAgB,IACf,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,CAAC,SAAS,EACpB,cAAc,EAAE,KAAK,CAAC,cAAc,GACpC,EACF,cAAK,SAAS,EAAC,sCAAsC,YAClD,IAAI,CAAC,WAAW,GACb,IACF,IACF,EAEL,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAClB,cAAK,SAAS,EAAC,oFAAoF,YAChG,KAAK,CAAC,UAAU,GACb,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChB,KAAC,aAAa,IACZ,KAAK,EAAE,KAAK,CAAC,QAAQ,EACrB,KAAK,EAAE,KAAK,CAAC,aAAa,EAC1B,WAAW,EAAE,KAAK,CAAC,mBAAmB,EACtC,WAAW,EAAE,KAAK,CAAC,sBAAsB,IAAI,UAAU,KAAK,QAAQ,EACpE,sBAAsB,EACpB,KAAK,CAAC,8BAA8B;oBACpC,CAAC,SAAS;wBACR,CAAC,CAAC,sDAAsD;wBACxD,CAAC,CAAC,mEAAmE,CAAC,EAE1E,sBAAsB,EACpB,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,YAAY,EAEnD,0BAA0B,EAAC,kBAAkB,EAC7C,mBAAmB,EACjB,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,GAE5D,CACH,CAAC,CAAC,CAAC,IAAI,EAER,cAAK,SAAS,EAAC,uBAAuB,YACpC,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,iBAAiB,qBAGrB,GACL,IACF,CACP,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,KAAK,EACL,KAAK,GAAG,YAAY,EACpB,WAAW,EACX,WAAW,GAAG,KAAK,EACnB,sBAAsB,EACtB,sBAAsB,GAAG,aAAa,EACtC,0BAA0B,GAAG,YAAY,EACzC,mBAAmB,GAUpB;IACC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAgC,SAAS,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,CAAC,OAAO;gBAAE,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,QAAQ,CAAC,OAAO;YAAE,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACrD,QAAQ,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;QAC3B,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3C,UAAU,EAAE,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,SAAS,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,uBAAuB,GAAG,KAAK,IAAI,EAAE;QACzC,IAAI,CAAC,mBAAmB;YAAE,OAAO;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,CAAC;YACH,MAAM,mBAAmB,EAAE,CAAC;YAC5B,MAAM,SAAS,EAAE,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC,+CAA+C;QACjD,CAAC,CAAC,KAAK,CAAC;IAEV,OAAO,CACL,eAAK,SAAS,EAAC,MAAM,aACnB,cAAK,SAAS,EAAC,4BAA4B,YAAE,KAAK,GAAO,EACxD,WAAW,CAAC,CAAC,CAAC,CACb,cAAK,SAAS,EAAC,oCAAoC,YAAE,WAAW,GAAO,CACxE,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,IAAI,sBAAsB,CAAC,CAAC,CAAC,CACvC,cAAK,SAAS,EAAC,0FAA0F,YACtG,sBAAsB,GACnB,CACP,CAAC,CAAC,CAAC,IAAI,EACR,eAAK,SAAS,EAAC,iCAAiC,aAC9C,gBACE,QAAQ,QACR,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,UAAU,mBACF,WAAW,EAC1B,SAAS,EAAE,EAAE,CACX,mGAAmG,EACnG,WAAW,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,eAAe,CACjE,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;4BACjB,IAAI,CAAC,WAAW;gCAAE,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;wBACjD,CAAC,GACD,EACF,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,UAAU,EAC3D,QAAQ,EAAE,WAAW,IAAI,CAAC,mBAAmB,EAC7C,SAAS,EAAC,mJAAmJ,aAE5J,MAAM,CAAC,CAAC,CAAC,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,EACzD,IAAI;gCACH,CAAC,CAAC,0BAA0B;gCAC5B,CAAC,CAAC,WAAW;oCACX,CAAC,CAAC,sBAAsB;oCACxB,CAAC,CAAC,MAAM;wCACN,CAAC,CAAC,QAAQ;wCACV,CAAC,CAAC,MAAM,IACP,IACL,IACF,CACP,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAE9E,MAAM,kBAAkB,GACtB,iPAAiP,CAAC;AACpP,MAAM,eAAe,GACnB,8NAA8N,CAAC;AAQjO,SAAS,WAAW,CAAC,EAAE,KAAK,EAAoC;IAC9D,OAAO,CACL,4BACG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CACjB,MAAC,MAAM,CAAC,IAAI,IAEV,KAAK,EAAE,EAAE,CAAC,KAAK,EACf,SAAS,EAAE,eAAe,aAE1B,eAAM,SAAS,EAAC,gEAAgE,YAC9E,KAAC,MAAM,CAAC,aAAa,cACnB,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GACF,GAClB,EACP,gBAAM,SAAS,EAAC,eAAe,aAC7B,KAAC,MAAM,CAAC,QAAQ,cAAE,EAAE,CAAC,KAAK,GAAmB,EAC5C,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAChB,eAAM,SAAS,EAAC,+BAA+B,YAC5C,EAAE,CAAC,WAAW,GACV,CACR,CAAC,CAAC,CAAC,IAAI,IACH,KAhBF,EAAE,CAAC,KAAK,CAiBD,CACf,CAAC,GACD,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAOnB;IACC,MAAM,OAAO,GACX,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,CACL,MAAC,MAAM,CAAC,IAAI,IACV,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAS,CAAC,EAC/C,QAAQ,EAAE,KAAK,CAAC,QAAQ,aAExB,MAAC,MAAM,CAAC,OAAO,IACb,SAAS,EACP,KAAK,CAAC,KAAK;oBACT,CAAC,CAAC,EAAE,CACA,WAAW,EACX,4FAA4F,CAC7F;oBACH,CAAC,CAAC,EAAE,CACA,WAAW,EACX,yFAAyF,CAC1F,gBAEI,MAAM,aAEjB,KAAC,MAAM,CAAC,KAAK,cAAE,OAAO,CAAC,KAAK,GAAgB,EAC5C,KAAC,MAAM,CAAC,IAAI,cACV,KAAC,eAAe,IAAC,IAAI,EAAE,EAAE,GAAI,GACjB,IACC,EACjB,KAAC,MAAM,CAAC,MAAM,cACZ,KAAC,MAAM,CAAC,OAAO,IACb,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,EAAC,QAAQ,EACjB,UAAU,EAAE,CAAC,YAEb,KAAC,MAAM,CAAC,QAAQ,cACd,KAAC,WAAW,IAAC,KAAK,EAAE,YAAY,GAAI,GACpB,GACH,GACH,IACJ,CACf,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAKzB;IACC,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAClE,OAAO,CACL,MAAC,MAAM,CAAC,IAAI,IACV,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAe,CAAC,EACrD,QAAQ,EAAE,KAAK,CAAC,QAAQ,aAExB,MAAC,MAAM,CAAC,OAAO,IACb,SAAS,EAAE,EAAE,CACX,WAAW,EACX,4FAA4F,CAC7F,gBACU,gBAAgB,aAE3B,KAAC,MAAM,CAAC,KAAK,cAAE,OAAO,CAAC,KAAK,GAAgB,EAC5C,KAAC,MAAM,CAAC,IAAI,cACV,KAAC,eAAe,IAAC,IAAI,EAAE,EAAE,GAAI,GACjB,IACC,EACjB,KAAC,MAAM,CAAC,MAAM,cACZ,KAAC,MAAM,CAAC,OAAO,IACb,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,EAAC,QAAQ,EACjB,UAAU,EAAE,CAAC,YAEb,KAAC,MAAM,CAAC,QAAQ,cACd,KAAC,WAAW,IACV,KAAK,EAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCACzD,KAAK,EAAE,CAAC;gCACR,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,KAAK;gCACpD,WAAW,EAAE,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC;qCACjD,WAAW;6BACf,CAAC,CAAC,GACH,GACc,GACH,GACH,IACJ,CACf,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAoC;IAC9D,OAAO,CACL,oCAEE,SAAS,EAAC,gIAAgI,YAEzI,GAAG,CAAC,CAAC,CAAC,KAAC,YAAY,IAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GACjE,CACR,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,CAAQ;IACrB,OAAO,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/C,CAAC;AACD,SAAS,kBAAkB,CAAC,QAAiB;IAC3C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACpD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC9B,CAAC;AACD,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AACD,SAAS,QAAQ,CAAC,CAAS;IACzB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,OAAoB;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IACrD,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC;IACxD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n IconLock,\n IconBuilding,\n IconWorld,\n IconTrash,\n IconCheck,\n IconChevronDown,\n IconCopy,\n} from \"@tabler/icons-react\";\nimport * as Select from \"@radix-ui/react-select\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { useActionQuery, useActionMutation } from \"../use-action.js\";\nimport { cn } from \"../utils.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport interface ShareButtonProps {\n resourceType: string;\n resourceId: string;\n resourceTitle?: string;\n /** @deprecated No longer affects rendering — trigger always says\n * \"Share\". Kept for callsite compatibility. */\n variant?: \"compact\" | \"label\";\n /** Notified when the share popover opens or closes. Hosts that render the\n * button next to an iframe use this to disable the iframe's pointer events\n * while the popover is open, so popover hover/clicks aren't swallowed. */\n onOpenChange?: (open: boolean) => void;\n /** Optional public/share URL shown as a copyable link in the popover. */\n shareUrl?: string;\n /** Optional label for the copyable link section. */\n shareUrlLabel?: string;\n /** Optional helper text for the copyable link section. */\n shareUrlDescription?: ReactNode;\n /** When true, the share URL is only copyable after visibility is public. */\n shareUrlRequiresPublic?: boolean;\n /** Optional helper text shown when the share URL requires public visibility. */\n shareUrlUnavailableDescription?: ReactNode;\n /** Optional template-specific copy for the visibility picker. */\n visibilityCopy?: Partial<\n Record<Visibility, { label?: string; description?: string }>\n >;\n /** Optional note rendered between general access and the copyable link. */\n accessNote?: ReactNode;\n}\n\ntype Visibility = \"private\" | \"org\" | \"public\";\ntype Role = \"viewer\" | \"editor\" | \"admin\";\n\ninterface Share {\n id: string;\n principalType: \"user\" | \"org\";\n principalId: string;\n role: Role;\n}\n\ninterface SharesResponse {\n ownerEmail: string | null;\n orgId: string | null;\n visibility: Visibility | null;\n role?: \"owner\" | Role;\n shares: Share[];\n}\n\n// Mirror shadcn's <Button size=\"sm\" variant=\"outline\"> class string so the\n// trigger sits flush next to other sm outline buttons in the template.\nconst BUTTON_BASE =\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\";\nconst BUTTON_OUTLINE_SM = cn(\n BUTTON_BASE,\n \"h-9 px-3 border border-[hsl(var(--sidebar-border,var(--input)))] bg-[hsl(var(--sidebar-background,var(--background)))] text-foreground hover:bg-[hsl(var(--sidebar-accent,var(--accent)))] hover:text-[hsl(var(--sidebar-accent-foreground,var(--accent-foreground)))]\",\n);\nconst BUTTON_PRIMARY_SM = cn(\n BUTTON_BASE,\n \"h-9 px-4 bg-primary text-primary-foreground hover:bg-primary/90\",\n);\nconst BUTTON_GHOST_ICON = cn(\n BUTTON_BASE,\n \"h-7 w-7 p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n);\nconst SHARE_POPOVER_SURFACE =\n \"border-[hsl(var(--sidebar-border,var(--border)))] bg-[hsl(var(--sidebar-background,var(--popover)))]\";\n\nconst VIS_META: Record<\n Visibility,\n { label: string; description: string; Icon: typeof IconLock }\n> = {\n private: {\n label: \"Private\",\n description: \"Only people with access can view\",\n Icon: IconLock,\n },\n org: {\n label: \"Organization\",\n description: \"Anyone in your organization can view\",\n Icon: IconBuilding,\n },\n public: {\n label: \"Public\",\n description: \"Anyone with the link can view\",\n Icon: IconWorld,\n },\n};\n\nfunction visibilityMeta(\n visibility: Visibility,\n copy?: ShareButtonProps[\"visibilityCopy\"],\n): (typeof VIS_META)[Visibility] {\n const base = VIS_META[visibility];\n const override = copy?.[visibility];\n return {\n ...base,\n label: override?.label ?? base.label,\n description: override?.description ?? base.description,\n };\n}\n\nconst ROLE_OPTIONS: Array<{ value: Role; label: string; description: string }> =\n [\n { value: \"viewer\", label: \"Viewer\", description: \"Can view\" },\n { value: \"editor\", label: \"Editor\", description: \"Can edit\" },\n {\n value: \"admin\",\n label: \"Admin\",\n description: \"Can edit and manage access\",\n },\n ];\n\n/**\n * Framework share control. Renders a shadcn-outline-styled trigger that\n * opens a Google-Docs-style popover anchored beneath it. Uses Tailwind\n * + CSS variables so the same component renders natively in light and\n * dark mode in any shadcn template.\n */\nexport function ShareButton(props: ShareButtonProps) {\n const [open, setOpen] = useState(false);\n const [pendingVisibility, setPendingVisibility] = useState<Visibility | null>(\n null,\n );\n const visibilityRequestId = useRef(0);\n const queryClient = useQueryClient();\n const shareQueryParams = useMemo(\n () => ({\n resourceType: props.resourceType,\n resourceId: props.resourceId,\n }),\n [props.resourceType, props.resourceId],\n );\n const shareQueryKey = useMemo(\n () => [\"action\", \"list-resource-shares\", shareQueryParams] as const,\n [shareQueryParams],\n );\n const setVisibility = useActionMutation(\"set-resource-visibility\");\n const sharesQuery = useActionQuery<SharesResponse>(\n \"list-resource-shares\",\n shareQueryParams,\n );\n const handleOpenChange = (v: boolean) => {\n setOpen(v);\n props.onOpenChange?.(v);\n if (v && pendingVisibility === null) sharesQuery.refetch();\n };\n\n const updateCachedVisibility = (visibility: Visibility) => {\n queryClient.setQueryData<SharesResponse>(shareQueryKey, (prev) =>\n prev ? { ...prev, visibility } : prev,\n );\n };\n\n const handleVisibilityChange = (next: Visibility): Promise<void> => {\n const requestId = ++visibilityRequestId.current;\n const previous = queryClient.getQueryData<SharesResponse>(shareQueryKey);\n setPendingVisibility(next);\n updateCachedVisibility(next);\n return new Promise((resolve, reject) => {\n setVisibility.mutate(\n {\n resourceType: props.resourceType,\n resourceId: props.resourceId,\n visibility: next,\n } as any,\n {\n onSuccess: (result: any) => {\n if (requestId === visibilityRequestId.current) {\n updateCachedVisibility(\n (result?.visibility as Visibility | undefined) ?? next,\n );\n }\n sharesQuery\n .refetch()\n .then(() => resolve())\n .catch(reject)\n .finally(() => {\n if (requestId === visibilityRequestId.current) {\n setPendingVisibility(null);\n }\n });\n },\n onError: (error) => {\n if (requestId === visibilityRequestId.current) {\n setPendingVisibility(null);\n if (previous) {\n queryClient.setQueryData(shareQueryKey, previous);\n } else {\n queryClient.invalidateQueries({ queryKey: shareQueryKey });\n }\n }\n reject(error);\n },\n },\n );\n });\n };\n\n // The trigger always says \"Share\" — the icon reflects the resource's\n // current visibility (lock / building / globe), matching Google Docs.\n // While the query is loading and we don't know the visibility yet,\n // render a skeleton placeholder in the icon slot instead of guessing.\n const loaded = sharesQuery.data !== undefined;\n const serverVisibility =\n (sharesQuery.data?.visibility as Visibility | null) ?? \"private\";\n const currentVisibility = pendingVisibility ?? serverVisibility;\n const TriggerIcon =\n currentVisibility === \"public\"\n ? IconWorld\n : currentVisibility === \"org\"\n ? IconBuilding\n : IconLock;\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <button type=\"button\" className={BUTTON_OUTLINE_SM}>\n {loaded ? (\n <TriggerIcon size={16} strokeWidth={1.75} />\n ) : (\n <span\n aria-hidden\n className=\"inline-block h-4 w-4 rounded-sm bg-muted animate-pulse\"\n />\n )}\n <span>Share</span>\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n sideOffset={6}\n className={cn(\n \"z-[2000] w-[min(460px,92vw)] rounded-lg p-4 shadow-lg\",\n SHARE_POPOVER_SURFACE,\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <SharePanel\n {...props}\n sharesQuery={sharesQuery}\n visibilityOverride={pendingVisibility}\n onVisibilityChange={handleVisibilityChange}\n onClose={() => handleOpenChange(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\ninterface OrgMember {\n email: string;\n name?: string | null;\n}\n\nfunction useOrgMembers(): OrgMember[] {\n const [members, setMembers] = useState<OrgMember[]>([]);\n useEffect(() => {\n let cancelled = false;\n fetch(agentNativePath(\"/_agent-native/org/members\"))\n .then((r) => (r.ok ? r.json() : null))\n .then((data) => {\n if (cancelled || !data) return;\n const list = Array.isArray(data?.members) ? data.members : [];\n setMembers(\n list\n .map((m: any) => ({\n email: typeof m?.email === \"string\" ? m.email : \"\",\n name: typeof m?.name === \"string\" ? m.name : null,\n }))\n .filter((m: OrgMember) => m.email),\n );\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, []);\n return members;\n}\n\nfunction SharePanel(\n props: ShareButtonProps & {\n sharesQuery: ReturnType<typeof useActionQuery<SharesResponse>>;\n visibilityOverride: Visibility | null;\n onVisibilityChange: (visibility: Visibility) => Promise<void>;\n onClose: () => void;\n },\n) {\n const {\n resourceType,\n resourceId,\n resourceTitle,\n sharesQuery,\n visibilityOverride,\n onVisibilityChange,\n onClose,\n } = props;\n\n const share = useActionMutation(\"share-resource\");\n const unshare = useActionMutation(\"unshare-resource\");\n\n const [email, setEmail] = useState(\"\");\n const [role, setRole] = useState<Role>(\"viewer\");\n const [notifyPeople, setNotifyPeople] = useState(true);\n const hasInviteEmail = email.trim().length > 0;\n const orgMembers = useOrgMembers();\n const datalistId = `share-autocomplete-${resourceType}-${resourceId}`;\n\n // Optimistic overlays so clicks feel instant.\n const [pendingAdds, setPendingAdds] = useState<Share[]>([]);\n const [pendingRemoves, setPendingRemoves] = useState<Set<string>>(new Set());\n const [roleOverrides, setRoleOverrides] = useState<Record<string, Role>>({});\n // Principals with an in-flight share/unshare mutation. We disable the\n // role dropdown and the trash button for any share in this set so a\n // user can't race a role-change against a remove (which would otherwise\n // let the upsert silently re-grant access after the delete landed), and\n // can't rapid-fire two creates for the same pending add.\n const [inFlight, setInFlight] = useState<Set<string>>(new Set());\n const addInFlight = (k: string) =>\n setInFlight((prev) => new Set(prev).add(k));\n const clearInFlight = (k: string) =>\n setInFlight((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n\n useEffect(() => {\n sharesQuery.refetch();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const data = sharesQuery.data;\n const isLoading = data === undefined;\n const visibility: Visibility =\n visibilityOverride ?? (data?.visibility as Visibility | null) ?? \"private\";\n const canManage = data?.role === \"owner\" || data?.role === \"admin\";\n const meta = visibilityMeta(visibility, props.visibilityCopy);\n\n const serverShares = data?.shares ?? [];\n const shares: Share[] = [\n ...serverShares\n .filter((s) => !pendingRemoves.has(keyOf(s)))\n .map((s) => ({ ...s, role: roleOverrides[keyOf(s)] ?? s.role })),\n ...pendingAdds,\n ];\n\n const handleVisibility = (next: Visibility) => {\n if (next === visibility) return;\n void onVisibilityChange(next).catch(() => {});\n };\n\n const handleAdd = () => {\n const trimmed = email.trim();\n if (!trimmed) return;\n const optimistic: Share = {\n id: `pending-${trimmed}`,\n principalType: \"user\",\n principalId: trimmed,\n role,\n };\n const k = keyOf(optimistic);\n // Ignore duplicate submits while an add for the same principal is in flight.\n if (inFlight.has(k)) return;\n setPendingAdds((p) => [...p, optimistic]);\n setEmail(\"\");\n addInFlight(k);\n share.mutate(\n {\n resourceType,\n resourceId,\n principalType: \"user\",\n principalId: trimmed,\n role,\n notify: notifyPeople,\n resourceUrl: getNotificationUrl(props.shareUrl),\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setPendingAdds((p) => p.filter((s) => s.id !== optimistic.id));\n clearInFlight(k);\n });\n },\n onError: () => {\n setPendingAdds((p) => p.filter((s) => s.id !== optimistic.id));\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleChangeRole = (s: Share, next: Role) => {\n if (s.role === next) return;\n const k = keyOf(s);\n // Don't stack a role change on top of an in-flight add/remove/role\n // change for the same principal — it can race with unshare and end up\n // re-granting access after a delete. UI already disables the control,\n // but belt-and-suspenders here too.\n if (inFlight.has(k)) return;\n setRoleOverrides((prev) => ({ ...prev, [k]: next }));\n addInFlight(k);\n // share-resource is upsert: calling with same principal + new role\n // updates the existing share row. See sharing/actions/share-resource.ts.\n share.mutate(\n {\n resourceType,\n resourceId,\n principalType: s.principalType,\n principalId: s.principalId,\n role: next,\n notify: false,\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setRoleOverrides((prev) => {\n const { [k]: _, ...rest } = prev;\n return rest;\n });\n clearInFlight(k);\n });\n },\n onError: () => {\n setRoleOverrides((prev) => {\n const { [k]: _, ...rest } = prev;\n return rest;\n });\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleRemove = (s: Share) => {\n const k = keyOf(s);\n // If any other mutation is in flight for this principal, don't start a\n // remove — it can interleave with an upsert and leave the row in place.\n // The UI already disables the trash button when inFlight.has(k).\n if (inFlight.has(k)) return;\n setPendingRemoves((prev) => new Set(prev).add(k));\n addInFlight(k);\n unshare.mutate(\n {\n resourceType,\n resourceId,\n principalType: s.principalType,\n principalId: s.principalId,\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setPendingRemoves((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n clearInFlight(k);\n });\n },\n onError: () => {\n setPendingRemoves((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleDone = () => {\n if (canManage && hasInviteEmail) handleAdd();\n onClose();\n };\n\n const titleText = resourceTitle\n ? `Share \"${resourceTitle}\"`\n : `Share ${resourceType}`;\n\n if (isLoading) {\n return (\n <div>\n <div\n className=\"mb-3 truncate text-base font-semibold\"\n title={titleText}\n >\n {titleText}\n </div>\n <div className=\"mb-4 h-9 rounded-md bg-muted animate-pulse\" />\n <div className=\"mb-2 text-sm font-semibold\">People with access</div>\n <div className=\"mb-4 h-7 rounded-md bg-muted animate-pulse\" />\n <div className=\"mb-2 text-sm font-semibold\">General access</div>\n <div className=\"mb-4 h-9 rounded-md bg-muted animate-pulse\" />\n <div className=\"mt-2 flex justify-end\">\n <button type=\"button\" onClick={onClose} className={BUTTON_PRIMARY_SM}>\n Done\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div>\n <div className=\"mb-3 truncate text-base font-semibold\" title={titleText}>\n {titleText}\n </div>\n\n {canManage ? (\n <div className=\"mb-4 space-y-2\">\n <div className=\"flex items-stretch gap-2\">\n <input\n type=\"email\"\n placeholder=\"Add people by email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleAdd();\n }}\n list={orgMembers.length > 0 ? datalistId : undefined}\n autoComplete=\"off\"\n className=\"flex-1 min-w-0 h-9 rounded-md border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n {orgMembers.length > 0 ? (\n <datalist id={datalistId}>\n {orgMembers\n .filter(\n (m) =>\n m.email !== sharesQuery.data?.ownerEmail &&\n !(sharesQuery.data?.shares ?? []).some(\n (s) =>\n s.principalType === \"user\" &&\n s.principalId === m.email,\n ),\n )\n .map((m) => (\n <option\n key={m.email}\n value={m.email}\n label={m.name ?? undefined}\n />\n ))}\n </datalist>\n ) : null}\n <RoleSelect value={role} onChange={setRole} />\n </div>\n {hasInviteEmail ? (\n <label className=\"inline-flex items-center gap-2 text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n checked={notifyPeople}\n onChange={(e) => setNotifyPeople(e.target.checked)}\n className=\"h-4 w-4 rounded border-input accent-primary\"\n />\n Notify people\n </label>\n ) : null}\n </div>\n ) : null}\n\n <div className=\"mb-2 text-sm font-semibold\">People with access</div>\n <ul className=\"mb-4 flex flex-col gap-1 list-none p-0 m-0\">\n {data?.ownerEmail ? (\n <li className=\"flex items-center gap-3 px-1 py-1.5 text-sm\">\n <Avatar label={displayName(data.ownerEmail, orgMembers)} />\n <span className=\"flex-1 min-w-0 truncate\">\n {displayName(data.ownerEmail, orgMembers)}\n </span>\n <span className=\"text-xs text-muted-foreground\">Owner</span>\n </li>\n ) : null}\n {shares.map((s) => (\n <li\n key={keyOf(s)}\n className={cn(\n \"flex items-center gap-3 px-1 py-1.5 text-sm\",\n inFlight.has(keyOf(s)) && \"opacity-60\",\n )}\n >\n <Avatar\n label={\n s.principalType === \"org\"\n ? s.principalId\n : displayName(s.principalId, orgMembers)\n }\n org={s.principalType === \"org\"}\n />\n <span className=\"flex-1 min-w-0 truncate\">\n {s.principalType === \"org\"\n ? s.principalId\n : displayName(s.principalId, orgMembers)}\n </span>\n {canManage ? (\n <RoleSelect\n value={s.role}\n onChange={(r) => handleChangeRole(s, r)}\n disabled={inFlight.has(keyOf(s))}\n plain\n />\n ) : (\n <span className=\"text-xs text-muted-foreground\">\n {cap(s.role)}\n </span>\n )}\n {canManage ? (\n <button\n type=\"button\"\n aria-label=\"Remove\"\n onClick={() => handleRemove(s)}\n disabled={inFlight.has(keyOf(s))}\n className={BUTTON_GHOST_ICON}\n >\n <IconTrash size={14} />\n </button>\n ) : null}\n </li>\n ))}\n {!shares.length && !data?.ownerEmail ? (\n <li className=\"px-1 py-1.5 text-sm text-muted-foreground\">\n No one has access yet.\n </li>\n ) : null}\n </ul>\n\n <div className=\"mb-2 text-sm font-semibold\">General access</div>\n <div className=\"mb-4 flex items-center gap-3\">\n <span\n aria-hidden\n className=\"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground\"\n >\n <meta.Icon size={16} strokeWidth={1.75} />\n </span>\n <div className=\"min-w-0 flex-1\">\n <VisibilitySelect\n value={visibility}\n onChange={handleVisibility}\n disabled={!canManage}\n visibilityCopy={props.visibilityCopy}\n />\n <div className=\"mt-0.5 text-xs text-muted-foreground\">\n {meta.description}\n </div>\n </div>\n </div>\n\n {props.accessNote ? (\n <div className=\"mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground\">\n {props.accessNote}\n </div>\n ) : null}\n\n {props.shareUrl ? (\n <CopyLinkField\n value={props.shareUrl}\n label={props.shareUrlLabel}\n description={props.shareUrlDescription}\n unavailable={props.shareUrlRequiresPublic && visibility !== \"public\"}\n unavailableDescription={\n props.shareUrlUnavailableDescription ??\n (canManage\n ? \"Make general access public before copying this link.\"\n : \"This link is not public. Ask an owner or admin to make it public.\")\n }\n unavailableActionLabel={\n canManage ? \"Make public and copy\" : \"Not public\"\n }\n unavailableActionBusyLabel=\"Making public...\"\n onUnavailableAction={\n canManage ? () => onVisibilityChange(\"public\") : undefined\n }\n />\n ) : null}\n\n <div className=\"mt-2 flex justify-end\">\n <button\n type=\"button\"\n onClick={handleDone}\n className={BUTTON_PRIMARY_SM}\n >\n Done\n </button>\n </div>\n </div>\n );\n}\n\nfunction CopyLinkField({\n value,\n label = \"Share link\",\n description,\n unavailable = false,\n unavailableDescription,\n unavailableActionLabel = \"Unavailable\",\n unavailableActionBusyLabel = \"Working...\",\n onUnavailableAction,\n}: {\n value: string;\n label?: string;\n description?: ReactNode;\n unavailable?: boolean;\n unavailableDescription?: ReactNode;\n unavailableActionLabel?: string;\n unavailableActionBusyLabel?: string;\n onUnavailableAction?: () => Promise<void> | void;\n}) {\n const [copied, setCopied] = useState(false);\n const [busy, setBusy] = useState(false);\n const resetRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => {\n return () => {\n if (resetRef.current) clearTimeout(resetRef.current);\n };\n }, []);\n\n const markCopied = () => {\n setCopied(true);\n if (resetRef.current) clearTimeout(resetRef.current);\n resetRef.current = setTimeout(() => setCopied(false), 1400);\n };\n\n const copyValue = async () => {\n await navigator.clipboard.writeText(value);\n markCopied();\n };\n\n const handleCopy = async () => {\n try {\n await copyValue();\n } catch {\n setCopied(false);\n }\n };\n\n const handleUnavailableAction = async () => {\n if (!onUnavailableAction) return;\n setBusy(true);\n try {\n await onUnavailableAction();\n await copyValue();\n } catch {\n setCopied(false);\n } finally {\n setBusy(false);\n }\n };\n\n const inputValue = unavailable\n ? \"Link available after general access is Public\"\n : value;\n\n return (\n <div className=\"mb-4\">\n <div className=\"mb-2 text-sm font-semibold\">{label}</div>\n {description ? (\n <div className=\"mb-2 text-xs text-muted-foreground\">{description}</div>\n ) : null}\n {unavailable && unavailableDescription ? (\n <div className=\"mb-2 rounded-md border border-border bg-muted/35 px-3 py-2 text-xs text-muted-foreground\">\n {unavailableDescription}\n </div>\n ) : null}\n <div className=\"flex min-w-0 items-center gap-2\">\n <input\n readOnly\n disabled={unavailable}\n value={inputValue}\n aria-disabled={unavailable}\n className={cn(\n \"h-9 min-w-0 flex-1 rounded-md border border-input px-3 text-sm text-muted-foreground outline-none\",\n unavailable ? \"cursor-not-allowed bg-muted/40\" : \"bg-background\",\n )}\n onFocus={(event) => {\n if (!unavailable) event.currentTarget.select();\n }}\n />\n <button\n type=\"button\"\n onClick={unavailable ? handleUnavailableAction : handleCopy}\n disabled={unavailable && !onUnavailableAction}\n className=\"inline-flex h-9 shrink-0 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm font-medium text-foreground hover:bg-accent\"\n >\n {copied ? <IconCheck size={15} /> : <IconCopy size={15} />}\n {busy\n ? unavailableActionBusyLabel\n : unavailable\n ? unavailableActionLabel\n : copied\n ? \"Copied\"\n : \"Copy\"}\n </button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)\n// ---------------------------------------------------------------------------\n\nconst selectContentClass =\n \"z-[2100] min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\";\nconst selectItemClass =\n \"relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm py-2 pl-8 pr-3 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\";\n\ninterface ShadSelectItemProps {\n value: string;\n label: string;\n description?: string;\n}\n\nfunction SelectItems({ items }: { items: ShadSelectItemProps[] }) {\n return (\n <>\n {items.map((it) => (\n <Select.Item\n key={it.value}\n value={it.value}\n className={selectItemClass}\n >\n <span className=\"absolute left-2 top-2 flex h-4 w-4 items-center justify-center\">\n <Select.ItemIndicator>\n <IconCheck size={14} />\n </Select.ItemIndicator>\n </span>\n <span className=\"flex flex-col\">\n <Select.ItemText>{it.label}</Select.ItemText>\n {it.description ? (\n <span className=\"text-xs text-muted-foreground\">\n {it.description}\n </span>\n ) : null}\n </span>\n </Select.Item>\n ))}\n </>\n );\n}\n\nfunction RoleSelect(props: {\n value: Role;\n onChange: (v: Role) => void;\n disabled?: boolean;\n /** When true, render as inline text + chevron (no border / bg) — matches\n * the per-person role picker in Google Docs. */\n plain?: boolean;\n}) {\n const current =\n ROLE_OPTIONS.find((o) => o.value === props.value) ?? ROLE_OPTIONS[0];\n return (\n <Select.Root\n value={props.value}\n onValueChange={(v) => props.onChange(v as Role)}\n disabled={props.disabled}\n >\n <Select.Trigger\n className={\n props.plain\n ? cn(\n BUTTON_BASE,\n \"h-7 px-2 bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n )\n : cn(\n BUTTON_BASE,\n \"h-9 px-3 border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n )\n }\n aria-label=\"Role\"\n >\n <Select.Value>{current.label}</Select.Value>\n <Select.Icon>\n <IconChevronDown size={14} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className={selectContentClass}\n position=\"popper\"\n sideOffset={4}\n >\n <Select.Viewport>\n <SelectItems items={ROLE_OPTIONS} />\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction VisibilitySelect(props: {\n value: Visibility;\n onChange: (v: Visibility) => void;\n disabled?: boolean;\n visibilityCopy?: ShareButtonProps[\"visibilityCopy\"];\n}) {\n const current = visibilityMeta(props.value, props.visibilityCopy);\n return (\n <Select.Root\n value={props.value}\n onValueChange={(v) => props.onChange(v as Visibility)}\n disabled={props.disabled}\n >\n <Select.Trigger\n className={cn(\n BUTTON_BASE,\n \"h-7 px-1 -ml-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n aria-label=\"General access\"\n >\n <Select.Value>{current.label}</Select.Value>\n <Select.Icon>\n <IconChevronDown size={14} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className={selectContentClass}\n position=\"popper\"\n sideOffset={4}\n >\n <Select.Viewport>\n <SelectItems\n items={(Object.keys(VIS_META) as Visibility[]).map((k) => ({\n value: k,\n label: visibilityMeta(k, props.visibilityCopy).label,\n description: visibilityMeta(k, props.visibilityCopy)\n .description,\n }))}\n />\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction Avatar({ label, org }: { label: string; org?: boolean }) {\n return (\n <span\n aria-hidden\n className=\"inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-muted text-[11px] font-semibold text-muted-foreground\"\n >\n {org ? <IconBuilding size={14} strokeWidth={1.75} /> : initials(label)}\n </span>\n );\n}\n\nfunction keyOf(s: Share): string {\n return `${s.principalType}:${s.principalId}`;\n}\nfunction getNotificationUrl(explicit?: string): string | undefined {\n if (explicit) return explicit;\n if (typeof window === \"undefined\") return undefined;\n return window.location.href;\n}\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\nfunction initials(s: string): string {\n const name = s.split(\"@\")[0] ?? s;\n return (name[0] ?? \"?\").toUpperCase();\n}\n\nfunction displayName(email: string, members: OrgMember[]): string {\n const match = members.find((m) => m.email === email);\n if (match?.name && match.name.trim()) return match.name;\n return email;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ShareButton.js","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n IconLock,\n IconBuilding,\n IconWorld,\n IconTrash,\n IconCheck,\n IconChevronDown,\n IconCopy,\n} from \"@tabler/icons-react\";\nimport * as Select from \"@radix-ui/react-select\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { useActionQuery, useActionMutation } from \"../use-action.js\";\nimport { cn } from \"../utils.js\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport interface ShareButtonProps {\n resourceType: string;\n resourceId: string;\n resourceTitle?: string;\n /** @deprecated No longer affects rendering — trigger always says\n * \"Share\". Kept for callsite compatibility. */\n variant?: \"compact\" | \"label\";\n /** Notified when the share popover opens or closes. Hosts that render the\n * button next to an iframe use this to disable the iframe's pointer events\n * while the popover is open, so popover hover/clicks aren't swallowed. */\n onOpenChange?: (open: boolean) => void;\n /** Optional public/share URL shown as a copyable link in the popover.\n * This is treated as the primary \"Copy link\" target — same convention\n * as Google Docs' Share dialog, which copies the editor URL. */\n shareUrl?: string;\n /** Optional label for the primary copyable link section. */\n shareUrlLabel?: string;\n /** Optional helper text for the primary copyable link section. */\n shareUrlDescription?: ReactNode;\n /** Optional secondary copyable link (e.g. a presentation / read-only\n * surface for the same resource). Anyone with at least viewer access\n * can open it — access is enforced on the resource itself, not the\n * URL shape, so we never gate this behind visibility. */\n secondaryShareUrl?: string;\n /** Optional label for the secondary copyable link. */\n secondaryShareUrlLabel?: string;\n /** Optional helper text for the secondary copyable link. */\n secondaryShareUrlDescription?: ReactNode;\n /** @deprecated No longer enforced — access is checked on the resource,\n * not the URL shape, mirroring Google Slides. Kept for callsite\n * compatibility; the prop is now a no-op. */\n shareUrlRequiresPublic?: boolean;\n /** @deprecated See `shareUrlRequiresPublic`. No longer rendered. */\n shareUrlUnavailableDescription?: ReactNode;\n /** Optional template-specific copy for the visibility picker. */\n visibilityCopy?: Partial<\n Record<Visibility, { label?: string; description?: string }>\n >;\n /** Optional note rendered between general access and the copyable link. */\n accessNote?: ReactNode;\n}\n\ntype Visibility = \"private\" | \"org\" | \"public\";\ntype Role = \"viewer\" | \"editor\" | \"admin\";\n\ninterface Share {\n id: string;\n principalType: \"user\" | \"org\";\n principalId: string;\n role: Role;\n}\n\ninterface SharesResponse {\n ownerEmail: string | null;\n orgId: string | null;\n visibility: Visibility | null;\n role?: \"owner\" | Role;\n shares: Share[];\n}\n\n// Mirror shadcn's <Button size=\"sm\" variant=\"outline\"> class string so the\n// trigger sits flush next to other sm outline buttons in the template.\nconst BUTTON_BASE =\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\";\nconst BUTTON_OUTLINE_SM = cn(\n BUTTON_BASE,\n \"h-9 px-3 border border-[hsl(var(--sidebar-border,var(--input)))] bg-[hsl(var(--sidebar-background,var(--background)))] text-foreground hover:bg-[hsl(var(--sidebar-accent,var(--accent)))] hover:text-[hsl(var(--sidebar-accent-foreground,var(--accent-foreground)))]\",\n);\nconst BUTTON_PRIMARY_SM = cn(\n BUTTON_BASE,\n \"h-9 px-4 bg-primary text-primary-foreground hover:bg-primary/90\",\n);\nconst BUTTON_GHOST_ICON = cn(\n BUTTON_BASE,\n \"h-7 w-7 p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n);\nconst SHARE_POPOVER_SURFACE =\n \"border-[hsl(var(--sidebar-border,var(--border)))] bg-[hsl(var(--sidebar-background,var(--popover)))]\";\n\nconst VIS_META: Record<\n Visibility,\n { label: string; description: string; Icon: typeof IconLock }\n> = {\n private: {\n label: \"Private\",\n description: \"Only people with access can view\",\n Icon: IconLock,\n },\n org: {\n label: \"Organization\",\n description: \"Anyone in your organization can view\",\n Icon: IconBuilding,\n },\n public: {\n label: \"Public\",\n description: \"Anyone with the link can view\",\n Icon: IconWorld,\n },\n};\n\nfunction visibilityMeta(\n visibility: Visibility,\n copy?: ShareButtonProps[\"visibilityCopy\"],\n): (typeof VIS_META)[Visibility] {\n const base = VIS_META[visibility];\n const override = copy?.[visibility];\n return {\n ...base,\n label: override?.label ?? base.label,\n description: override?.description ?? base.description,\n };\n}\n\nconst ROLE_OPTIONS: Array<{ value: Role; label: string; description: string }> =\n [\n { value: \"viewer\", label: \"Viewer\", description: \"Can view\" },\n { value: \"editor\", label: \"Editor\", description: \"Can edit\" },\n {\n value: \"admin\",\n label: \"Admin\",\n description: \"Can edit and manage access\",\n },\n ];\n\n/**\n * Framework share control. Renders a shadcn-outline-styled trigger that\n * opens a Google-Docs-style popover anchored beneath it. Uses Tailwind\n * + CSS variables so the same component renders natively in light and\n * dark mode in any shadcn template.\n */\nexport function ShareButton(props: ShareButtonProps) {\n const [open, setOpen] = useState(false);\n const [pendingVisibility, setPendingVisibility] = useState<Visibility | null>(\n null,\n );\n const visibilityRequestId = useRef(0);\n const queryClient = useQueryClient();\n const shareQueryParams = useMemo(\n () => ({\n resourceType: props.resourceType,\n resourceId: props.resourceId,\n }),\n [props.resourceType, props.resourceId],\n );\n const shareQueryKey = useMemo(\n () => [\"action\", \"list-resource-shares\", shareQueryParams] as const,\n [shareQueryParams],\n );\n const setVisibility = useActionMutation(\"set-resource-visibility\");\n const sharesQuery = useActionQuery<SharesResponse>(\n \"list-resource-shares\",\n shareQueryParams,\n );\n const handleOpenChange = (v: boolean) => {\n setOpen(v);\n props.onOpenChange?.(v);\n if (v && pendingVisibility === null) sharesQuery.refetch();\n };\n\n const updateCachedVisibility = (visibility: Visibility) => {\n queryClient.setQueryData<SharesResponse>(shareQueryKey, (prev) =>\n prev ? { ...prev, visibility } : prev,\n );\n };\n\n const handleVisibilityChange = (next: Visibility): Promise<void> => {\n const requestId = ++visibilityRequestId.current;\n const previous = queryClient.getQueryData<SharesResponse>(shareQueryKey);\n setPendingVisibility(next);\n updateCachedVisibility(next);\n return new Promise((resolve, reject) => {\n setVisibility.mutate(\n {\n resourceType: props.resourceType,\n resourceId: props.resourceId,\n visibility: next,\n } as any,\n {\n onSuccess: (result: any) => {\n if (requestId === visibilityRequestId.current) {\n updateCachedVisibility(\n (result?.visibility as Visibility | undefined) ?? next,\n );\n }\n sharesQuery\n .refetch()\n .then(() => resolve())\n .catch(reject)\n .finally(() => {\n if (requestId === visibilityRequestId.current) {\n setPendingVisibility(null);\n }\n });\n },\n onError: (error) => {\n if (requestId === visibilityRequestId.current) {\n setPendingVisibility(null);\n if (previous) {\n queryClient.setQueryData(shareQueryKey, previous);\n } else {\n queryClient.invalidateQueries({ queryKey: shareQueryKey });\n }\n }\n reject(error);\n },\n },\n );\n });\n };\n\n // The trigger always says \"Share\" — the icon reflects the resource's\n // current visibility (lock / building / globe), matching Google Docs.\n // While the query is loading and we don't know the visibility yet,\n // render a skeleton placeholder in the icon slot instead of guessing.\n const loaded = sharesQuery.data !== undefined;\n const serverVisibility =\n (sharesQuery.data?.visibility as Visibility | null) ?? \"private\";\n const currentVisibility = pendingVisibility ?? serverVisibility;\n const TriggerIcon =\n currentVisibility === \"public\"\n ? IconWorld\n : currentVisibility === \"org\"\n ? IconBuilding\n : IconLock;\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <button type=\"button\" className={BUTTON_OUTLINE_SM}>\n {loaded ? (\n <TriggerIcon size={16} strokeWidth={1.75} />\n ) : (\n <span\n aria-hidden\n className=\"inline-block h-4 w-4 rounded-sm bg-muted animate-pulse\"\n />\n )}\n <span>Share</span>\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n sideOffset={6}\n className={cn(\n \"z-[2000] w-[min(460px,92vw)] rounded-lg p-4 shadow-lg\",\n SHARE_POPOVER_SURFACE,\n )}\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <SharePanel\n {...props}\n sharesQuery={sharesQuery}\n visibilityOverride={pendingVisibility}\n onVisibilityChange={handleVisibilityChange}\n onClose={() => handleOpenChange(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\ninterface OrgMember {\n email: string;\n name?: string | null;\n}\n\nfunction useOrgMembers(): OrgMember[] {\n const [members, setMembers] = useState<OrgMember[]>([]);\n useEffect(() => {\n let cancelled = false;\n fetch(agentNativePath(\"/_agent-native/org/members\"))\n .then((r) => (r.ok ? r.json() : null))\n .then((data) => {\n if (cancelled || !data) return;\n const list = Array.isArray(data?.members) ? data.members : [];\n setMembers(\n list\n .map((m: any) => ({\n email: typeof m?.email === \"string\" ? m.email : \"\",\n name: typeof m?.name === \"string\" ? m.name : null,\n }))\n .filter((m: OrgMember) => m.email),\n );\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, []);\n return members;\n}\n\nfunction SharePanel(\n props: ShareButtonProps & {\n sharesQuery: ReturnType<typeof useActionQuery<SharesResponse>>;\n visibilityOverride: Visibility | null;\n onVisibilityChange: (visibility: Visibility) => Promise<void>;\n onClose: () => void;\n },\n) {\n const {\n resourceType,\n resourceId,\n resourceTitle,\n sharesQuery,\n visibilityOverride,\n onVisibilityChange,\n onClose,\n } = props;\n\n const share = useActionMutation(\"share-resource\");\n const unshare = useActionMutation(\"unshare-resource\");\n\n const [email, setEmail] = useState(\"\");\n const [role, setRole] = useState<Role>(\"viewer\");\n const [notifyPeople, setNotifyPeople] = useState(true);\n const hasInviteEmail = email.trim().length > 0;\n const orgMembers = useOrgMembers();\n const datalistId = `share-autocomplete-${resourceType}-${resourceId}`;\n\n // Optimistic overlays so clicks feel instant.\n const [pendingAdds, setPendingAdds] = useState<Share[]>([]);\n const [pendingRemoves, setPendingRemoves] = useState<Set<string>>(new Set());\n const [roleOverrides, setRoleOverrides] = useState<Record<string, Role>>({});\n // Principals with an in-flight share/unshare mutation. We disable the\n // role dropdown and the trash button for any share in this set so a\n // user can't race a role-change against a remove (which would otherwise\n // let the upsert silently re-grant access after the delete landed), and\n // can't rapid-fire two creates for the same pending add.\n const [inFlight, setInFlight] = useState<Set<string>>(new Set());\n const addInFlight = (k: string) =>\n setInFlight((prev) => new Set(prev).add(k));\n const clearInFlight = (k: string) =>\n setInFlight((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n\n useEffect(() => {\n sharesQuery.refetch();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const data = sharesQuery.data;\n const isLoading = data === undefined;\n const visibility: Visibility =\n visibilityOverride ?? (data?.visibility as Visibility | null) ?? \"private\";\n const canManage = data?.role === \"owner\" || data?.role === \"admin\";\n const meta = visibilityMeta(visibility, props.visibilityCopy);\n\n const serverShares = data?.shares ?? [];\n const shares: Share[] = [\n ...serverShares\n .filter((s) => !pendingRemoves.has(keyOf(s)))\n .map((s) => ({ ...s, role: roleOverrides[keyOf(s)] ?? s.role })),\n ...pendingAdds,\n ];\n\n const handleVisibility = (next: Visibility) => {\n if (next === visibility) return;\n void onVisibilityChange(next).catch(() => {});\n };\n\n const handleAdd = () => {\n const trimmed = email.trim();\n if (!trimmed) return;\n const optimistic: Share = {\n id: `pending-${trimmed}`,\n principalType: \"user\",\n principalId: trimmed,\n role,\n };\n const k = keyOf(optimistic);\n // Ignore duplicate submits while an add for the same principal is in flight.\n if (inFlight.has(k)) return;\n setPendingAdds((p) => [...p, optimistic]);\n setEmail(\"\");\n addInFlight(k);\n share.mutate(\n {\n resourceType,\n resourceId,\n principalType: \"user\",\n principalId: trimmed,\n role,\n notify: notifyPeople,\n resourceUrl: getNotificationUrl(props.shareUrl),\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setPendingAdds((p) => p.filter((s) => s.id !== optimistic.id));\n clearInFlight(k);\n });\n },\n onError: () => {\n setPendingAdds((p) => p.filter((s) => s.id !== optimistic.id));\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleChangeRole = (s: Share, next: Role) => {\n if (s.role === next) return;\n const k = keyOf(s);\n // Don't stack a role change on top of an in-flight add/remove/role\n // change for the same principal — it can race with unshare and end up\n // re-granting access after a delete. UI already disables the control,\n // but belt-and-suspenders here too.\n if (inFlight.has(k)) return;\n setRoleOverrides((prev) => ({ ...prev, [k]: next }));\n addInFlight(k);\n // share-resource is upsert: calling with same principal + new role\n // updates the existing share row. See sharing/actions/share-resource.ts.\n share.mutate(\n {\n resourceType,\n resourceId,\n principalType: s.principalType,\n principalId: s.principalId,\n role: next,\n notify: false,\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setRoleOverrides((prev) => {\n const { [k]: _, ...rest } = prev;\n return rest;\n });\n clearInFlight(k);\n });\n },\n onError: () => {\n setRoleOverrides((prev) => {\n const { [k]: _, ...rest } = prev;\n return rest;\n });\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleRemove = (s: Share) => {\n const k = keyOf(s);\n // If any other mutation is in flight for this principal, don't start a\n // remove — it can interleave with an upsert and leave the row in place.\n // The UI already disables the trash button when inFlight.has(k).\n if (inFlight.has(k)) return;\n setPendingRemoves((prev) => new Set(prev).add(k));\n addInFlight(k);\n unshare.mutate(\n {\n resourceType,\n resourceId,\n principalType: s.principalType,\n principalId: s.principalId,\n } as any,\n {\n onSuccess: () => {\n sharesQuery.refetch().then(() => {\n setPendingRemoves((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n clearInFlight(k);\n });\n },\n onError: () => {\n setPendingRemoves((prev) => {\n const next = new Set(prev);\n next.delete(k);\n return next;\n });\n clearInFlight(k);\n },\n },\n );\n };\n\n const handleDone = () => {\n if (canManage && hasInviteEmail) handleAdd();\n onClose();\n };\n\n const titleText = resourceTitle\n ? `Share \"${resourceTitle}\"`\n : `Share ${resourceType}`;\n\n if (isLoading) {\n return (\n <div>\n <div\n className=\"mb-3 truncate text-base font-semibold\"\n title={titleText}\n >\n {titleText}\n </div>\n <div className=\"mb-4 h-9 rounded-md bg-muted animate-pulse\" />\n <div className=\"mb-2 text-sm font-semibold\">People with access</div>\n <div className=\"mb-4 h-7 rounded-md bg-muted animate-pulse\" />\n <div className=\"mb-2 text-sm font-semibold\">General access</div>\n <div className=\"mb-4 h-9 rounded-md bg-muted animate-pulse\" />\n <div className=\"mt-2 flex justify-end\">\n <button type=\"button\" onClick={onClose} className={BUTTON_PRIMARY_SM}>\n Done\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div>\n <div className=\"mb-3 truncate text-base font-semibold\" title={titleText}>\n {titleText}\n </div>\n\n {canManage ? (\n <div className=\"mb-4 space-y-2\">\n <div className=\"flex items-stretch gap-2\">\n <input\n type=\"email\"\n placeholder=\"Add people by email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleAdd();\n }}\n list={orgMembers.length > 0 ? datalistId : undefined}\n autoComplete=\"off\"\n className=\"flex-1 min-w-0 h-9 rounded-md border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background\"\n />\n {orgMembers.length > 0 ? (\n <datalist id={datalistId}>\n {orgMembers\n .filter(\n (m) =>\n m.email !== sharesQuery.data?.ownerEmail &&\n !(sharesQuery.data?.shares ?? []).some(\n (s) =>\n s.principalType === \"user\" &&\n s.principalId === m.email,\n ),\n )\n .map((m) => (\n <option\n key={m.email}\n value={m.email}\n label={m.name ?? undefined}\n />\n ))}\n </datalist>\n ) : null}\n <RoleSelect value={role} onChange={setRole} />\n </div>\n {hasInviteEmail ? (\n <label className=\"inline-flex items-center gap-2 text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n checked={notifyPeople}\n onChange={(e) => setNotifyPeople(e.target.checked)}\n className=\"h-4 w-4 rounded border-input accent-primary\"\n />\n Notify people\n </label>\n ) : null}\n </div>\n ) : null}\n\n <div className=\"mb-2 text-sm font-semibold\">People with access</div>\n <ul className=\"mb-4 flex flex-col gap-1 list-none p-0 m-0\">\n {data?.ownerEmail ? (\n <li className=\"flex items-center gap-3 px-1 py-1.5 text-sm\">\n <Avatar label={displayName(data.ownerEmail, orgMembers)} />\n <span className=\"flex-1 min-w-0 truncate\">\n {displayName(data.ownerEmail, orgMembers)}\n </span>\n <span className=\"text-xs text-muted-foreground\">Owner</span>\n </li>\n ) : null}\n {shares.map((s) => (\n <li\n key={keyOf(s)}\n className={cn(\n \"flex items-center gap-3 px-1 py-1.5 text-sm\",\n inFlight.has(keyOf(s)) && \"opacity-60\",\n )}\n >\n <Avatar\n label={\n s.principalType === \"org\"\n ? s.principalId\n : displayName(s.principalId, orgMembers)\n }\n org={s.principalType === \"org\"}\n />\n <span className=\"flex-1 min-w-0 truncate\">\n {s.principalType === \"org\"\n ? s.principalId\n : displayName(s.principalId, orgMembers)}\n </span>\n {canManage ? (\n <RoleSelect\n value={s.role}\n onChange={(r) => handleChangeRole(s, r)}\n disabled={inFlight.has(keyOf(s))}\n plain\n />\n ) : (\n <span className=\"text-xs text-muted-foreground\">\n {cap(s.role)}\n </span>\n )}\n {canManage ? (\n <button\n type=\"button\"\n aria-label=\"Remove\"\n onClick={() => handleRemove(s)}\n disabled={inFlight.has(keyOf(s))}\n className={BUTTON_GHOST_ICON}\n >\n <IconTrash size={14} />\n </button>\n ) : null}\n </li>\n ))}\n {!shares.length && !data?.ownerEmail ? (\n <li className=\"px-1 py-1.5 text-sm text-muted-foreground\">\n No one has access yet.\n </li>\n ) : null}\n </ul>\n\n <div className=\"mb-2 text-sm font-semibold\">General access</div>\n <div className=\"mb-4 flex items-center gap-3\">\n <span\n aria-hidden\n className=\"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground\"\n >\n <meta.Icon size={16} strokeWidth={1.75} />\n </span>\n <div className=\"min-w-0 flex-1\">\n <VisibilitySelect\n value={visibility}\n onChange={handleVisibility}\n disabled={!canManage}\n visibilityCopy={props.visibilityCopy}\n />\n <div className=\"mt-0.5 text-xs text-muted-foreground\">\n {meta.description}\n </div>\n </div>\n </div>\n\n {props.accessNote ? (\n <div className=\"mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground\">\n {props.accessNote}\n </div>\n ) : null}\n\n {props.shareUrl ? (\n <CopyLinkField\n value={props.shareUrl}\n label={props.shareUrlLabel}\n description={props.shareUrlDescription}\n />\n ) : null}\n\n {props.secondaryShareUrl ? (\n <CopyLinkField\n value={props.secondaryShareUrl}\n label={props.secondaryShareUrlLabel}\n description={props.secondaryShareUrlDescription}\n />\n ) : null}\n\n <div className=\"mt-2 flex justify-end\">\n <button\n type=\"button\"\n onClick={handleDone}\n className={BUTTON_PRIMARY_SM}\n >\n Done\n </button>\n </div>\n </div>\n );\n}\n\nfunction CopyLinkField({\n value,\n label = \"Share link\",\n description,\n}: {\n value: string;\n label?: string;\n description?: ReactNode;\n}) {\n const [copied, setCopied] = useState(false);\n const resetRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(() => {\n return () => {\n if (resetRef.current) clearTimeout(resetRef.current);\n };\n }, []);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n if (resetRef.current) clearTimeout(resetRef.current);\n resetRef.current = setTimeout(() => setCopied(false), 1400);\n } catch {\n setCopied(false);\n }\n };\n\n return (\n <div className=\"mb-4\">\n <div className=\"mb-2 text-sm font-semibold\">{label}</div>\n {description ? (\n <div className=\"mb-2 text-xs text-muted-foreground\">{description}</div>\n ) : null}\n <div className=\"flex min-w-0 items-center gap-2\">\n <input\n readOnly\n value={value}\n className=\"h-9 min-w-0 flex-1 rounded-md border border-input bg-background px-3 text-sm text-muted-foreground outline-none\"\n onFocus={(event) => event.currentTarget.select()}\n />\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"inline-flex h-9 shrink-0 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm font-medium text-foreground hover:bg-accent\"\n >\n {copied ? <IconCheck size={15} /> : <IconCopy size={15} />}\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Radix Select wrappers styled like shadcn Select (no native <select> anywhere)\n// ---------------------------------------------------------------------------\n\nconst selectContentClass =\n \"z-[2100] min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\";\nconst selectItemClass =\n \"relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm py-2 pl-8 pr-3 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\";\n\ninterface ShadSelectItemProps {\n value: string;\n label: string;\n description?: string;\n}\n\nfunction SelectItems({ items }: { items: ShadSelectItemProps[] }) {\n return (\n <>\n {items.map((it) => (\n <Select.Item\n key={it.value}\n value={it.value}\n className={selectItemClass}\n >\n <span className=\"absolute left-2 top-2 flex h-4 w-4 items-center justify-center\">\n <Select.ItemIndicator>\n <IconCheck size={14} />\n </Select.ItemIndicator>\n </span>\n <span className=\"flex flex-col\">\n <Select.ItemText>{it.label}</Select.ItemText>\n {it.description ? (\n <span className=\"text-xs text-muted-foreground\">\n {it.description}\n </span>\n ) : null}\n </span>\n </Select.Item>\n ))}\n </>\n );\n}\n\nfunction RoleSelect(props: {\n value: Role;\n onChange: (v: Role) => void;\n disabled?: boolean;\n /** When true, render as inline text + chevron (no border / bg) — matches\n * the per-person role picker in Google Docs. */\n plain?: boolean;\n}) {\n const current =\n ROLE_OPTIONS.find((o) => o.value === props.value) ?? ROLE_OPTIONS[0];\n return (\n <Select.Root\n value={props.value}\n onValueChange={(v) => props.onChange(v as Role)}\n disabled={props.disabled}\n >\n <Select.Trigger\n className={\n props.plain\n ? cn(\n BUTTON_BASE,\n \"h-7 px-2 bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground\",\n )\n : cn(\n BUTTON_BASE,\n \"h-9 px-3 border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n )\n }\n aria-label=\"Role\"\n >\n <Select.Value>{current.label}</Select.Value>\n <Select.Icon>\n <IconChevronDown size={14} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className={selectContentClass}\n position=\"popper\"\n sideOffset={4}\n >\n <Select.Viewport>\n <SelectItems items={ROLE_OPTIONS} />\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction VisibilitySelect(props: {\n value: Visibility;\n onChange: (v: Visibility) => void;\n disabled?: boolean;\n visibilityCopy?: ShareButtonProps[\"visibilityCopy\"];\n}) {\n const current = visibilityMeta(props.value, props.visibilityCopy);\n return (\n <Select.Root\n value={props.value}\n onValueChange={(v) => props.onChange(v as Visibility)}\n disabled={props.disabled}\n >\n <Select.Trigger\n className={cn(\n BUTTON_BASE,\n \"h-7 px-1 -ml-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n aria-label=\"General access\"\n >\n <Select.Value>{current.label}</Select.Value>\n <Select.Icon>\n <IconChevronDown size={14} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className={selectContentClass}\n position=\"popper\"\n sideOffset={4}\n >\n <Select.Viewport>\n <SelectItems\n items={(Object.keys(VIS_META) as Visibility[]).map((k) => ({\n value: k,\n label: visibilityMeta(k, props.visibilityCopy).label,\n description: visibilityMeta(k, props.visibilityCopy)\n .description,\n }))}\n />\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n}\n\nfunction Avatar({ label, org }: { label: string; org?: boolean }) {\n return (\n <span\n aria-hidden\n className=\"inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-muted text-[11px] font-semibold text-muted-foreground\"\n >\n {org ? <IconBuilding size={14} strokeWidth={1.75} /> : initials(label)}\n </span>\n );\n}\n\nfunction keyOf(s: Share): string {\n return `${s.principalType}:${s.principalId}`;\n}\nfunction getNotificationUrl(explicit?: string): string | undefined {\n if (explicit) return explicit;\n if (typeof window === \"undefined\") return undefined;\n return window.location.href;\n}\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\nfunction initials(s: string): string {\n const name = s.split(\"@\")[0] ?? s;\n return (name[0] ?? \"?\").toUpperCase();\n}\n\nfunction displayName(email: string, members: OrgMember[]): string {\n const match = members.find((m) => m.email === email);\n if (match?.name && match.name.trim()) return match.name;\n return email;\n}\n"]}
|
|
@@ -96,42 +96,24 @@ describe("ShareButton", () => {
|
|
|
96
96
|
resourceUrl: "https://content.agent-native.com/page/doc-1",
|
|
97
97
|
}), expect.any(Object));
|
|
98
98
|
});
|
|
99
|
-
it("
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
configurable: true,
|
|
104
|
-
});
|
|
105
|
-
await act(async () => {
|
|
106
|
-
root.render(_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ShareButton, { resourceType: "deck", resourceId: "deck-1", resourceTitle: "Launch deck", shareUrl: "https://slides.agent-native.com/p/deck-1", shareUrlRequiresPublic: true }) }));
|
|
107
|
-
});
|
|
108
|
-
const makePublicAndCopy = Array.from(container.querySelectorAll("button")).find((button) => button.textContent === "Make public and copy");
|
|
109
|
-
if (!makePublicAndCopy)
|
|
110
|
-
throw new Error("Make public button not found");
|
|
111
|
-
const linkInput = container.querySelector('input[value="Link available after general access is Public"]');
|
|
112
|
-
expect(linkInput).toBeTruthy();
|
|
99
|
+
it("shows the copy action for share URLs regardless of visibility", async () => {
|
|
100
|
+
// Mirrors Google Slides: the copy button is always live. Access is
|
|
101
|
+
// enforced when the recipient opens the URL, not by hiding the link in
|
|
102
|
+
// the share dialog.
|
|
113
103
|
await act(async () => {
|
|
114
|
-
|
|
104
|
+
root.render(_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ShareButton, { resourceType: "deck", resourceId: "deck-1", shareUrl: "https://slides.agent-native.com/deck/deck-1" }) }));
|
|
115
105
|
});
|
|
116
|
-
expect(
|
|
117
|
-
resourceType: "deck",
|
|
118
|
-
resourceId: "deck-1",
|
|
119
|
-
visibility: "public",
|
|
120
|
-
}), expect.any(Object));
|
|
121
|
-
expect(writeText).not.toHaveBeenCalled();
|
|
106
|
+
expect(Array.from(container.querySelectorAll("button")).some((button) => button.textContent === "Copy")).toBe(true);
|
|
122
107
|
});
|
|
123
|
-
it("
|
|
124
|
-
sharesData.current = {
|
|
125
|
-
ownerEmail: "owner@example.com",
|
|
126
|
-
orgId: null,
|
|
127
|
-
visibility: "public",
|
|
128
|
-
role: "owner",
|
|
129
|
-
shares: [],
|
|
130
|
-
};
|
|
108
|
+
it("renders both primary and secondary share URLs", async () => {
|
|
131
109
|
await act(async () => {
|
|
132
|
-
root.render(_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ShareButton, { resourceType: "deck", resourceId: "deck-1", shareUrl: "https://slides.agent-native.com/p/deck-1",
|
|
110
|
+
root.render(_jsx(QueryClientProvider, { client: queryClient, children: _jsx(ShareButton, { resourceType: "deck", resourceId: "deck-1", shareUrl: "https://slides.agent-native.com/deck/deck-1", shareUrlLabel: "Editor link", secondaryShareUrl: "https://slides.agent-native.com/p/deck-1", secondaryShareUrlLabel: "Presentation link" }) }));
|
|
133
111
|
});
|
|
134
|
-
|
|
112
|
+
const inputs = Array.from(container.querySelectorAll("input"));
|
|
113
|
+
const editorInput = inputs.find((i) => i.value === "https://slides.agent-native.com/deck/deck-1");
|
|
114
|
+
const presentationInput = inputs.find((i) => i.value === "https://slides.agent-native.com/p/deck-1");
|
|
115
|
+
expect(editorInput).toBeTruthy();
|
|
116
|
+
expect(presentationInput).toBeTruthy();
|
|
135
117
|
});
|
|
136
118
|
});
|
|
137
119
|
//# sourceMappingURL=ShareButton.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShareButton.spec.js","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\nimport React, { act } from \"react\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { ShareButton } from \"./ShareButton.js\";\n\nconst shareMutate = vi.hoisted(() => vi.fn());\nconst otherMutate = vi.hoisted(() => vi.fn());\nconst refetchShares = vi.hoisted(() => vi.fn(async () => undefined));\nconst sharesData = vi.hoisted(() => ({\n current: {\n ownerEmail: \"owner@example.com\",\n orgId: null,\n visibility: \"private\",\n role: \"owner\",\n shares: [],\n },\n}));\n\nvi.mock(\"../use-action.js\", () => ({\n useActionQuery: () => ({\n data: sharesData.current,\n refetch: refetchShares,\n }),\n useActionMutation: (name: string) => ({\n mutate: name === \"share-resource\" ? shareMutate : otherMutate,\n }),\n}));\n\nvi.mock(\"../components/ui/popover.js\", () => ({\n Popover: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n PopoverTrigger: ({ children }: { children: React.ReactNode }) => (\n <>{children}</>\n ),\n PopoverContent: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n}));\n\nfunction setInputValue(input: HTMLInputElement, value: string) {\n const setter = Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(input),\n \"value\",\n )?.set;\n act(() => {\n setter?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n });\n}\n\ndescribe(\"ShareButton\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let queryClient: QueryClient;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n Response.json({\n members: [],\n }),\n ),\n );\n shareMutate.mockReset();\n otherMutate.mockReset();\n refetchShares.mockClear();\n sharesData.current = {\n ownerEmail: \"owner@example.com\",\n orgId: null,\n visibility: \"private\",\n role: \"owner\",\n shares: [],\n };\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n mutations: { retry: false },\n },\n });\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n queryClient.clear();\n container.remove();\n vi.unstubAllGlobals();\n });\n\n it(\"submits a typed email invite when Done is clicked\", async () => {\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"document\"\n resourceId=\"doc-1\"\n resourceTitle=\"Launch notes\"\n shareUrl=\"https://content.agent-native.com/page/doc-1\"\n />\n </QueryClientProvider>,\n );\n });\n\n const input = container.querySelector(\n 'input[placeholder=\"Add people by email\"]',\n ) as HTMLInputElement;\n setInputValue(input, \"teammate@example.com\");\n\n const done = Array.from(container.querySelectorAll(\"button\")).find(\n (button) => button.textContent === \"Done\",\n );\n if (!done) throw new Error(\"Done button not found\");\n\n act(() => {\n done.click();\n });\n\n expect(shareMutate).toHaveBeenCalledWith(\n expect.objectContaining({\n resourceType: \"document\",\n resourceId: \"doc-1\",\n principalType: \"user\",\n principalId: \"teammate@example.com\",\n role: \"viewer\",\n notify: true,\n resourceUrl: \"https://content.agent-native.com/page/doc-1\",\n }),\n expect.any(Object),\n );\n });\n\n it(\"requires public visibility before copying a public-only link\", async () => {\n const writeText = vi.fn(async () => undefined);\n Object.defineProperty(navigator, \"clipboard\", {\n value: { writeText },\n configurable: true,\n });\n\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"deck\"\n resourceId=\"deck-1\"\n resourceTitle=\"Launch deck\"\n shareUrl=\"https://slides.agent-native.com/p/deck-1\"\n shareUrlRequiresPublic\n />\n </QueryClientProvider>,\n );\n });\n\n const makePublicAndCopy = Array.from(\n container.querySelectorAll(\"button\"),\n ).find((button) => button.textContent === \"Make public and copy\");\n if (!makePublicAndCopy) throw new Error(\"Make public button not found\");\n\n const linkInput = container.querySelector(\n 'input[value=\"Link available after general access is Public\"]',\n );\n expect(linkInput).toBeTruthy();\n\n await act(async () => {\n makePublicAndCopy.click();\n });\n\n expect(otherMutate).toHaveBeenCalledWith(\n expect.objectContaining({\n resourceType: \"deck\",\n resourceId: \"deck-1\",\n visibility: \"public\",\n }),\n expect.any(Object),\n );\n expect(writeText).not.toHaveBeenCalled();\n });\n\n it(\"shows the copy action for public public-only links\", async () => {\n sharesData.current = {\n ownerEmail: \"owner@example.com\",\n orgId: null,\n visibility: \"public\",\n role: \"owner\",\n shares: [],\n };\n\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"deck\"\n resourceId=\"deck-1\"\n shareUrl=\"https://slides.agent-native.com/p/deck-1\"\n shareUrlRequiresPublic\n />\n </QueryClientProvider>,\n );\n });\n\n expect(\n Array.from(container.querySelectorAll(\"button\")).some(\n (button) => button.textContent === \"Copy\",\n ),\n ).toBe(true);\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"ShareButton.spec.js","sourceRoot":"","sources":["../../../src/client/sharing/ShareButton.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\nimport React, { act } from \"react\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { ShareButton } from \"./ShareButton.js\";\n\nconst shareMutate = vi.hoisted(() => vi.fn());\nconst otherMutate = vi.hoisted(() => vi.fn());\nconst refetchShares = vi.hoisted(() => vi.fn(async () => undefined));\nconst sharesData = vi.hoisted(() => ({\n current: {\n ownerEmail: \"owner@example.com\",\n orgId: null,\n visibility: \"private\",\n role: \"owner\",\n shares: [],\n },\n}));\n\nvi.mock(\"../use-action.js\", () => ({\n useActionQuery: () => ({\n data: sharesData.current,\n refetch: refetchShares,\n }),\n useActionMutation: (name: string) => ({\n mutate: name === \"share-resource\" ? shareMutate : otherMutate,\n }),\n}));\n\nvi.mock(\"../components/ui/popover.js\", () => ({\n Popover: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n PopoverTrigger: ({ children }: { children: React.ReactNode }) => (\n <>{children}</>\n ),\n PopoverContent: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n}));\n\nfunction setInputValue(input: HTMLInputElement, value: string) {\n const setter = Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(input),\n \"value\",\n )?.set;\n act(() => {\n setter?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n input.dispatchEvent(new Event(\"change\", { bubbles: true }));\n });\n}\n\ndescribe(\"ShareButton\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let queryClient: QueryClient;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n Response.json({\n members: [],\n }),\n ),\n );\n shareMutate.mockReset();\n otherMutate.mockReset();\n refetchShares.mockClear();\n sharesData.current = {\n ownerEmail: \"owner@example.com\",\n orgId: null,\n visibility: \"private\",\n role: \"owner\",\n shares: [],\n };\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n mutations: { retry: false },\n },\n });\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n queryClient.clear();\n container.remove();\n vi.unstubAllGlobals();\n });\n\n it(\"submits a typed email invite when Done is clicked\", async () => {\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"document\"\n resourceId=\"doc-1\"\n resourceTitle=\"Launch notes\"\n shareUrl=\"https://content.agent-native.com/page/doc-1\"\n />\n </QueryClientProvider>,\n );\n });\n\n const input = container.querySelector(\n 'input[placeholder=\"Add people by email\"]',\n ) as HTMLInputElement;\n setInputValue(input, \"teammate@example.com\");\n\n const done = Array.from(container.querySelectorAll(\"button\")).find(\n (button) => button.textContent === \"Done\",\n );\n if (!done) throw new Error(\"Done button not found\");\n\n act(() => {\n done.click();\n });\n\n expect(shareMutate).toHaveBeenCalledWith(\n expect.objectContaining({\n resourceType: \"document\",\n resourceId: \"doc-1\",\n principalType: \"user\",\n principalId: \"teammate@example.com\",\n role: \"viewer\",\n notify: true,\n resourceUrl: \"https://content.agent-native.com/page/doc-1\",\n }),\n expect.any(Object),\n );\n });\n\n it(\"shows the copy action for share URLs regardless of visibility\", async () => {\n // Mirrors Google Slides: the copy button is always live. Access is\n // enforced when the recipient opens the URL, not by hiding the link in\n // the share dialog.\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"deck\"\n resourceId=\"deck-1\"\n shareUrl=\"https://slides.agent-native.com/deck/deck-1\"\n />\n </QueryClientProvider>,\n );\n });\n\n expect(\n Array.from(container.querySelectorAll(\"button\")).some(\n (button) => button.textContent === \"Copy\",\n ),\n ).toBe(true);\n });\n\n it(\"renders both primary and secondary share URLs\", async () => {\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <ShareButton\n resourceType=\"deck\"\n resourceId=\"deck-1\"\n shareUrl=\"https://slides.agent-native.com/deck/deck-1\"\n shareUrlLabel=\"Editor link\"\n secondaryShareUrl=\"https://slides.agent-native.com/p/deck-1\"\n secondaryShareUrlLabel=\"Presentation link\"\n />\n </QueryClientProvider>,\n );\n });\n\n const inputs = Array.from(container.querySelectorAll(\"input\"));\n const editorInput = inputs.find(\n (i) => i.value === \"https://slides.agent-native.com/deck/deck-1\",\n );\n const presentationInput = inputs.find(\n (i) => i.value === \"https://slides.agent-native.com/p/deck-1\",\n );\n expect(editorInput).toBeTruthy();\n expect(presentationInput).toBeTruthy();\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ssr-handler.d.ts","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AAgMA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,2FAgE5E"}
|
|
@@ -18,6 +18,22 @@
|
|
|
18
18
|
import { createRequestHandler } from "react-router";
|
|
19
19
|
import { defineEventHandler } from "h3";
|
|
20
20
|
import { getSentryClientConfigScript } from "./sentry-config.js";
|
|
21
|
+
import { getSession } from "./auth.js";
|
|
22
|
+
import { runWithRequestContext } from "./request-context.js";
|
|
23
|
+
/**
|
|
24
|
+
* Read the active org for a request without forcing every template to bundle
|
|
25
|
+
* the org module. Mirrors what `core-routes-plugin` does for action handlers.
|
|
26
|
+
*/
|
|
27
|
+
async function readOrgIdForEvent(event) {
|
|
28
|
+
try {
|
|
29
|
+
const { getOrgContext } = await import("../org/context.js");
|
|
30
|
+
const ctx = await getOrgContext(event);
|
|
31
|
+
return ctx?.orgId ?? undefined;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
21
37
|
function normalizeAppBasePath(value) {
|
|
22
38
|
if (!value || value === "/")
|
|
23
39
|
return "";
|
|
@@ -160,20 +176,37 @@ export function createH3SSRHandler(getBuild) {
|
|
|
160
176
|
}
|
|
161
177
|
try {
|
|
162
178
|
const request = requestWithPathname(event.req, p, basePath);
|
|
179
|
+
// Pin the active session onto the async request context so React Router
|
|
180
|
+
// loaders that call `getRequestUserEmail()` / `accessFilter()` see the
|
|
181
|
+
// signed-in user. Without this, SSR loaders fall through to the
|
|
182
|
+
// unauthenticated branch even when the user is logged in — which broke
|
|
183
|
+
// shared-deck "Presentation link" access for non-public decks.
|
|
184
|
+
let session = null;
|
|
185
|
+
try {
|
|
186
|
+
session = await getSession(event);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Auth lookup failures must not break SSR; treat as unauthenticated.
|
|
190
|
+
}
|
|
191
|
+
const orgId = session?.email ? await readOrgIdForEvent(event) : undefined;
|
|
192
|
+
const ctx = {
|
|
193
|
+
userEmail: session?.email ?? undefined,
|
|
194
|
+
orgId,
|
|
195
|
+
};
|
|
163
196
|
if (request.method === "HEAD") {
|
|
164
197
|
const getRequest = new Request(request.url, {
|
|
165
198
|
method: "GET",
|
|
166
199
|
headers: request.headers,
|
|
167
200
|
signal: request.signal,
|
|
168
201
|
});
|
|
169
|
-
const response = await handler(getRequest);
|
|
202
|
+
const response = await runWithRequestContext(ctx, () => handler(getRequest));
|
|
170
203
|
return await rewriteMountedResponse(new Response(null, {
|
|
171
204
|
status: response.status,
|
|
172
205
|
statusText: response.statusText,
|
|
173
206
|
headers: response.headers,
|
|
174
207
|
}), basePath);
|
|
175
208
|
}
|
|
176
|
-
return await rewriteMountedResponse(await handler(request), basePath);
|
|
209
|
+
return await rewriteMountedResponse(await runWithRequestContext(ctx, () => handler(request)), basePath);
|
|
177
210
|
}
|
|
178
211
|
catch (err) {
|
|
179
212
|
// Log the full stack server-side, but never leak it to the client.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEjE,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IAC3C,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,OAAO,GACX,MAAM,CAAC,IAGR,CAAC,GAAG,CAAC;IACN,OAAO,oBAAoB,CACzB,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC5B,OAAO,CAAC,GAAG,CAAC,aAAa;QACzB,OAAO,EAAE,kBAAkB;QAC3B,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,QAAQ,CACpB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAgB;IACxC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,OAAO,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC/B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACtC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,QAAQ,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,aAAa,GAAG,KAAK;iBACxB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;iBAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;gBAC5B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBAC7C,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxB,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,MAAM,IAAI,GAAsC;QAC9C,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,IAAI;SACR,OAAO,CACN,iEAAiE,EACjE,CAAC,MAAM,EAAE,IAAY,EAAE,KAAa,EAAE,IAAY,EAAE,EAAE,CACpD,GAAG,IAAI,IAAI,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,KAAK,EAAE,CACjE;SACA,OAAO,CAAC,qCAAqC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtE,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAqB;IAC3D,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,sBAAsB,CAAC,QAAgB;IAC9C,OAAO,CACL,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC;QACpC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACtC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACtC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAC9B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,KAAK,iBAAiB;QAC9B,QAAQ,KAAK,cAAc;QAC3B,QAAQ,KAAK,mBAAmB;QAChC,QAAQ,KAAK,cAAc;QAC3B,QAAQ,KAAK,cAAc;QAC3B,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,QAAkB,EAClB,QAAgB;IAEhB,MAAM,wBAAwB,GAAG,2BAA2B,EAAE,CAAC;IAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,wBAAwB;QAAE,OAAO,QAAQ,CAAC;IAE5D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvE,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;YACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,OAAO,IAAI,QAAQ,CACjB,gBAAgB,CACd,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,EACjC,wBAAwB,CACzB,EACD;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,OAAO;KACR,CACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAA0C;IAC3E,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAe,CAAC,CAAC;IACtD,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAc,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvE,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC1C,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;iBACvB,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC3C,OAAO,MAAM,sBAAsB,CACjC,IAAI,QAAQ,CAAC,IAAI,EAAE;oBACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B,CAAC,EACF,QAAQ,CACT,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,sBAAsB,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mEAAmE;YACnE,uEAAuE;YACvE,sEAAsE;YACtE,oEAAoE;YACpE,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;YACrD,MAAM,IAAI,GAAG,MAAM;gBACjB,CAAC,CAAC,uBAAuB;gBACzB,CAAC,CAAC,0BAA2B,GAAa,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC;YAC/D,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;gBACxB,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE;aAC1C,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n const metaEnv = (\n import.meta as unknown as {\n env?: Record<string, string | undefined>;\n }\n ).env;\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH ||\n process.env.APP_BASE_PATH ||\n metaEnv?.VITE_APP_BASE_PATH ||\n metaEnv?.APP_BASE_PATH ||\n metaEnv?.BASE_URL,\n );\n}\n\nfunction stripAppBasePath(pathname: string): string {\n const basePath = getAppBasePath();\n return stripBasePath(pathname, basePath);\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n if (!basePath && !sentryClientConfigScript) return response;\n\n const headers = new Headers(response.headers);\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n prefixMountedHtml(html, basePath),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await handler(getRequest);\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n );\n }\n return await rewriteMountedResponse(await handler(request), basePath);\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler, type H3Event } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\nimport { getSession } from \"./auth.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\n/**\n * Read the active org for a request without forcing every template to bundle\n * the org module. Mirrors what `core-routes-plugin` does for action handlers.\n */\nasync function readOrgIdForEvent(event: H3Event): Promise<string | undefined> {\n try {\n const { getOrgContext } = await import(\"../org/context.js\");\n const ctx = await getOrgContext(event);\n return ctx?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n const metaEnv = (\n import.meta as unknown as {\n env?: Record<string, string | undefined>;\n }\n ).env;\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH ||\n process.env.APP_BASE_PATH ||\n metaEnv?.VITE_APP_BASE_PATH ||\n metaEnv?.APP_BASE_PATH ||\n metaEnv?.BASE_URL,\n );\n}\n\nfunction stripAppBasePath(pathname: string): string {\n const basePath = getAppBasePath();\n return stripBasePath(pathname, basePath);\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n if (!basePath && !sentryClientConfigScript) return response;\n\n const headers = new Headers(response.headers);\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n return new Response(\n injectHeadScript(\n prefixMountedHtml(html, basePath),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n // Pin the active session onto the async request context so React Router\n // loaders that call `getRequestUserEmail()` / `accessFilter()` see the\n // signed-in user. Without this, SSR loaders fall through to the\n // unauthenticated branch even when the user is logged in — which broke\n // shared-deck \"Presentation link\" access for non-public decks.\n let session: Awaited<ReturnType<typeof getSession>> | null = null;\n try {\n session = await getSession(event);\n } catch {\n // Auth lookup failures must not break SSR; treat as unauthenticated.\n }\n const orgId = session?.email ? await readOrgIdForEvent(event) : undefined;\n const ctx = {\n userEmail: session?.email ?? undefined,\n orgId,\n };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
|