@cosmoops/connect-sdk 0.30.0 → 0.30.1
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/CHANGELOG.md +26 -0
- package/dist/cjs/client/components/ask-ai.js +61 -6
- package/dist/cjs/server/client.js +1 -1
- package/dist/esm/client/components/ask-ai.js +29 -7
- package/dist/esm/server/client.js +1 -1
- package/dist/types/client/components/ask-ai.d.ts +1 -1
- package/dist/types/server/client.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
`@cosmoops/connect-sdk` follows semver, with the 0.x convention that **minor
|
|
4
4
|
versions may carry breaking changes** and patch versions never do.
|
|
5
5
|
|
|
6
|
+
## 0.30.1
|
|
7
|
+
|
|
8
|
+
`ConnectAppShell` was putting **462 KB** of markdown renderer on every page of
|
|
9
|
+
every application platform that mounts it — which is every page, because the
|
|
10
|
+
shell owns the layout. `streamdown` was a static import in `ConnectAskAi`, so
|
|
11
|
+
it was downloaded, parsed and evaluated on each route to render nothing until
|
|
12
|
+
somebody opened the assistant, which most page views never do. Measured on a
|
|
13
|
+
partner app: 48 of its 49 routes carried it, roughly a quarter of each route's
|
|
14
|
+
JavaScript.
|
|
15
|
+
|
|
16
|
+
It is now `React.lazy`, so the chunk is requested the first time there is
|
|
17
|
+
markdown to render and cached by React from then on. No API changed and no
|
|
18
|
+
host setup changed; `streamdown` stays a peer dependency of `/client` and is
|
|
19
|
+
still needed for formatted answers.
|
|
20
|
+
|
|
21
|
+
The Suspense fallback is the **raw text** rather than a spinner. An answer
|
|
22
|
+
streams in token by token, and unformatted prose is readable — so the first
|
|
23
|
+
words now appear *while* the renderer is being fetched instead of behind it,
|
|
24
|
+
and re-render as markdown when it lands. On a cold cache that makes the first
|
|
25
|
+
answer feel earlier than it did before, not later.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- `ConnectAskAi` loads `streamdown` on demand instead of at module scope.
|
|
30
|
+
Partner apps get the saving by upgrading; nothing in their code moves.
|
|
31
|
+
|
|
6
32
|
## 0.30.0
|
|
7
33
|
|
|
8
34
|
`<ConnectAskAi>` forgot everything on reload. Connect's own panel has had
|
|
@@ -1,13 +1,68 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
37
|
exports.ConnectAskAi = ConnectAskAi;
|
|
5
38
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
39
|
const react_1 = require("react");
|
|
7
40
|
const react_2 = require("@heroui/react");
|
|
8
41
|
const lucide_react_1 = require("lucide-react");
|
|
9
|
-
const streamdown_1 = require("streamdown");
|
|
10
42
|
const provider_js_1 = require("../provider.js");
|
|
43
|
+
/**
|
|
44
|
+
* The markdown renderer, fetched the first time there is markdown to render.
|
|
45
|
+
*
|
|
46
|
+
* `streamdown` is **462 KB** of the host's client bundle, and a static import
|
|
47
|
+
* here put all of it on every page of every application platform that mounts
|
|
48
|
+
* `ConnectAppShell` - which is every page, because the shell owns the layout.
|
|
49
|
+
* It rendered nothing until somebody opened the assistant, which most page
|
|
50
|
+
* views never do. Measured on one partner app: 48 of 49 routes carrying it,
|
|
51
|
+
* about a quarter of each route's JavaScript.
|
|
52
|
+
*
|
|
53
|
+
* `lazy` rather than a conditional `import()` in an effect: React caches the
|
|
54
|
+
* module promise, so the chunk is requested once no matter how many messages
|
|
55
|
+
* render, and the boundary below is what covers the gap.
|
|
56
|
+
*
|
|
57
|
+
* The fallback is the **raw text**, not a spinner. An answer streams in token
|
|
58
|
+
* by token, and unformatted prose is readable - so the first words appear
|
|
59
|
+
* while the renderer is still arriving rather than behind it. Once it lands,
|
|
60
|
+
* the same text re-renders as markdown.
|
|
61
|
+
*/
|
|
62
|
+
const Streamdown = (0, react_1.lazy)(async () => {
|
|
63
|
+
const mod = await Promise.resolve().then(() => __importStar(require("streamdown")));
|
|
64
|
+
return { default: mod.Streamdown };
|
|
65
|
+
});
|
|
11
66
|
const use_active_path_js_1 = require("../use-active-path.js");
|
|
12
67
|
const ai_screens_js_1 = require("./ai-screens.js");
|
|
13
68
|
const ai_widgets_js_1 = require("./ai-widgets.js");
|
|
@@ -267,11 +322,11 @@ function ConnectAskAi({ title = "Ask AI", assistantName = "Assistant", placehold
|
|
|
267
322
|
*/
|
|
268
323
|
const resolvedPath = (0, use_active_path_js_1.useActivePath)(activePath);
|
|
269
324
|
const currentScreen = (0, react_1.useMemo)(() => (resolvedPath ? (0, ai_screens_js_1.matchConnectScreen)(screens, resolvedPath) : null), [screens, resolvedPath]);
|
|
270
|
-
const renderMarkdown = (0, react_1.useCallback)((text, isStreaming = false) => ((0, jsx_runtime_1.jsx)(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
325
|
+
const renderMarkdown = (0, react_1.useCallback)((text, isStreaming = false) => ((0, jsx_runtime_1.jsx)(react_1.Suspense, { fallback: (0, jsx_runtime_1.jsx)("div", { className: "connect-ai-body whitespace-pre-wrap", children: text }), children: (0, jsx_runtime_1.jsx)(Streamdown, { className: "connect-ai-body", mode: isStreaming ? "streaming" : "static", isAnimating: isStreaming, animated: ANIMATED, caret: isStreaming ? "block" : undefined, plugins: markdownPlugins,
|
|
326
|
+
// Retrieved documents cite real URLs; an interstitial on every one of
|
|
327
|
+
// them turns a citation into a chore. The renderer still sanitises the
|
|
328
|
+
// markup itself, which is the part that matters.
|
|
329
|
+
linkSafety: LINK_SAFETY, children: text }) })), [markdownPlugins]);
|
|
275
330
|
const stop = (0, react_1.useCallback)(() => {
|
|
276
331
|
abortRef.current?.abort();
|
|
277
332
|
abortRef.current = null;
|
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { Button, Input, Label, TextField } from "@heroui/react";
|
|
5
5
|
import { Brain, ChevronDown, History, Plus, Send, Sparkles, Square, X } from "lucide-react";
|
|
6
|
-
import { Streamdown } from "streamdown";
|
|
7
6
|
import { useConnect } from "../provider.js";
|
|
7
|
+
/**
|
|
8
|
+
* The markdown renderer, fetched the first time there is markdown to render.
|
|
9
|
+
*
|
|
10
|
+
* `streamdown` is **462 KB** of the host's client bundle, and a static import
|
|
11
|
+
* here put all of it on every page of every application platform that mounts
|
|
12
|
+
* `ConnectAppShell` - which is every page, because the shell owns the layout.
|
|
13
|
+
* It rendered nothing until somebody opened the assistant, which most page
|
|
14
|
+
* views never do. Measured on one partner app: 48 of 49 routes carrying it,
|
|
15
|
+
* about a quarter of each route's JavaScript.
|
|
16
|
+
*
|
|
17
|
+
* `lazy` rather than a conditional `import()` in an effect: React caches the
|
|
18
|
+
* module promise, so the chunk is requested once no matter how many messages
|
|
19
|
+
* render, and the boundary below is what covers the gap.
|
|
20
|
+
*
|
|
21
|
+
* The fallback is the **raw text**, not a spinner. An answer streams in token
|
|
22
|
+
* by token, and unformatted prose is readable - so the first words appear
|
|
23
|
+
* while the renderer is still arriving rather than behind it. Once it lands,
|
|
24
|
+
* the same text re-renders as markdown.
|
|
25
|
+
*/
|
|
26
|
+
const Streamdown = lazy(async () => {
|
|
27
|
+
const mod = await import("streamdown");
|
|
28
|
+
return { default: mod.Streamdown };
|
|
29
|
+
});
|
|
8
30
|
import { useActivePath } from "../use-active-path.js";
|
|
9
31
|
import { matchConnectScreen } from "./ai-screens.js";
|
|
10
32
|
import { AiActions, AiChart, AiDetails, AiMetrics, AiSources, AiSteps, AiTable, AiTimeline } from "./ai-widgets.js";
|
|
@@ -264,11 +286,11 @@ export function ConnectAskAi({ title = "Ask AI", assistantName = "Assistant", pl
|
|
|
264
286
|
*/
|
|
265
287
|
const resolvedPath = useActivePath(activePath);
|
|
266
288
|
const currentScreen = useMemo(() => (resolvedPath ? matchConnectScreen(screens, resolvedPath) : null), [screens, resolvedPath]);
|
|
267
|
-
const renderMarkdown = useCallback((text, isStreaming = false) => (_jsx(Streamdown, { className: "connect-ai-body", mode: isStreaming ? "streaming" : "static", isAnimating: isStreaming, animated: ANIMATED, caret: isStreaming ? "block" : undefined, plugins: markdownPlugins,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
289
|
+
const renderMarkdown = useCallback((text, isStreaming = false) => (_jsx(Suspense, { fallback: _jsx("div", { className: "connect-ai-body whitespace-pre-wrap", children: text }), children: _jsx(Streamdown, { className: "connect-ai-body", mode: isStreaming ? "streaming" : "static", isAnimating: isStreaming, animated: ANIMATED, caret: isStreaming ? "block" : undefined, plugins: markdownPlugins,
|
|
290
|
+
// Retrieved documents cite real URLs; an interstitial on every one of
|
|
291
|
+
// them turns a citation into a chore. The renderer still sanitises the
|
|
292
|
+
// markup itself, which is the part that matters.
|
|
293
|
+
linkSafety: LINK_SAFETY, children: text }) })), [markdownPlugins]);
|
|
272
294
|
const stop = useCallback(() => {
|
|
273
295
|
abortRef.current?.abort();
|
|
274
296
|
abortRef.current = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmoops/connect-sdk",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"description": "Official server-side SDK for the CosmoOps Connect platform API - Login with Connect, entitlements, billing and metering.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "commonjs",
|