@puckeditor/plugin-ai 0.8.3-canary.70014e71 → 0.8.3-canary.8cefba87
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/index.js +166 -30
- package/dist/index.mjs +166 -30
- package/package.json +11 -8
package/dist/index.js
CHANGED
|
@@ -742,7 +742,7 @@ var import_ulid2 = require("ulid");
|
|
|
742
742
|
// src/components/Chat/index.tsx
|
|
743
743
|
init_react_import();
|
|
744
744
|
|
|
745
|
-
// ../../node_modules/.pnpm/@ai-sdk+react@3.0.232_react@19.2.8_zod@
|
|
745
|
+
// ../../node_modules/.pnpm/@ai-sdk+react@3.0.232_react@19.2.8_zod@3.25.76/node_modules/@ai-sdk/react/dist/index.mjs
|
|
746
746
|
init_react_import();
|
|
747
747
|
var import_ai = require("ai");
|
|
748
748
|
var import_react4 = require("react");
|
|
@@ -3420,6 +3420,29 @@ var syncFieldValues = (entry, fields, props) => {
|
|
|
3420
3420
|
});
|
|
3421
3421
|
}
|
|
3422
3422
|
};
|
|
3423
|
+
var claimedHostStyles = /* @__PURE__ */ new WeakMap();
|
|
3424
|
+
var claimHostStyles = (el, applyWhiteSpace) => {
|
|
3425
|
+
if (!claimedHostStyles.has(el)) {
|
|
3426
|
+
claimedHostStyles.set(el, {
|
|
3427
|
+
cursor: el.style.cursor,
|
|
3428
|
+
whiteSpace: applyWhiteSpace ? el.style.whiteSpace : null
|
|
3429
|
+
});
|
|
3430
|
+
}
|
|
3431
|
+
applyHostStyles(el);
|
|
3432
|
+
};
|
|
3433
|
+
var applyHostStyles = (el) => {
|
|
3434
|
+
const claimed = claimedHostStyles.get(el);
|
|
3435
|
+
if (!claimed) return;
|
|
3436
|
+
el.style.cursor = "text";
|
|
3437
|
+
if (claimed.whiteSpace !== null) el.style.whiteSpace = "pre-wrap";
|
|
3438
|
+
};
|
|
3439
|
+
var releaseHostStyles = (el) => {
|
|
3440
|
+
const claimed = claimedHostStyles.get(el);
|
|
3441
|
+
if (!claimed) return;
|
|
3442
|
+
el.style.cursor = claimed.cursor;
|
|
3443
|
+
if (claimed.whiteSpace !== null) el.style.whiteSpace = claimed.whiteSpace;
|
|
3444
|
+
claimedHostStyles.delete(el);
|
|
3445
|
+
};
|
|
3423
3446
|
var attachInlineEditing = (el, {
|
|
3424
3447
|
componentId,
|
|
3425
3448
|
propPath,
|
|
@@ -3432,8 +3455,7 @@ var attachInlineEditing = (el, {
|
|
|
3432
3455
|
const syncEditable = () => {
|
|
3433
3456
|
el.contentEditable = hovering || focused ? mode === "richtext" ? "true" : "plaintext-only" : "false";
|
|
3434
3457
|
};
|
|
3435
|
-
|
|
3436
|
-
el.style.cursor = "text";
|
|
3458
|
+
claimHostStyles(el, mode !== "richtext");
|
|
3437
3459
|
syncEditable();
|
|
3438
3460
|
let lastValidNumberText = el.innerText.replaceAll(/\n/gm, "");
|
|
3439
3461
|
const handleInput = () => {
|
|
@@ -3511,7 +3533,7 @@ var attachInlineEditing = (el, {
|
|
|
3511
3533
|
el.removeEventListener("mouseout", handleMouseOut, true);
|
|
3512
3534
|
el.removeEventListener("focus", handleFocus);
|
|
3513
3535
|
el.removeEventListener("blur", handleBlur);
|
|
3514
|
-
el
|
|
3536
|
+
releaseHostStyles(el);
|
|
3515
3537
|
el.removeAttribute("contenteditable");
|
|
3516
3538
|
cleanupPortal?.();
|
|
3517
3539
|
};
|
|
@@ -3577,7 +3599,7 @@ var wireArrayItemEditing = ({
|
|
|
3577
3599
|
const mode = inlineEditModeFor(field);
|
|
3578
3600
|
const registration = wiring.get(target);
|
|
3579
3601
|
if (registration?.propPath === propPath && registration.mode === mode) {
|
|
3580
|
-
target
|
|
3602
|
+
applyHostStyles(target);
|
|
3581
3603
|
continue;
|
|
3582
3604
|
}
|
|
3583
3605
|
registration?.cleanup();
|
|
@@ -3903,7 +3925,7 @@ function createDesignComponentConfig(registration) {
|
|
|
3903
3925
|
morphed.current = { el: entryEl, html, attrSig };
|
|
3904
3926
|
morphHtml(entryEl, html, attrFields);
|
|
3905
3927
|
for (const el of fieldWiring.current.keys()) {
|
|
3906
|
-
if (el.isConnected) el
|
|
3928
|
+
if (el.isConnected) applyHostStyles(el);
|
|
3907
3929
|
}
|
|
3908
3930
|
}
|
|
3909
3931
|
syncFieldValues(entryEl, annotations.fields, props);
|
|
@@ -4062,9 +4084,11 @@ function getDynamicConfigGlobals(dynamicConfig) {
|
|
|
4062
4084
|
...typeof script === "string" ? { script } : {}
|
|
4063
4085
|
};
|
|
4064
4086
|
}
|
|
4087
|
+
var INLINE_EDIT_RESET = ":where([data-puck-design] [contenteditable]){overflow-wrap:inherit;line-break:inherit;-webkit-nbsp-mode:inherit}";
|
|
4065
4088
|
function DesignGlobals({
|
|
4066
4089
|
styles,
|
|
4067
|
-
script
|
|
4090
|
+
script,
|
|
4091
|
+
isEditing
|
|
4068
4092
|
}) {
|
|
4069
4093
|
const scriptRef = (0, import_react25.useRef)(null);
|
|
4070
4094
|
const hostRef = (0, import_react25.useRef)(null);
|
|
@@ -4082,6 +4106,7 @@ function DesignGlobals({
|
|
|
4082
4106
|
};
|
|
4083
4107
|
}, [script]);
|
|
4084
4108
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
4109
|
+
isEditing && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("style", { children: INLINE_EDIT_RESET }),
|
|
4085
4110
|
styles && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("style", { children: styles }),
|
|
4086
4111
|
script && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: hostRef, style: { display: "none" } })
|
|
4087
4112
|
] });
|
|
@@ -4094,7 +4119,14 @@ function withDesignGlobals(root) {
|
|
|
4094
4119
|
const render = (props) => {
|
|
4095
4120
|
const { styles, script } = getDynamicConfigGlobals(props._dynamicConfig);
|
|
4096
4121
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
4097
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
4122
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
4123
|
+
DesignGlobals,
|
|
4124
|
+
{
|
|
4125
|
+
styles,
|
|
4126
|
+
script,
|
|
4127
|
+
isEditing: props.puck?.isEditing
|
|
4128
|
+
}
|
|
4129
|
+
),
|
|
4098
4130
|
userRender ? userRender(props) : props.children
|
|
4099
4131
|
] });
|
|
4100
4132
|
};
|
|
@@ -4360,12 +4392,28 @@ var waitForIframeReady = async (root, imageTimeout = 1e4) => {
|
|
|
4360
4392
|
await waitForNextPaint(document2);
|
|
4361
4393
|
};
|
|
4362
4394
|
|
|
4395
|
+
// src/lib/client-tool-response.ts
|
|
4396
|
+
init_react_import();
|
|
4397
|
+
async function postClientToolResponse(host, body) {
|
|
4398
|
+
const response = await fetch(`${host.replace(/\/+$/, "")}/tool`, {
|
|
4399
|
+
method: "POST",
|
|
4400
|
+
headers: { "Content-Type": "application/json" },
|
|
4401
|
+
body: JSON.stringify(body)
|
|
4402
|
+
});
|
|
4403
|
+
if (!response.ok) {
|
|
4404
|
+
throw new Error(
|
|
4405
|
+
`Client tool endpoint returned ${response.status} ${response.statusText}`.trim()
|
|
4406
|
+
);
|
|
4407
|
+
}
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4363
4410
|
// src/components/Chat/index.tsx
|
|
4364
4411
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
4365
4412
|
var q = (0, import_qler.default)();
|
|
4366
4413
|
var DEFAULT_API_VERSION = "v2";
|
|
4367
4414
|
var BUILD_OP_DEBOUNCE_MS = 1e3 / 60;
|
|
4368
|
-
var
|
|
4415
|
+
var CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE = "Unable to verify the page data. Please enable the `/chat/tool` endpoint on the server and try again.";
|
|
4416
|
+
var PLUGIN_AI_VERSION = true ? "0.8.3-canary.8cefba87" : "unknown";
|
|
4369
4417
|
var BENCHMARK = false;
|
|
4370
4418
|
var prefixedUlid = (prefix = "") => `${prefix ? `${prefix}_` : ""}${(0, import_ulid.ulid)()}`;
|
|
4371
4419
|
var getClassName18 = getClassNameFactory("Chat", styles_module_default);
|
|
@@ -4403,10 +4451,14 @@ function Chat2(props) {
|
|
|
4403
4451
|
}, [puckData, getPuck]);
|
|
4404
4452
|
const [error, setError] = (0, import_react27.useState)();
|
|
4405
4453
|
const [userError, setUserError] = (0, import_react27.useState)();
|
|
4454
|
+
const clientToolEndpointUnavailableRef = (0, import_react27.useRef)(false);
|
|
4455
|
+
const stopChatRef = (0, import_react27.useRef)(null);
|
|
4406
4456
|
const [composerAttachments, setComposerAttachments] = (0, import_react27.useState)([]);
|
|
4407
4457
|
const removedAttachmentClientIdsRef = (0, import_react27.useRef)(/* @__PURE__ */ new Set());
|
|
4408
4458
|
const uploadControllersRef = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
|
|
4409
4459
|
const pendingBuildOpsRef = (0, import_react27.useRef)([]);
|
|
4460
|
+
const lastStreamActivityRef = (0, import_react27.useRef)(0);
|
|
4461
|
+
const hiddenSinceRef = (0, import_react27.useRef)(null);
|
|
4410
4462
|
const [toolStatus, setToolStatus] = (0, import_react27.useState)({});
|
|
4411
4463
|
const [subagentState, setSubagentState] = (0, import_react27.useState)({});
|
|
4412
4464
|
const attachmentConfig = (0, import_react27.useMemo)(
|
|
@@ -4517,8 +4569,43 @@ function Chat2(props) {
|
|
|
4517
4569
|
},
|
|
4518
4570
|
[debouncedFlushBuildOps]
|
|
4519
4571
|
);
|
|
4572
|
+
const handleClientToolEndpointUnavailable = (0, import_react27.useCallback)(() => {
|
|
4573
|
+
if (clientToolEndpointUnavailableRef.current) return;
|
|
4574
|
+
clientToolEndpointUnavailableRef.current = true;
|
|
4575
|
+
setError(CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE);
|
|
4576
|
+
console.error(CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE);
|
|
4577
|
+
setToolStatus((current) => {
|
|
4578
|
+
let changed = false;
|
|
4579
|
+
const next = {};
|
|
4580
|
+
for (const [id, toolState] of Object.entries(current)) {
|
|
4581
|
+
if (toolState.loading) {
|
|
4582
|
+
changed = true;
|
|
4583
|
+
next[id] = {
|
|
4584
|
+
...toolState,
|
|
4585
|
+
loading: false,
|
|
4586
|
+
label: "Verification unavailable"
|
|
4587
|
+
};
|
|
4588
|
+
} else {
|
|
4589
|
+
next[id] = toolState;
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4592
|
+
return changed ? next : current;
|
|
4593
|
+
});
|
|
4594
|
+
stopChatRef.current?.();
|
|
4595
|
+
}, []);
|
|
4596
|
+
const sendClientToolResponse = (0, import_react27.useCallback)(
|
|
4597
|
+
async (body) => {
|
|
4598
|
+
try {
|
|
4599
|
+
await postClientToolResponse(host, body);
|
|
4600
|
+
} catch {
|
|
4601
|
+
handleClientToolEndpointUnavailable();
|
|
4602
|
+
}
|
|
4603
|
+
},
|
|
4604
|
+
[handleClientToolEndpointUnavailable, host]
|
|
4605
|
+
);
|
|
4520
4606
|
const processData = (0, import_react27.useCallback)(
|
|
4521
4607
|
(dataPart) => {
|
|
4608
|
+
lastStreamActivityRef.current = Date.now();
|
|
4522
4609
|
switch (dataPart.type) {
|
|
4523
4610
|
case "data-new-chat-created": {
|
|
4524
4611
|
localChatId.current = dataPart.data.chatId;
|
|
@@ -4549,13 +4636,9 @@ function Chat2(props) {
|
|
|
4549
4636
|
debouncedFlushBuildOps.flush();
|
|
4550
4637
|
q.wait().then(() => {
|
|
4551
4638
|
const { appState } = getPuck();
|
|
4552
|
-
return
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
body: JSON.stringify({
|
|
4556
|
-
id: requestId,
|
|
4557
|
-
responses: [{ action, output: appState.data }]
|
|
4558
|
-
})
|
|
4639
|
+
return sendClientToolResponse({
|
|
4640
|
+
id: requestId,
|
|
4641
|
+
responses: [{ action, output: appState.data }]
|
|
4559
4642
|
});
|
|
4560
4643
|
}).catch((e) => {
|
|
4561
4644
|
console.error("Failed to respond to client request:", e);
|
|
@@ -4597,13 +4680,9 @@ function Chat2(props) {
|
|
|
4597
4680
|
`Upload failed with status ${uploadResponse.status}`
|
|
4598
4681
|
);
|
|
4599
4682
|
}
|
|
4600
|
-
return
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
body: JSON.stringify({
|
|
4604
|
-
id: requestId,
|
|
4605
|
-
responses: [{ action, output: { sizeBytes: blob.size } }]
|
|
4606
|
-
})
|
|
4683
|
+
return sendClientToolResponse({
|
|
4684
|
+
id: requestId,
|
|
4685
|
+
responses: [{ action, output: { sizeBytes: blob.size } }]
|
|
4607
4686
|
});
|
|
4608
4687
|
}).catch((e) => {
|
|
4609
4688
|
console.error("Failed to respond to client request:", e);
|
|
@@ -4650,6 +4729,7 @@ function Chat2(props) {
|
|
|
4650
4729
|
getPuck,
|
|
4651
4730
|
puckDispatch,
|
|
4652
4731
|
queueBuildOp,
|
|
4732
|
+
sendClientToolResponse,
|
|
4653
4733
|
uploadScreenshot
|
|
4654
4734
|
]
|
|
4655
4735
|
);
|
|
@@ -4719,12 +4799,14 @@ function Chat2(props) {
|
|
|
4719
4799
|
if (BENCHMARK) {
|
|
4720
4800
|
console.timeEnd("chat");
|
|
4721
4801
|
}
|
|
4722
|
-
|
|
4802
|
+
if (!clientToolEndpointUnavailableRef.current) {
|
|
4803
|
+
setError(e.message);
|
|
4804
|
+
}
|
|
4723
4805
|
},
|
|
4724
4806
|
onFinish: (options) => {
|
|
4725
4807
|
debouncedFlushBuildOps.flush();
|
|
4726
4808
|
q.wait().then(() => {
|
|
4727
|
-
if (!options.isAbort) {
|
|
4809
|
+
if (!options.isAbort || clientToolEndpointUnavailableRef.current) {
|
|
4728
4810
|
puckDispatch({
|
|
4729
4811
|
type: "set",
|
|
4730
4812
|
state: getPuck().appState,
|
|
@@ -4739,12 +4821,63 @@ function Chat2(props) {
|
|
|
4739
4821
|
});
|
|
4740
4822
|
}
|
|
4741
4823
|
});
|
|
4742
|
-
(0, import_react27.useEffect)(
|
|
4743
|
-
|
|
4824
|
+
(0, import_react27.useEffect)(() => {
|
|
4825
|
+
stopChatRef.current = stop;
|
|
4826
|
+
return () => {
|
|
4827
|
+
stopChatRef.current = null;
|
|
4744
4828
|
stop();
|
|
4745
|
-
}
|
|
4746
|
-
|
|
4747
|
-
);
|
|
4829
|
+
};
|
|
4830
|
+
}, [stop]);
|
|
4831
|
+
const statusRef = (0, import_react27.useRef)(status);
|
|
4832
|
+
(0, import_react27.useEffect)(() => {
|
|
4833
|
+
statusRef.current = status;
|
|
4834
|
+
}, [status]);
|
|
4835
|
+
(0, import_react27.useEffect)(() => {
|
|
4836
|
+
lastStreamActivityRef.current = Date.now();
|
|
4837
|
+
}, [messages]);
|
|
4838
|
+
(0, import_react27.useEffect)(() => {
|
|
4839
|
+
const FROZEN_HIDDEN_MS = 3 * 6e4;
|
|
4840
|
+
const RESUME_GRACE_MS = 12e3;
|
|
4841
|
+
const isStreaming = () => statusRef.current === "streaming" || statusRef.current === "submitted";
|
|
4842
|
+
let graceTimer;
|
|
4843
|
+
const recoverIfSevered = () => {
|
|
4844
|
+
if (!isStreaming()) return;
|
|
4845
|
+
if (Date.now() - lastStreamActivityRef.current < RESUME_GRACE_MS) return;
|
|
4846
|
+
stop();
|
|
4847
|
+
setToolStatus((current) => {
|
|
4848
|
+
let changed = false;
|
|
4849
|
+
const next = {};
|
|
4850
|
+
for (const [id, toolState] of Object.entries(current)) {
|
|
4851
|
+
if (toolState.loading) {
|
|
4852
|
+
changed = true;
|
|
4853
|
+
next[id] = { ...toolState, loading: false, label: "Interrupted" };
|
|
4854
|
+
} else {
|
|
4855
|
+
next[id] = toolState;
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
return changed ? next : current;
|
|
4859
|
+
});
|
|
4860
|
+
};
|
|
4861
|
+
const onVisibilityChange = () => {
|
|
4862
|
+
if (document.hidden) {
|
|
4863
|
+
hiddenSinceRef.current = isStreaming() ? Date.now() : null;
|
|
4864
|
+
return;
|
|
4865
|
+
}
|
|
4866
|
+
const hiddenSince = hiddenSinceRef.current;
|
|
4867
|
+
hiddenSinceRef.current = null;
|
|
4868
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
4869
|
+
if (hiddenSince === null || Date.now() - hiddenSince < FROZEN_HIDDEN_MS) {
|
|
4870
|
+
return;
|
|
4871
|
+
}
|
|
4872
|
+
lastStreamActivityRef.current = 0;
|
|
4873
|
+
graceTimer = setTimeout(recoverIfSevered, RESUME_GRACE_MS);
|
|
4874
|
+
};
|
|
4875
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
4876
|
+
return () => {
|
|
4877
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
4878
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
4879
|
+
};
|
|
4880
|
+
}, [stop]);
|
|
4748
4881
|
const [forcedStatus, setForcedStatus] = (0, import_react27.useState)();
|
|
4749
4882
|
const resolvedStatus = (0, import_react27.useMemo)(
|
|
4750
4883
|
() => forcedStatus ?? status,
|
|
@@ -4795,6 +4928,8 @@ function Chat2(props) {
|
|
|
4795
4928
|
if (!text && readyAttachments.length === 0) {
|
|
4796
4929
|
return false;
|
|
4797
4930
|
}
|
|
4931
|
+
clientToolEndpointUnavailableRef.current = false;
|
|
4932
|
+
setError("");
|
|
4798
4933
|
setUserError("");
|
|
4799
4934
|
if (chat?.onSubmit) {
|
|
4800
4935
|
try {
|
|
@@ -5034,6 +5169,7 @@ function Chat2(props) {
|
|
|
5034
5169
|
),
|
|
5035
5170
|
error,
|
|
5036
5171
|
handleRetry: () => {
|
|
5172
|
+
clientToolEndpointUnavailableRef.current = false;
|
|
5037
5173
|
setError("");
|
|
5038
5174
|
regenerate();
|
|
5039
5175
|
},
|
package/dist/index.mjs
CHANGED
|
@@ -729,7 +729,7 @@ import { ulid as ulid2 } from "ulid";
|
|
|
729
729
|
// src/components/Chat/index.tsx
|
|
730
730
|
init_react_import();
|
|
731
731
|
|
|
732
|
-
// ../../node_modules/.pnpm/@ai-sdk+react@3.0.232_react@19.2.8_zod@
|
|
732
|
+
// ../../node_modules/.pnpm/@ai-sdk+react@3.0.232_react@19.2.8_zod@3.25.76/node_modules/@ai-sdk/react/dist/index.mjs
|
|
733
733
|
init_react_import();
|
|
734
734
|
var import_throttleit = __toESM(require_throttleit(), 1);
|
|
735
735
|
import {
|
|
@@ -3452,6 +3452,29 @@ var syncFieldValues = (entry, fields, props) => {
|
|
|
3452
3452
|
});
|
|
3453
3453
|
}
|
|
3454
3454
|
};
|
|
3455
|
+
var claimedHostStyles = /* @__PURE__ */ new WeakMap();
|
|
3456
|
+
var claimHostStyles = (el, applyWhiteSpace) => {
|
|
3457
|
+
if (!claimedHostStyles.has(el)) {
|
|
3458
|
+
claimedHostStyles.set(el, {
|
|
3459
|
+
cursor: el.style.cursor,
|
|
3460
|
+
whiteSpace: applyWhiteSpace ? el.style.whiteSpace : null
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
applyHostStyles(el);
|
|
3464
|
+
};
|
|
3465
|
+
var applyHostStyles = (el) => {
|
|
3466
|
+
const claimed = claimedHostStyles.get(el);
|
|
3467
|
+
if (!claimed) return;
|
|
3468
|
+
el.style.cursor = "text";
|
|
3469
|
+
if (claimed.whiteSpace !== null) el.style.whiteSpace = "pre-wrap";
|
|
3470
|
+
};
|
|
3471
|
+
var releaseHostStyles = (el) => {
|
|
3472
|
+
const claimed = claimedHostStyles.get(el);
|
|
3473
|
+
if (!claimed) return;
|
|
3474
|
+
el.style.cursor = claimed.cursor;
|
|
3475
|
+
if (claimed.whiteSpace !== null) el.style.whiteSpace = claimed.whiteSpace;
|
|
3476
|
+
claimedHostStyles.delete(el);
|
|
3477
|
+
};
|
|
3455
3478
|
var attachInlineEditing = (el, {
|
|
3456
3479
|
componentId,
|
|
3457
3480
|
propPath,
|
|
@@ -3464,8 +3487,7 @@ var attachInlineEditing = (el, {
|
|
|
3464
3487
|
const syncEditable = () => {
|
|
3465
3488
|
el.contentEditable = hovering || focused ? mode === "richtext" ? "true" : "plaintext-only" : "false";
|
|
3466
3489
|
};
|
|
3467
|
-
|
|
3468
|
-
el.style.cursor = "text";
|
|
3490
|
+
claimHostStyles(el, mode !== "richtext");
|
|
3469
3491
|
syncEditable();
|
|
3470
3492
|
let lastValidNumberText = el.innerText.replaceAll(/\n/gm, "");
|
|
3471
3493
|
const handleInput = () => {
|
|
@@ -3543,7 +3565,7 @@ var attachInlineEditing = (el, {
|
|
|
3543
3565
|
el.removeEventListener("mouseout", handleMouseOut, true);
|
|
3544
3566
|
el.removeEventListener("focus", handleFocus);
|
|
3545
3567
|
el.removeEventListener("blur", handleBlur);
|
|
3546
|
-
el
|
|
3568
|
+
releaseHostStyles(el);
|
|
3547
3569
|
el.removeAttribute("contenteditable");
|
|
3548
3570
|
cleanupPortal?.();
|
|
3549
3571
|
};
|
|
@@ -3609,7 +3631,7 @@ var wireArrayItemEditing = ({
|
|
|
3609
3631
|
const mode = inlineEditModeFor(field);
|
|
3610
3632
|
const registration = wiring.get(target);
|
|
3611
3633
|
if (registration?.propPath === propPath && registration.mode === mode) {
|
|
3612
|
-
target
|
|
3634
|
+
applyHostStyles(target);
|
|
3613
3635
|
continue;
|
|
3614
3636
|
}
|
|
3615
3637
|
registration?.cleanup();
|
|
@@ -3935,7 +3957,7 @@ function createDesignComponentConfig(registration) {
|
|
|
3935
3957
|
morphed.current = { el: entryEl, html, attrSig };
|
|
3936
3958
|
morphHtml(entryEl, html, attrFields);
|
|
3937
3959
|
for (const el of fieldWiring.current.keys()) {
|
|
3938
|
-
if (el.isConnected) el
|
|
3960
|
+
if (el.isConnected) applyHostStyles(el);
|
|
3939
3961
|
}
|
|
3940
3962
|
}
|
|
3941
3963
|
syncFieldValues(entryEl, annotations.fields, props);
|
|
@@ -4094,9 +4116,11 @@ function getDynamicConfigGlobals(dynamicConfig) {
|
|
|
4094
4116
|
...typeof script === "string" ? { script } : {}
|
|
4095
4117
|
};
|
|
4096
4118
|
}
|
|
4119
|
+
var INLINE_EDIT_RESET = ":where([data-puck-design] [contenteditable]){overflow-wrap:inherit;line-break:inherit;-webkit-nbsp-mode:inherit}";
|
|
4097
4120
|
function DesignGlobals({
|
|
4098
4121
|
styles,
|
|
4099
|
-
script
|
|
4122
|
+
script,
|
|
4123
|
+
isEditing
|
|
4100
4124
|
}) {
|
|
4101
4125
|
const scriptRef = useRef12(null);
|
|
4102
4126
|
const hostRef = useRef12(null);
|
|
@@ -4114,6 +4138,7 @@ function DesignGlobals({
|
|
|
4114
4138
|
};
|
|
4115
4139
|
}, [script]);
|
|
4116
4140
|
return /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
4141
|
+
isEditing && /* @__PURE__ */ jsx33("style", { children: INLINE_EDIT_RESET }),
|
|
4117
4142
|
styles && /* @__PURE__ */ jsx33("style", { children: styles }),
|
|
4118
4143
|
script && /* @__PURE__ */ jsx33("div", { ref: hostRef, style: { display: "none" } })
|
|
4119
4144
|
] });
|
|
@@ -4126,7 +4151,14 @@ function withDesignGlobals(root) {
|
|
|
4126
4151
|
const render = (props) => {
|
|
4127
4152
|
const { styles, script } = getDynamicConfigGlobals(props._dynamicConfig);
|
|
4128
4153
|
return /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
4129
|
-
/* @__PURE__ */ jsx33(
|
|
4154
|
+
/* @__PURE__ */ jsx33(
|
|
4155
|
+
DesignGlobals,
|
|
4156
|
+
{
|
|
4157
|
+
styles,
|
|
4158
|
+
script,
|
|
4159
|
+
isEditing: props.puck?.isEditing
|
|
4160
|
+
}
|
|
4161
|
+
),
|
|
4130
4162
|
userRender ? userRender(props) : props.children
|
|
4131
4163
|
] });
|
|
4132
4164
|
};
|
|
@@ -4392,12 +4424,28 @@ var waitForIframeReady = async (root, imageTimeout = 1e4) => {
|
|
|
4392
4424
|
await waitForNextPaint(document2);
|
|
4393
4425
|
};
|
|
4394
4426
|
|
|
4427
|
+
// src/lib/client-tool-response.ts
|
|
4428
|
+
init_react_import();
|
|
4429
|
+
async function postClientToolResponse(host, body) {
|
|
4430
|
+
const response = await fetch(`${host.replace(/\/+$/, "")}/tool`, {
|
|
4431
|
+
method: "POST",
|
|
4432
|
+
headers: { "Content-Type": "application/json" },
|
|
4433
|
+
body: JSON.stringify(body)
|
|
4434
|
+
});
|
|
4435
|
+
if (!response.ok) {
|
|
4436
|
+
throw new Error(
|
|
4437
|
+
`Client tool endpoint returned ${response.status} ${response.statusText}`.trim()
|
|
4438
|
+
);
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4395
4442
|
// src/components/Chat/index.tsx
|
|
4396
4443
|
import { Fragment as Fragment9, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4397
4444
|
var q = qler();
|
|
4398
4445
|
var DEFAULT_API_VERSION = "v2";
|
|
4399
4446
|
var BUILD_OP_DEBOUNCE_MS = 1e3 / 60;
|
|
4400
|
-
var
|
|
4447
|
+
var CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE = "Unable to verify the page data. Please enable the `/chat/tool` endpoint on the server and try again.";
|
|
4448
|
+
var PLUGIN_AI_VERSION = true ? "0.8.3-canary.8cefba87" : "unknown";
|
|
4401
4449
|
var BENCHMARK = false;
|
|
4402
4450
|
var prefixedUlid = (prefix = "") => `${prefix ? `${prefix}_` : ""}${ulid()}`;
|
|
4403
4451
|
var getClassName18 = getClassNameFactory("Chat", styles_module_default);
|
|
@@ -4435,10 +4483,14 @@ function Chat2(props) {
|
|
|
4435
4483
|
}, [puckData, getPuck]);
|
|
4436
4484
|
const [error, setError] = useState16();
|
|
4437
4485
|
const [userError, setUserError] = useState16();
|
|
4486
|
+
const clientToolEndpointUnavailableRef = useRef13(false);
|
|
4487
|
+
const stopChatRef = useRef13(null);
|
|
4438
4488
|
const [composerAttachments, setComposerAttachments] = useState16([]);
|
|
4439
4489
|
const removedAttachmentClientIdsRef = useRef13(/* @__PURE__ */ new Set());
|
|
4440
4490
|
const uploadControllersRef = useRef13(/* @__PURE__ */ new Map());
|
|
4441
4491
|
const pendingBuildOpsRef = useRef13([]);
|
|
4492
|
+
const lastStreamActivityRef = useRef13(0);
|
|
4493
|
+
const hiddenSinceRef = useRef13(null);
|
|
4442
4494
|
const [toolStatus, setToolStatus] = useState16({});
|
|
4443
4495
|
const [subagentState, setSubagentState] = useState16({});
|
|
4444
4496
|
const attachmentConfig = useMemo6(
|
|
@@ -4549,8 +4601,43 @@ function Chat2(props) {
|
|
|
4549
4601
|
},
|
|
4550
4602
|
[debouncedFlushBuildOps]
|
|
4551
4603
|
);
|
|
4604
|
+
const handleClientToolEndpointUnavailable = useCallback6(() => {
|
|
4605
|
+
if (clientToolEndpointUnavailableRef.current) return;
|
|
4606
|
+
clientToolEndpointUnavailableRef.current = true;
|
|
4607
|
+
setError(CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE);
|
|
4608
|
+
console.error(CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE);
|
|
4609
|
+
setToolStatus((current) => {
|
|
4610
|
+
let changed = false;
|
|
4611
|
+
const next = {};
|
|
4612
|
+
for (const [id, toolState] of Object.entries(current)) {
|
|
4613
|
+
if (toolState.loading) {
|
|
4614
|
+
changed = true;
|
|
4615
|
+
next[id] = {
|
|
4616
|
+
...toolState,
|
|
4617
|
+
loading: false,
|
|
4618
|
+
label: "Verification unavailable"
|
|
4619
|
+
};
|
|
4620
|
+
} else {
|
|
4621
|
+
next[id] = toolState;
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
return changed ? next : current;
|
|
4625
|
+
});
|
|
4626
|
+
stopChatRef.current?.();
|
|
4627
|
+
}, []);
|
|
4628
|
+
const sendClientToolResponse = useCallback6(
|
|
4629
|
+
async (body) => {
|
|
4630
|
+
try {
|
|
4631
|
+
await postClientToolResponse(host, body);
|
|
4632
|
+
} catch {
|
|
4633
|
+
handleClientToolEndpointUnavailable();
|
|
4634
|
+
}
|
|
4635
|
+
},
|
|
4636
|
+
[handleClientToolEndpointUnavailable, host]
|
|
4637
|
+
);
|
|
4552
4638
|
const processData = useCallback6(
|
|
4553
4639
|
(dataPart) => {
|
|
4640
|
+
lastStreamActivityRef.current = Date.now();
|
|
4554
4641
|
switch (dataPart.type) {
|
|
4555
4642
|
case "data-new-chat-created": {
|
|
4556
4643
|
localChatId.current = dataPart.data.chatId;
|
|
@@ -4581,13 +4668,9 @@ function Chat2(props) {
|
|
|
4581
4668
|
debouncedFlushBuildOps.flush();
|
|
4582
4669
|
q.wait().then(() => {
|
|
4583
4670
|
const { appState } = getPuck();
|
|
4584
|
-
return
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
body: JSON.stringify({
|
|
4588
|
-
id: requestId,
|
|
4589
|
-
responses: [{ action, output: appState.data }]
|
|
4590
|
-
})
|
|
4671
|
+
return sendClientToolResponse({
|
|
4672
|
+
id: requestId,
|
|
4673
|
+
responses: [{ action, output: appState.data }]
|
|
4591
4674
|
});
|
|
4592
4675
|
}).catch((e) => {
|
|
4593
4676
|
console.error("Failed to respond to client request:", e);
|
|
@@ -4629,13 +4712,9 @@ function Chat2(props) {
|
|
|
4629
4712
|
`Upload failed with status ${uploadResponse.status}`
|
|
4630
4713
|
);
|
|
4631
4714
|
}
|
|
4632
|
-
return
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
body: JSON.stringify({
|
|
4636
|
-
id: requestId,
|
|
4637
|
-
responses: [{ action, output: { sizeBytes: blob.size } }]
|
|
4638
|
-
})
|
|
4715
|
+
return sendClientToolResponse({
|
|
4716
|
+
id: requestId,
|
|
4717
|
+
responses: [{ action, output: { sizeBytes: blob.size } }]
|
|
4639
4718
|
});
|
|
4640
4719
|
}).catch((e) => {
|
|
4641
4720
|
console.error("Failed to respond to client request:", e);
|
|
@@ -4682,6 +4761,7 @@ function Chat2(props) {
|
|
|
4682
4761
|
getPuck,
|
|
4683
4762
|
puckDispatch,
|
|
4684
4763
|
queueBuildOp,
|
|
4764
|
+
sendClientToolResponse,
|
|
4685
4765
|
uploadScreenshot
|
|
4686
4766
|
]
|
|
4687
4767
|
);
|
|
@@ -4751,12 +4831,14 @@ function Chat2(props) {
|
|
|
4751
4831
|
if (BENCHMARK) {
|
|
4752
4832
|
console.timeEnd("chat");
|
|
4753
4833
|
}
|
|
4754
|
-
|
|
4834
|
+
if (!clientToolEndpointUnavailableRef.current) {
|
|
4835
|
+
setError(e.message);
|
|
4836
|
+
}
|
|
4755
4837
|
},
|
|
4756
4838
|
onFinish: (options) => {
|
|
4757
4839
|
debouncedFlushBuildOps.flush();
|
|
4758
4840
|
q.wait().then(() => {
|
|
4759
|
-
if (!options.isAbort) {
|
|
4841
|
+
if (!options.isAbort || clientToolEndpointUnavailableRef.current) {
|
|
4760
4842
|
puckDispatch({
|
|
4761
4843
|
type: "set",
|
|
4762
4844
|
state: getPuck().appState,
|
|
@@ -4771,12 +4853,63 @@ function Chat2(props) {
|
|
|
4771
4853
|
});
|
|
4772
4854
|
}
|
|
4773
4855
|
});
|
|
4774
|
-
useEffect13(
|
|
4775
|
-
|
|
4856
|
+
useEffect13(() => {
|
|
4857
|
+
stopChatRef.current = stop;
|
|
4858
|
+
return () => {
|
|
4859
|
+
stopChatRef.current = null;
|
|
4776
4860
|
stop();
|
|
4777
|
-
}
|
|
4778
|
-
|
|
4779
|
-
);
|
|
4861
|
+
};
|
|
4862
|
+
}, [stop]);
|
|
4863
|
+
const statusRef = useRef13(status);
|
|
4864
|
+
useEffect13(() => {
|
|
4865
|
+
statusRef.current = status;
|
|
4866
|
+
}, [status]);
|
|
4867
|
+
useEffect13(() => {
|
|
4868
|
+
lastStreamActivityRef.current = Date.now();
|
|
4869
|
+
}, [messages]);
|
|
4870
|
+
useEffect13(() => {
|
|
4871
|
+
const FROZEN_HIDDEN_MS = 3 * 6e4;
|
|
4872
|
+
const RESUME_GRACE_MS = 12e3;
|
|
4873
|
+
const isStreaming = () => statusRef.current === "streaming" || statusRef.current === "submitted";
|
|
4874
|
+
let graceTimer;
|
|
4875
|
+
const recoverIfSevered = () => {
|
|
4876
|
+
if (!isStreaming()) return;
|
|
4877
|
+
if (Date.now() - lastStreamActivityRef.current < RESUME_GRACE_MS) return;
|
|
4878
|
+
stop();
|
|
4879
|
+
setToolStatus((current) => {
|
|
4880
|
+
let changed = false;
|
|
4881
|
+
const next = {};
|
|
4882
|
+
for (const [id, toolState] of Object.entries(current)) {
|
|
4883
|
+
if (toolState.loading) {
|
|
4884
|
+
changed = true;
|
|
4885
|
+
next[id] = { ...toolState, loading: false, label: "Interrupted" };
|
|
4886
|
+
} else {
|
|
4887
|
+
next[id] = toolState;
|
|
4888
|
+
}
|
|
4889
|
+
}
|
|
4890
|
+
return changed ? next : current;
|
|
4891
|
+
});
|
|
4892
|
+
};
|
|
4893
|
+
const onVisibilityChange = () => {
|
|
4894
|
+
if (document.hidden) {
|
|
4895
|
+
hiddenSinceRef.current = isStreaming() ? Date.now() : null;
|
|
4896
|
+
return;
|
|
4897
|
+
}
|
|
4898
|
+
const hiddenSince = hiddenSinceRef.current;
|
|
4899
|
+
hiddenSinceRef.current = null;
|
|
4900
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
4901
|
+
if (hiddenSince === null || Date.now() - hiddenSince < FROZEN_HIDDEN_MS) {
|
|
4902
|
+
return;
|
|
4903
|
+
}
|
|
4904
|
+
lastStreamActivityRef.current = 0;
|
|
4905
|
+
graceTimer = setTimeout(recoverIfSevered, RESUME_GRACE_MS);
|
|
4906
|
+
};
|
|
4907
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
4908
|
+
return () => {
|
|
4909
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
4910
|
+
if (graceTimer) clearTimeout(graceTimer);
|
|
4911
|
+
};
|
|
4912
|
+
}, [stop]);
|
|
4780
4913
|
const [forcedStatus, setForcedStatus] = useState16();
|
|
4781
4914
|
const resolvedStatus = useMemo6(
|
|
4782
4915
|
() => forcedStatus ?? status,
|
|
@@ -4827,6 +4960,8 @@ function Chat2(props) {
|
|
|
4827
4960
|
if (!text && readyAttachments.length === 0) {
|
|
4828
4961
|
return false;
|
|
4829
4962
|
}
|
|
4963
|
+
clientToolEndpointUnavailableRef.current = false;
|
|
4964
|
+
setError("");
|
|
4830
4965
|
setUserError("");
|
|
4831
4966
|
if (chat?.onSubmit) {
|
|
4832
4967
|
try {
|
|
@@ -5066,6 +5201,7 @@ function Chat2(props) {
|
|
|
5066
5201
|
),
|
|
5067
5202
|
error,
|
|
5068
5203
|
handleRetry: () => {
|
|
5204
|
+
clientToolEndpointUnavailableRef.current = false;
|
|
5069
5205
|
setError("");
|
|
5070
5206
|
regenerate();
|
|
5071
5207
|
},
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@puckeditor/plugin-ai",
|
|
3
|
-
"version": "0.8.3-canary.
|
|
3
|
+
"version": "0.8.3-canary.8cefba87",
|
|
4
4
|
"author": "Chris Villa <chris@puckeditor.com>",
|
|
5
|
-
"repository":
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "puckeditor/puck"
|
|
8
|
+
},
|
|
6
9
|
"bugs": "https://github.com/puckeditor/puck/issues",
|
|
7
10
|
"homepage": "https://puckeditor.com",
|
|
8
11
|
"keywords": [
|
|
@@ -49,12 +52,12 @@
|
|
|
49
52
|
"tsup": "^8.2.4",
|
|
50
53
|
"typescript": "^5.5.4",
|
|
51
54
|
"vitest": "^4.1.0",
|
|
52
|
-
"@puckeditor/ai-types": "0.8.3-canary.
|
|
53
|
-
"@puckeditor/platform-types": "0.8.3-canary.
|
|
54
|
-
"eslint-config-custom": "0.8.3-canary.
|
|
55
|
-
"reducer": "0.8.3-canary.
|
|
56
|
-
"tsconfig": "0.8.3-canary.
|
|
57
|
-
"tsup-config": "0.8.3-canary.
|
|
55
|
+
"@puckeditor/ai-types": "0.8.3-canary.8cefba87",
|
|
56
|
+
"@puckeditor/platform-types": "0.8.3-canary.8cefba87",
|
|
57
|
+
"eslint-config-custom": "0.8.3-canary.8cefba87",
|
|
58
|
+
"reducer": "0.8.3-canary.8cefba87",
|
|
59
|
+
"tsconfig": "0.8.3-canary.8cefba87",
|
|
60
|
+
"tsup-config": "0.8.3-canary.8cefba87"
|
|
58
61
|
},
|
|
59
62
|
"peerDependencies": {
|
|
60
63
|
"@puckeditor/core": "^0",
|