@blocklet/aigne-hub 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +29 -0
  2. package/lib/cjs/api/ai-kit.js +60 -0
  3. package/lib/cjs/api/api.js +17 -0
  4. package/lib/cjs/api/app.js +57 -0
  5. package/lib/cjs/api/call/api.js +51 -0
  6. package/lib/cjs/api/call/app.js +74 -0
  7. package/lib/cjs/api/call/index.js +19 -0
  8. package/lib/cjs/api/call/proxy.js +64 -0
  9. package/lib/cjs/api/call/v1.js +166 -0
  10. package/lib/cjs/api/call/v2.js +101 -0
  11. package/lib/cjs/api/config.js +46 -0
  12. package/lib/cjs/api/constants.js +4 -0
  13. package/lib/cjs/api/error.js +42 -0
  14. package/lib/cjs/api/index.js +19 -0
  15. package/lib/cjs/api/types/audio.js +2 -0
  16. package/lib/cjs/api/types/chat.js +14 -0
  17. package/lib/cjs/api/types/embedding.js +2 -0
  18. package/lib/cjs/api/types/image.js +2 -0
  19. package/lib/cjs/api/types/index.js +19 -0
  20. package/lib/cjs/api/types/status.js +2 -0
  21. package/lib/cjs/api/utils/auth.js +90 -0
  22. package/lib/cjs/api/utils/event-stream.js +59 -0
  23. package/lib/cjs/components/conversation/conversation.js +71 -0
  24. package/lib/cjs/components/conversation/index.js +25 -0
  25. package/lib/cjs/components/conversation/message.js +120 -0
  26. package/lib/cjs/components/conversation/prompt.js +43 -0
  27. package/lib/cjs/components/conversation/use-conversation.js +100 -0
  28. package/lib/cjs/components/credit/alert.js +40 -0
  29. package/lib/cjs/components/credit/balance.js +95 -0
  30. package/lib/cjs/components/credit/button.js +69 -0
  31. package/lib/cjs/components/credit/index.js +12 -0
  32. package/lib/cjs/components/form-label.js +27 -0
  33. package/lib/cjs/components/image-preview.js +116 -0
  34. package/lib/cjs/components/index.js +45 -0
  35. package/lib/cjs/components/loading-image.js +37 -0
  36. package/lib/cjs/components/subscribe/alert.js +53 -0
  37. package/lib/cjs/components/subscribe/button.js +92 -0
  38. package/lib/cjs/components/subscribe/state.js +42 -0
  39. package/lib/cjs/components/switch-button.js +48 -0
  40. package/lib/cjs/components/table.js +203 -0
  41. package/lib/cjs/index.js +2 -0
  42. package/lib/cjs/libs/logger.js +8 -0
  43. package/lib/cjs/utils/withLocaleProvider.js +11 -0
  44. package/lib/esm/api/ai-kit.js +54 -0
  45. package/lib/esm/api/api.js +11 -0
  46. package/lib/esm/api/app.js +42 -0
  47. package/lib/esm/api/call/api.js +24 -0
  48. package/lib/esm/api/call/app.js +68 -0
  49. package/lib/esm/api/call/index.js +3 -0
  50. package/lib/esm/api/call/proxy.js +58 -0
  51. package/lib/esm/api/call/v1.js +155 -0
  52. package/lib/esm/api/call/v2.js +93 -0
  53. package/lib/esm/api/config.js +41 -0
  54. package/lib/esm/api/constants.js +1 -0
  55. package/lib/esm/api/error.js +37 -0
  56. package/lib/esm/api/index.js +3 -0
  57. package/lib/esm/api/types/audio.js +1 -0
  58. package/lib/esm/api/types/chat.js +9 -0
  59. package/lib/esm/api/types/embedding.js +1 -0
  60. package/lib/esm/api/types/image.js +1 -0
  61. package/lib/esm/api/types/index.js +3 -0
  62. package/lib/esm/api/types/status.js +1 -0
  63. package/lib/esm/api/utils/auth.js +79 -0
  64. package/lib/esm/api/utils/event-stream.js +50 -0
  65. package/lib/esm/components/conversation/conversation.js +65 -0
  66. package/lib/esm/components/conversation/index.js +4 -0
  67. package/lib/esm/components/conversation/message.js +114 -0
  68. package/lib/esm/components/conversation/prompt.js +40 -0
  69. package/lib/esm/components/conversation/use-conversation.js +97 -0
  70. package/lib/esm/components/credit/alert.js +35 -0
  71. package/lib/esm/components/credit/balance.js +90 -0
  72. package/lib/esm/components/credit/button.js +64 -0
  73. package/lib/esm/components/credit/index.js +3 -0
  74. package/lib/esm/components/form-label.js +24 -0
  75. package/lib/esm/components/image-preview.js +110 -0
  76. package/lib/esm/components/index.js +14 -0
  77. package/lib/esm/components/loading-image.js +35 -0
  78. package/lib/esm/components/subscribe/alert.js +48 -0
  79. package/lib/esm/components/subscribe/button.js +87 -0
  80. package/lib/esm/components/subscribe/state.js +39 -0
  81. package/lib/esm/components/switch-button.js +46 -0
  82. package/lib/esm/components/table.js +198 -0
  83. package/lib/esm/index.js +1 -0
  84. package/lib/esm/libs/logger.js +3 -0
  85. package/lib/esm/utils/withLocaleProvider.js +8 -0
  86. package/lib/types/api/ai-kit.d.ts +70 -0
  87. package/lib/types/api/api.d.ts +4 -0
  88. package/lib/types/api/app.d.ts +113 -0
  89. package/lib/types/api/call/api.d.ts +2 -0
  90. package/lib/types/api/call/app.d.ts +50 -0
  91. package/lib/types/api/call/index.d.ts +3 -0
  92. package/lib/types/api/call/proxy.d.ts +6 -0
  93. package/lib/types/api/call/v1.d.ts +51 -0
  94. package/lib/types/api/call/v2.d.ts +30 -0
  95. package/lib/types/api/config.d.ts +14 -0
  96. package/lib/types/api/constants.d.ts +1 -0
  97. package/lib/types/api/error.d.ts +18 -0
  98. package/lib/types/api/index.d.ts +3 -0
  99. package/lib/types/api/types/audio.d.ts +18 -0
  100. package/lib/types/api/types/chat.d.ts +97 -0
  101. package/lib/types/api/types/embedding.d.ts +9 -0
  102. package/lib/types/api/types/image.d.ts +23 -0
  103. package/lib/types/api/types/index.d.ts +3 -0
  104. package/lib/types/api/types/status.d.ts +3 -0
  105. package/lib/types/api/utils/auth.d.ts +33 -0
  106. package/lib/types/api/utils/event-stream.d.ts +7 -0
  107. package/lib/types/components/conversation/conversation.d.ts +30 -0
  108. package/lib/types/components/conversation/index.d.ts +4 -0
  109. package/lib/types/components/conversation/message.d.ts +10 -0
  110. package/lib/types/components/conversation/prompt.d.ts +10 -0
  111. package/lib/types/components/conversation/use-conversation.d.ts +44 -0
  112. package/lib/types/components/credit/alert.d.ts +10 -0
  113. package/lib/types/components/credit/balance.d.ts +7 -0
  114. package/lib/types/components/credit/button.d.ts +11 -0
  115. package/lib/types/components/credit/index.d.ts +3 -0
  116. package/lib/types/components/form-label.d.ts +7 -0
  117. package/lib/types/components/image-preview.d.ts +17 -0
  118. package/lib/types/components/index.d.ts +12 -0
  119. package/lib/types/components/loading-image.d.ts +6 -0
  120. package/lib/types/components/subscribe/alert.d.ts +5 -0
  121. package/lib/types/components/subscribe/button.d.ts +5 -0
  122. package/lib/types/components/subscribe/state.d.ts +14 -0
  123. package/lib/types/components/switch-button.d.ts +7 -0
  124. package/lib/types/components/table.d.ts +3 -0
  125. package/lib/types/index.d.ts +1 -0
  126. package/lib/types/libs/logger.d.ts +2 -0
  127. package/lib/types/utils/withLocaleProvider.d.ts +9 -0
  128. package/package.json +158 -0
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const events_1 = require("events");
7
+ const fs_1 = require("fs");
8
+ const promises_1 = require("fs/promises");
9
+ const path_1 = require("path");
10
+ const config_1 = __importDefault(require("@blocklet/sdk/lib/config"));
11
+ const yaml_1 = require("yaml");
12
+ const logger_1 = __importDefault(require("../libs/logger"));
13
+ class Config extends events_1.EventEmitter {
14
+ constructor() {
15
+ super();
16
+ this.reloadConfigFile = async () => {
17
+ try {
18
+ this.config = (0, yaml_1.parse)((await (0, promises_1.readFile)(Config.CONFIG_FILE_PATH)).toString());
19
+ }
20
+ catch (error) {
21
+ logger_1.default.error(`Parse ${Config.CONFIG_FILE_PATH} error`, { error });
22
+ }
23
+ };
24
+ if (!(0, fs_1.existsSync)(Config.CONFIG_FILE_PATH)) {
25
+ (0, fs_1.writeFileSync)(Config.CONFIG_FILE_PATH, '');
26
+ }
27
+ this.reloadConfigFile();
28
+ }
29
+ get useAIKitService() {
30
+ var _a;
31
+ return (_a = this.config) === null || _a === void 0 ? void 0 : _a.useAIKitService;
32
+ }
33
+ set useAIKitService(value) {
34
+ var _a;
35
+ (_a = this.config) !== null && _a !== void 0 ? _a : (this.config = {});
36
+ this.config.useAIKitService = value;
37
+ this.save();
38
+ this.emit('change', this.config);
39
+ }
40
+ async save() {
41
+ await (0, promises_1.writeFile)(Config.CONFIG_FILE_PATH, (0, yaml_1.stringify)(this.config));
42
+ }
43
+ }
44
+ Config.CONFIG_FILE_PATH = (0, path_1.join)(config_1.default.env.dataDir, 'ai-kit-service.config.yaml');
45
+ const AIKitConfig = new Config();
46
+ exports.default = AIKitConfig;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AI_KIT_BASE_URL = void 0;
4
+ exports.AI_KIT_BASE_URL = process.env.AI_KIT_BASE_URL || 'https://www.aikit.rocks/ai-kit';
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreditError = exports.SubscriptionError = exports.CreditErrorType = exports.SubscriptionErrorType = void 0;
4
+ var SubscriptionErrorType;
5
+ (function (SubscriptionErrorType) {
6
+ SubscriptionErrorType["UNSUBSCRIBED"] = "UNSUBSCRIBED";
7
+ SubscriptionErrorType["UNKNOWN"] = "UNKNOWN";
8
+ })(SubscriptionErrorType || (exports.SubscriptionErrorType = SubscriptionErrorType = {}));
9
+ var CreditErrorType;
10
+ (function (CreditErrorType) {
11
+ CreditErrorType["NOT_ENOUGH"] = "NOT_ENOUGH";
12
+ CreditErrorType["UNKNOWN"] = "UNKNOWN";
13
+ })(CreditErrorType || (exports.CreditErrorType = CreditErrorType = {}));
14
+ const SubscriptionErrors = {
15
+ [SubscriptionErrorType.UNSUBSCRIBED]: 'Hello, in order to continue chatting, please first subscribe to AI-KIT service',
16
+ [SubscriptionErrorType.UNKNOWN]: 'An unknown error occurred',
17
+ };
18
+ class SubscriptionError extends Error {
19
+ constructor(type) {
20
+ const message = SubscriptionErrors[type] || SubscriptionErrors[SubscriptionErrorType.UNKNOWN];
21
+ super(message);
22
+ this.timestamp = new Date().toISOString();
23
+ this.type = type;
24
+ }
25
+ }
26
+ exports.SubscriptionError = SubscriptionError;
27
+ const CreditErrors = {
28
+ [CreditErrorType.NOT_ENOUGH]: 'Hello, in order to continue chatting, please first buy some credits in the link below.',
29
+ [CreditErrorType.UNKNOWN]: 'An unknown error occurred',
30
+ };
31
+ class CreditError extends Error {
32
+ constructor(type, link) {
33
+ let message = CreditErrors[type] || CreditErrors[CreditErrorType.UNKNOWN];
34
+ if (type === CreditErrorType.NOT_ENOUGH && link) {
35
+ message += `\n\n${link}`;
36
+ }
37
+ super(message);
38
+ this.timestamp = new Date().toISOString();
39
+ this.type = type;
40
+ }
41
+ }
42
+ exports.CreditError = CreditError;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./ai-kit"), exports);
18
+ __exportStar(require("./error"), exports);
19
+ __exportStar(require("./app"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isChatCompletionChunk = isChatCompletionChunk;
4
+ exports.isChatCompletionUsage = isChatCompletionUsage;
5
+ exports.isChatCompletionError = isChatCompletionError;
6
+ function isChatCompletionChunk(data) {
7
+ return typeof data.delta === 'object';
8
+ }
9
+ function isChatCompletionUsage(data) {
10
+ return typeof data.usage === 'object';
11
+ }
12
+ function isChatCompletionError(data) {
13
+ return typeof data.error === 'object';
14
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./chat"), exports);
18
+ __exportStar(require("./image"), exports);
19
+ __exportStar(require("./embedding"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /// <reference path="./auth.type.d.ts" />
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ensureAdmin = exports.wallet = void 0;
8
+ exports.appIdFromPublicKey = appIdFromPublicKey;
9
+ exports.verifyRemoteComponentCall = verifyRemoteComponentCall;
10
+ exports.signRemoteComponentCall = signRemoteComponentCall;
11
+ exports.getRemoteComponentCallHeaders = getRemoteComponentCallHeaders;
12
+ exports.ensureRemoteComponentCall = ensureRemoteComponentCall;
13
+ const did_1 = require("@arcblock/did");
14
+ const middlewares_1 = require("@blocklet/sdk/lib/middlewares");
15
+ const wallet_1 = __importDefault(require("@blocklet/sdk/lib/wallet"));
16
+ const mcrypto_1 = require("@ocap/mcrypto");
17
+ const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
18
+ const TOKEN_EXPIRES_IN_SECONDS = 60 * 10;
19
+ exports.wallet = (0, wallet_1.default)();
20
+ const ADMIN_ROLES = ['owner', 'admin'];
21
+ exports.ensureAdmin = (0, middlewares_1.auth)({ roles: ADMIN_ROLES });
22
+ const signer = (0, mcrypto_1.getSigner)((0, did_1.DidType)('default').pk);
23
+ function hashData({ appId, timestamp, data, userDid, }) {
24
+ const hasher = (0, mcrypto_1.getHasher)((0, did_1.DidType)('default').hash);
25
+ return hasher((0, json_stable_stringify_1.default)({ appId, timestamp, data: data || {}, userDid }), 1);
26
+ }
27
+ function appIdFromPublicKey(publicKey) {
28
+ return (0, did_1.fromPublicKey)(publicKey, (0, did_1.DidType)({ role: mcrypto_1.types.RoleType.ROLE_APPLICATION, pk: mcrypto_1.types.KeyType.ED25519, hash: mcrypto_1.types.HashType.SHA3 }));
29
+ }
30
+ function verifyRemoteComponentCall({ appId, timestamp, data, sig, pk, userDid, expiresIn = TOKEN_EXPIRES_IN_SECONDS, }) {
31
+ if (Math.abs(Date.now() / 1000 - timestamp) > expiresIn)
32
+ throw new Error('signature expired');
33
+ return signer.verify(hashData({ appId, timestamp, data, userDid }), sig, pk);
34
+ }
35
+ function signRemoteComponentCall({ data, userDid }) {
36
+ const appId = exports.wallet.address;
37
+ const timestamp = Math.round(Date.now() / 1000);
38
+ return {
39
+ appId,
40
+ timestamp,
41
+ userDid,
42
+ sig: signer.sign(hashData({ appId, timestamp, data, userDid }), exports.wallet.secretKey),
43
+ };
44
+ }
45
+ function getRemoteComponentCallHeaders(data, userDid) {
46
+ const { appId, timestamp, sig } = signRemoteComponentCall({ data, userDid });
47
+ return {
48
+ 'x-app-id': appId,
49
+ 'x-timestamp': timestamp.toString(),
50
+ 'x-component-sig': sig,
51
+ 'x-app-user-did': userDid || '',
52
+ };
53
+ }
54
+ function ensureRemoteComponentCall(getPublicKey, fallback) {
55
+ return async (req, res, next) => {
56
+ try {
57
+ const sig = req.get('x-component-sig');
58
+ const appId = req.get('x-app-id');
59
+ const timestamp = req.get('x-timestamp');
60
+ const userDid = req.get('x-app-user-did'); // Get user did
61
+ if (!sig || !appId || !timestamp) {
62
+ throw new Error('Missing required headers x-component-sig/x-app-id/x-timestamp');
63
+ }
64
+ const pk = await getPublicKey(appId);
65
+ if (appIdFromPublicKey(pk) !== appId)
66
+ throw new Error('appId and public key not match');
67
+ if (!verifyRemoteComponentCall({
68
+ appId,
69
+ sig,
70
+ timestamp: parseInt(timestamp, 10),
71
+ data: req.body,
72
+ pk,
73
+ userDid,
74
+ })) {
75
+ throw new Error('Validate signature error');
76
+ }
77
+ req.appClient = {
78
+ appId,
79
+ userDid,
80
+ };
81
+ }
82
+ catch (error) {
83
+ if (!fallback)
84
+ throw error;
85
+ fallback(req, res, next);
86
+ return;
87
+ }
88
+ next();
89
+ };
90
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EventSourceParserStream = void 0;
7
+ exports.readableToWeb = readableToWeb;
8
+ exports.tryParseJsonFromResponseStream = tryParseJsonFromResponseStream;
9
+ const web_1 = require("stream/web");
10
+ const eventsource_parser_1 = require("eventsource-parser");
11
+ const logger_1 = __importDefault(require("../../libs/logger"));
12
+ function readableToWeb(readable) {
13
+ return new web_1.ReadableStream({
14
+ async start(controller) {
15
+ for await (const chunk of readable) {
16
+ controller.enqueue(chunk);
17
+ }
18
+ controller.close();
19
+ },
20
+ });
21
+ }
22
+ class EventSourceParserStream extends web_1.TransformStream {
23
+ constructor() {
24
+ let parser;
25
+ super({
26
+ start(controller) {
27
+ parser = (0, eventsource_parser_1.createParser)((event) => {
28
+ if (event.type === 'event') {
29
+ try {
30
+ const json = JSON.parse(event.data);
31
+ controller.enqueue(json);
32
+ }
33
+ catch (error) {
34
+ logger_1.default.error('parse chunk error', { error, data: event.data });
35
+ }
36
+ }
37
+ });
38
+ },
39
+ transform(chunk) {
40
+ parser === null || parser === void 0 ? void 0 : parser.feed(chunk);
41
+ },
42
+ });
43
+ }
44
+ }
45
+ exports.EventSourceParserStream = EventSourceParserStream;
46
+ async function tryParseJsonFromResponseStream(data) {
47
+ let text = '';
48
+ let json;
49
+ try {
50
+ for await (const chunk of readableToWeb(data).pipeThrough(new web_1.TextDecoderStream())) {
51
+ text += chunk;
52
+ }
53
+ json = JSON.parse(text);
54
+ }
55
+ catch (error) {
56
+ logger_1.default.error('parse json from response error', { text, error });
57
+ }
58
+ return json;
59
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = Conversation;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const material_1 = require("@mui/material");
9
+ const isNil_1 = __importDefault(require("lodash/isNil"));
10
+ const react_1 = require("react");
11
+ const image_preview_1 = __importDefault(require("../image-preview"));
12
+ const alert_1 = __importDefault(require("../subscribe/alert"));
13
+ const message_1 = __importDefault(require("./message"));
14
+ const prompt_1 = __importDefault(require("./prompt"));
15
+ function Conversation({ ref, messages, onSubmit, customActions = () => [], renderAvatar = undefined, maxWidth = 1000, scrollContainer = undefined, promptProps = {}, ...props }) {
16
+ const scroller = (0, react_1.useRef)(scrollContainer !== null && scrollContainer !== void 0 ? scrollContainer : null);
17
+ const { element, scrollToBottom } = useAutoScrollToBottom({ scroller });
18
+ (0, react_1.useImperativeHandle)(ref, () => ({
19
+ scrollToBottom,
20
+ }), [scrollToBottom]);
21
+ return ((0, jsx_runtime_1.jsx)(material_1.Box, { ...props, ref: scrollContainer ? undefined : scroller, sx: {
22
+ flexGrow: 1,
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ overflow: 'auto',
26
+ ...props.sx,
27
+ }, children: (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { mt: 2, mx: 2, flexGrow: 1, display: 'flex', flexDirection: 'column' }, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { flexGrow: 1, width: '100%', mx: 'auto', maxWidth }, children: [messages.map((msg) => {
28
+ var _a, _b;
29
+ const actions = customActions === null || customActions === void 0 ? void 0 : customActions(msg);
30
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { id: `conversation-${msg.id}`, children: [!(0, isNil_1.default)(msg.prompt) && ((0, jsx_runtime_1.jsx)(message_1.default, { avatar: (_a = renderAvatar === null || renderAvatar === void 0 ? void 0 : renderAvatar(msg, false)) !== null && _a !== void 0 ? _a : (0, jsx_runtime_1.jsx)(material_1.Avatar, { sx: { bgcolor: 'secondary.main' }, children: "\uD83E\uDDD1" }), message: msg.prompt, actions: actions === null || actions === void 0 ? void 0 : actions[0] })), (!(0, isNil_1.default)(msg.response) || !(0, isNil_1.default)(msg.loading) || !(0, isNil_1.default)(msg.error)) && ((0, jsx_runtime_1.jsxs)(message_1.default, { my: 1, id: `response-${msg.id}`, loading: msg.loading && !!msg.response, message: typeof msg.response === 'string' ? msg.response : undefined, avatar: (_b = renderAvatar === null || renderAvatar === void 0 ? void 0 : renderAvatar(msg, true)) !== null && _b !== void 0 ? _b : (0, jsx_runtime_1.jsx)(material_1.Avatar, { sx: { bgcolor: 'primary.main' }, children: "\uD83E\uDD16\uFE0F" }), actions: actions === null || actions === void 0 ? void 0 : actions[1], children: [Array.isArray(msg.response) && ((0, jsx_runtime_1.jsx)(image_preview_1.default, { itemWidth: 100, dataSource: msg.response.map(({ url }) => {
31
+ return {
32
+ src: url,
33
+ onLoad: () => scrollToBottom(),
34
+ };
35
+ }) })), msg.error ? ((0, jsx_runtime_1.jsx)(alert_1.default, { error: msg.error })) : (msg.loading &&
36
+ !msg.response && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
37
+ minHeight: 24,
38
+ display: 'flex',
39
+ alignItems: 'center',
40
+ }, children: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 16 }) })))] }))] }, msg.id));
41
+ }), element] }), (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { mx: 'auto', width: '100%', maxWidth, position: 'sticky', bottom: 0 }, children: [(0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
42
+ height: 16,
43
+ pointerEvents: 'none',
44
+ background: (theme) => `linear-gradient(transparent, ${theme.palette.background.paper})`,
45
+ } }), (0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
46
+ pb: 2,
47
+ bgcolor: 'background.paper',
48
+ }, children: (0, jsx_runtime_1.jsx)(prompt_1.default, { onSubmit: onSubmit, ...promptProps }) })] })] }) }));
49
+ }
50
+ const STICKY_SCROLL_BOTTOM_GAP = 5;
51
+ const useAutoScrollToBottom = ({ scroller }) => {
52
+ const element = (0, react_1.useRef)(null);
53
+ const enableAutoScrollBottom = (0, react_1.useRef)(true);
54
+ (0, react_1.useEffect)(() => {
55
+ const e = scroller.current;
56
+ if (!e) {
57
+ return () => { };
58
+ }
59
+ const listener = () => {
60
+ enableAutoScrollBottom.current = e.clientHeight + e.scrollTop >= e.scrollHeight - STICKY_SCROLL_BOTTOM_GAP;
61
+ };
62
+ e.addEventListener('scroll', listener);
63
+ return () => e.removeEventListener('scroll', listener);
64
+ }, [scroller]);
65
+ const scrollToBottom = (0, react_1.useCallback)(({ force } = {}) => {
66
+ if (force || enableAutoScrollBottom.current) {
67
+ setTimeout(() => { var _a, _b; return (_b = (_a = element.current) === null || _a === void 0 ? void 0 : _a.scrollIntoViewIfNeeded) === null || _b === void 0 ? void 0 : _b.call(_a); });
68
+ }
69
+ }, []);
70
+ return { element: (0, jsx_runtime_1.jsx)("div", { ref: element }), scrollToBottom };
71
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.useConversation = void 0;
21
+ const conversation_1 = __importDefault(require("./conversation"));
22
+ exports.default = conversation_1.default;
23
+ __exportStar(require("./conversation"), exports);
24
+ var use_conversation_1 = require("./use-conversation");
25
+ Object.defineProperty(exports, "useConversation", { enumerable: true, get: function () { return __importDefault(use_conversation_1).default; } });
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = Message;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const css_1 = require("@emotion/css");
9
+ const styled_1 = __importDefault(require("@emotion/styled"));
10
+ const icons_material_1 = require("@mui/icons-material");
11
+ const material_1 = require("@mui/material");
12
+ const react_1 = require("react");
13
+ const react_markdown_1 = __importDefault(require("react-markdown"));
14
+ function Message({ avatar = undefined, message = undefined, children = undefined, loading = false, actions = undefined, ...props }) {
15
+ const text = (0, react_1.useMemo)(() => (typeof message === 'string' ? message : message === null || message === void 0 ? void 0 : message.map((i) => `${i.role}: ${i.content}`).join('\n\n')), [message]);
16
+ return ((0, jsx_runtime_1.jsxs)(Root, { ...props, display: "flex", children: [(0, jsx_runtime_1.jsx)(material_1.Box, { className: "avatar", sx: {
17
+ mr: 1,
18
+ }, children: avatar }), (0, jsx_runtime_1.jsxs)(material_1.Box, { className: (0, css_1.cx)('content'), children: [(0, jsx_runtime_1.jsx)(material_1.Box, { component: react_markdown_1.default, className: (0, css_1.cx)('message', loading && 'cursor'), children: text }), children, (0, jsx_runtime_1.jsxs)(material_1.Box, { className: "actions", children: [actions, text && (0, jsx_runtime_1.jsx)(CopyButton, { message: text }, "copy")] })] })] }));
19
+ }
20
+ function CopyButton({ message }) {
21
+ const [copied, setCopied] = (0, react_1.useState)(false);
22
+ return ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { title: copied === 'copied' ? 'Copied!' : 'Copy', placement: "top", open: Boolean(copied), children: (0, jsx_runtime_1.jsx)(material_1.Button, { size: "small", className: (0, css_1.cx)('copy', copied && 'active'), onMouseEnter: () => setCopied(true), onMouseLeave: () => setCopied(false), onClick: () => {
23
+ navigator.clipboard.writeText(message);
24
+ setCopied('copied');
25
+ setTimeout(() => setCopied(false), 1500);
26
+ }, children: (0, jsx_runtime_1.jsx)(icons_material_1.CopyAll, { fontSize: "small" }) }) }));
27
+ }
28
+ const Root = (0, styled_1.default)(material_1.Box) `
29
+ > .avatar {
30
+ padding-top: 5px;
31
+
32
+ > .MuiAvatar-root {
33
+ width: 30px;
34
+ height: 30px;
35
+ }
36
+ }
37
+
38
+ > .content {
39
+ min-height: 40px;
40
+ flex: 1;
41
+ overflow: hidden;
42
+ word-break: break-word;
43
+ padding: 8px;
44
+ border-radius: 4px;
45
+ position: relative;
46
+
47
+ > .message {
48
+ > *:first-of-type {
49
+ margin-top: 0;
50
+ }
51
+ > *:last-child {
52
+ margin-bottom: 0;
53
+ }
54
+
55
+ pre {
56
+ line-height: 1.2;
57
+ background-color: #f6f8fa;
58
+ overflow: auto;
59
+ padding: 16px;
60
+ border-radius: 3px;
61
+ }
62
+
63
+ &.cursor {
64
+ > *:last-child {
65
+ &:after {
66
+ content: '';
67
+ display: inline-block;
68
+ vertical-align: middle;
69
+ height: 1em;
70
+ margin-top: -0.15em;
71
+ margin-left: 0.15em;
72
+ border-right: 0.15em solid orange;
73
+ animation: blink-caret 0.75s step-end infinite;
74
+
75
+ @keyframes blink-caret {
76
+ from,
77
+ to {
78
+ border-color: transparent;
79
+ }
80
+ 50% {
81
+ border-color: orange;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+
89
+ > .actions {
90
+ position: absolute;
91
+ right: 2px;
92
+ top: 2px;
93
+ border-radius: 4px;
94
+ opacity: 0;
95
+
96
+ &.active {
97
+ display: flex;
98
+ }
99
+
100
+ button {
101
+ min-width: 0;
102
+ padding: 0;
103
+ height: 24px;
104
+ width: 22px;
105
+ color: rgba(0, 0, 0, 0.4);
106
+ }
107
+ }
108
+ }
109
+
110
+ &:hover {
111
+ > .content {
112
+ background-color: rgba(0, 0, 0, 0.05);
113
+
114
+ > .actions {
115
+ opacity: 1;
116
+ background-color: rgba(240, 240, 240, 0.9);
117
+ }
118
+ }
119
+ }
120
+ `;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = Prompt;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const icons_material_1 = require("@mui/icons-material");
6
+ const material_1 = require("@mui/material");
7
+ const ahooks_1 = require("ahooks");
8
+ const react_1 = require("react");
9
+ function Prompt({ startAdornment = undefined, endAdornment = undefined, onSubmit, slotProps = {}, sx = {}, ...props }) {
10
+ const [prompt, setPrompt] = (0, react_1.useState)('');
11
+ const { value: historyPrompt, setValue: setHistoryPrompt, forwardLength, back, go, forward } = (0, ahooks_1.useHistoryTravel)('');
12
+ const submit = () => {
13
+ if (!prompt.trim()) {
14
+ return;
15
+ }
16
+ go(forwardLength);
17
+ // wait for history to set before submitting
18
+ setTimeout(() => {
19
+ setHistoryPrompt(prompt);
20
+ onSubmit(prompt);
21
+ setPrompt('');
22
+ }, 50);
23
+ };
24
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { ...props, sx: { display: 'flex', gap: 1, alignItems: 'center', ...sx }, component: "form", onSubmit: (e) => e.preventDefault(), children: [startAdornment, (0, jsx_runtime_1.jsx)(material_1.Input, { fullWidth: true, disableUnderline: true, value: prompt, multiline: true, maxRows: 10, sx: { py: 0.8, px: 1, boxShadow: 2, borderRadius: 1 }, onChange: (e) => setPrompt(e.target.value), onKeyDown: (e) => {
25
+ if (e.keyCode === 229) {
26
+ return;
27
+ }
28
+ if (!e.shiftKey && e.key === 'Enter') {
29
+ e.preventDefault();
30
+ submit();
31
+ }
32
+ else if (e.key === 'ArrowUp') {
33
+ e.preventDefault();
34
+ back();
35
+ setPrompt(historyPrompt || '');
36
+ }
37
+ else if (e.key === 'ArrowDown') {
38
+ e.preventDefault();
39
+ forward();
40
+ setPrompt(historyPrompt || '');
41
+ }
42
+ }, endAdornment: (0, jsx_runtime_1.jsx)(material_1.InputAdornment, { position: "end", children: (0, jsx_runtime_1.jsx)(material_1.IconButton, { onClick: submit, size: "small", type: "submit", children: (0, jsx_runtime_1.jsx)(icons_material_1.Send, { fontSize: "small" }) }) }), ...slotProps }), endAdornment] }));
43
+ }