@kafca/agentdock 0.1.54 → 0.1.56

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 (69) hide show
  1. package/README.md +12 -0
  2. package/dist/renderer/assets/{Badge-Rs12sArE.js → Badge-DjcoXx2J.js} +1 -1
  3. package/dist/renderer/assets/{Chat-C9KfsjuN.js → Chat-C5Bkm9-M.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-C3m7Mxpl.js → ChatMarkdown-uc36EzyD.js} +1 -1
  5. package/dist/renderer/assets/{Config-BhIq2lQa.js → Config-DHtQuuLy.js} +1 -1
  6. package/dist/renderer/assets/{CronList-CenDzorW.js → CronList-BYUnhzSC.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-BmeP5ocP.js → Dashboard-BPnGMDg3.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-BGONB4VS.js → EmptyState-DIZLiccW.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-Ba3PuI7k.js → KnowledgeDetail-CJ9IYOsa.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeHome-DkKXM7Bd.js → KnowledgeHome-BLGPwnBO.js} +1 -1
  11. package/dist/renderer/assets/{Logs-DTITWY-y.js → Logs-Dyd2Uwlt.js} +1 -1
  12. package/dist/renderer/assets/{Modal-BvFew60s.js → Modal-CQiUpfl4.js} +1 -1
  13. package/dist/renderer/assets/{MonitorList-DruqInIG.js → MonitorList-Byg3E3Gt.js} +1 -1
  14. package/dist/renderer/assets/{Page-CLjmm8c6.js → Page-7DxXvTMm.js} +1 -1
  15. package/dist/renderer/assets/{ProjectDetail-BCFaJig0.js → ProjectDetail-Dfr5s0Ja.js} +1 -1
  16. package/dist/renderer/assets/{ProjectList-Btg-mgwA.js → ProjectList-CDDQjAQ_.js} +1 -1
  17. package/dist/renderer/assets/{Select-CAwaG7ol.js → Select-D6z65IT3.js} +1 -1
  18. package/dist/renderer/assets/{SessionChat-CHPrm0Zs.js → SessionChat-s7CAaCPL.js} +1 -1
  19. package/dist/renderer/assets/{SessionList-0aGulton.js → SessionList-D-OycKKS.js} +1 -1
  20. package/dist/renderer/assets/{ThreadChat-BkSc0hKN.js → ThreadChat-CLdFynB5.js} +1 -1
  21. package/dist/renderer/assets/Workspace-xfT5z4j_.js +19 -0
  22. package/dist/renderer/assets/{arrow-left-Co19QKUc.js → arrow-left-CV5cL3f4.js} +1 -1
  23. package/dist/renderer/assets/{book-open-CtlUo2yw.js → book-open-DThvB7pj.js} +1 -1
  24. package/dist/renderer/assets/{bot-D-3jCeDr.js → bot-CWQ5-ovl.js} +1 -1
  25. package/dist/renderer/assets/{check-Cf5Y5H-1.js → check-DKM7zfWG.js} +1 -1
  26. package/dist/renderer/assets/{chevron-down-D1tfS-tx.js → chevron-down-Dfw2KU87.js} +1 -1
  27. package/dist/renderer/assets/{circle-DJOCyk2U.js → circle-CoP4RA4s.js} +1 -1
  28. package/dist/renderer/assets/{desktop-CmZMgSXn.js → desktop-CsDYrOOU.js} +1 -1
  29. package/dist/renderer/assets/{funnel-ZRCc1DCy.js → funnel-DpVLlG3g.js} +1 -1
  30. package/dist/renderer/assets/{heart-BuJEvv8x.js → heart-BMD36ejP.js} +1 -1
  31. package/dist/renderer/assets/{index-CDWUe2Sw.js → index-COxSYBjE.js} +2 -2
  32. package/dist/renderer/assets/{index-0gZsyozU.js → index-CTGTI-cm.js} +1 -1
  33. package/dist/renderer/assets/{pencil-sISh8tMs.js → pencil-Dv5WxhdC.js} +1 -1
  34. package/dist/renderer/assets/{play-CccQpZit.js → play-DnCnft83.js} +1 -1
  35. package/dist/renderer/assets/{plus-hxAkcfQ0.js → plus-DsxIagzS.js} +1 -1
  36. package/dist/renderer/assets/projects-DgjHcNgt.js +1 -0
  37. package/dist/renderer/assets/{save-By5b-_0Q.js → save-CST01lIc.js} +1 -1
  38. package/dist/renderer/assets/{search-CLzr87Rw.js → search-B_bqy6Wd.js} +1 -1
  39. package/dist/renderer/assets/{server-CubB1eW5.js → server-ecH4GNwa.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-Cz45af_C.js → session-utils-Dd_WKMYW.js} +1 -1
  41. package/dist/renderer/assets/{sessions-C8np5fRp.js → sessions-BQ33Mv4k.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-CemAc1Ry.js → shield-check-D6lG5Aoc.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-DFKhii8D.js → trash-2-Cefngb6Q.js} +1 -1
  44. package/dist/renderer/assets/{user-CaR8Rru_.js → user-D_8RSH-T.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-C8miJu8i.js → wifi-off-DB9D-pOu.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +1 -1
  48. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +1 -1
  49. package/dist-electron/services/local-ai-core/src/acp/store/runtime-config-store.js +39 -28
  50. package/dist-electron/services/local-ai-core/src/channel/lark/config.js +4 -16
  51. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +154 -65
  52. package/dist-electron/services/local-ai-core/src/channel/shared/channel-keys.js +16 -0
  53. package/dist-electron/services/local-ai-core/src/channel/shared/inbound-attachment-store.js +93 -0
  54. package/dist-electron/services/local-ai-core/src/channel/weixin/config.js +3 -16
  55. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +70 -35
  56. package/dist-electron/services/local-ai-core/src/kernel/local-core-errors.js +33 -5
  57. package/dist-electron/services/local-ai-core/src/runtime/channel-service.js +0 -40
  58. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +1 -14
  59. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +1 -14
  60. package/dist-electron/services/local-ai-core/src/runtime/provider-config-migration.js +16 -0
  61. package/dist-electron/services/local-ai-core/src/scheduler/channel-execution-policy.js +4 -6
  62. package/dist-electron/tests/electron/sandbox-config.test.js +5 -0
  63. package/dist-electron/tests/integration/channel-inbound-attachment-store.test.js +117 -0
  64. package/dist-electron/tests/integration/lark-gateway.test.js +81 -1
  65. package/dist-electron/tests/integration/local-core-errors.test.js +41 -0
  66. package/dist-electron/tests/integration/weixin-gateway.test.js +36 -0
  67. package/package.json +1 -1
  68. package/dist/renderer/assets/Workspace-DXJ3BGia.js +0 -19
  69. package/dist/renderer/assets/projects-CjdfXQ1l.js +0 -1
@@ -9,6 +9,7 @@ const node_fs_1 = require("node:fs");
9
9
  const node_os_1 = require("node:os");
10
10
  const node_path_1 = require("node:path");
11
11
  const node_stream_1 = require("node:stream");
12
+ const node_url_1 = require("node:url");
12
13
  const local_core_lark_gateway_js_1 = require("../../services/local-ai-core/src/channel/lark/local-core-lark-gateway.js");
13
14
  const runtime_state_js_1 = require("../../services/local-ai-core/src/channel/lark/runtime-state.js");
14
15
  function extractLarkCreatedMessage(request) {
@@ -1174,6 +1175,7 @@ function findLarkPostMdText(content) {
1174
1175
  });
1175
1176
  (0, node_test_1.default)('lark image messages are downloaded and forwarded as generic channel image parts', async () => {
1176
1177
  const sentMessages = [];
1178
+ const tempDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'lark-image-receive-'));
1177
1179
  const pngBytes = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
1178
1180
  const client = {
1179
1181
  im: {
@@ -1230,6 +1232,7 @@ function findLarkPostMdText(content) {
1230
1232
  }],
1231
1233
  }),
1232
1234
  getWorkspaceRouter: () => ({
1235
+ getWorkspaceRegistryEntry: async () => ({ path: tempDir }),
1233
1236
  getThreadSessionKey: (threadId) => `session:${threadId}`,
1234
1237
  sendThreadMessage: async (threadId, content) => {
1235
1238
  sentMessages.push({ threadId, content });
@@ -1266,9 +1269,14 @@ function findLarkPostMdText(content) {
1266
1269
  strict_1.default.deepEqual(sentMessages[0]?.content?.contentParts?.map((part) => part.type), ['text', 'image']);
1267
1270
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.mimeType, 'image/png');
1268
1271
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, pngBytes.toString('base64'));
1272
+ const imagePath = (0, node_path_1.join)(tempDir, '.agentdock', 'channel-uploads', 'lark', 'default', 'msg-image-1-img-key-1.png');
1273
+ strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.uri, (0, node_url_1.pathToFileURL)(imagePath).href);
1274
+ strict_1.default.deepEqual((0, node_fs_1.readFileSync)(imagePath), pngBytes);
1275
+ (0, node_fs_1.rmSync)(tempDir, { recursive: true, force: true });
1269
1276
  });
1270
1277
  (0, node_test_1.default)('lark file messages are downloaded and forwarded as generic channel file parts', async () => {
1271
1278
  const sentMessages = [];
1279
+ const tempDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'lark-file-receive-'));
1272
1280
  const fileBytes = Buffer.from('file content');
1273
1281
  const client = {
1274
1282
  im: {
@@ -1325,6 +1333,7 @@ function findLarkPostMdText(content) {
1325
1333
  }],
1326
1334
  }),
1327
1335
  getWorkspaceRouter: () => ({
1336
+ getWorkspaceRegistryEntry: async () => ({ path: tempDir }),
1328
1337
  getThreadSessionKey: (threadId) => `session:${threadId}`,
1329
1338
  sendThreadMessage: async (threadId, content) => {
1330
1339
  sentMessages.push({ threadId, content });
@@ -1360,8 +1369,58 @@ function findLarkPostMdText(content) {
1360
1369
  strict_1.default.match(sentMessages[0]?.content?.displayText, /\[User Message\]\n\[File: report\.pdf\]\n\[\/User Message\]/);
1361
1370
  strict_1.default.deepEqual(sentMessages[0]?.content?.contentParts?.map((part) => part.type), ['text', 'file']);
1362
1371
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.mimeType, 'application/pdf');
1363
- strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, fileBytes.toString('base64'));
1372
+ strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.data, undefined);
1364
1373
  strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.fileName, 'report.pdf');
1374
+ strict_1.default.equal(sentMessages[0]?.content?.contentParts?.[1]?.path, (0, node_path_1.join)(tempDir, '.agentdock', 'channel-uploads', 'lark', 'default', 'msg-file-in-1-report.pdf'));
1375
+ strict_1.default.deepEqual((0, node_fs_1.readFileSync)(sentMessages[0]?.content?.contentParts?.[1]?.path), fileBytes);
1376
+ (0, node_fs_1.rmSync)(tempDir, { recursive: true, force: true });
1377
+ });
1378
+ (0, node_test_1.default)('lark file messages are not downloaded before the sender is authorized', async () => {
1379
+ let resourceDownloads = 0;
1380
+ let inboundMessage;
1381
+ const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
1382
+ store: {
1383
+ getAuthorizedUser: () => undefined,
1384
+ },
1385
+ readConfig: async () => null,
1386
+ getWorkspaceRouter: () => ({}),
1387
+ eventBus: { emit: () => { }, on: () => () => { } },
1388
+ });
1389
+ const internals = gateway;
1390
+ internals.runtime.set('default', {
1391
+ workspaceId: 'default',
1392
+ enabled: true,
1393
+ status: 'running',
1394
+ connected: true,
1395
+ autoApprove: false,
1396
+ client: {
1397
+ im: {
1398
+ messageResource: {
1399
+ get: async () => {
1400
+ resourceDownloads += 1;
1401
+ throw new Error('should not download');
1402
+ },
1403
+ },
1404
+ },
1405
+ },
1406
+ });
1407
+ internals.handleInboundMessage = async (message) => {
1408
+ inboundMessage = message;
1409
+ };
1410
+ await internals.handleMessageEvent('default', {
1411
+ event: {
1412
+ sender: { sender_id: { user_id: 'user-1' } },
1413
+ message: {
1414
+ message_id: 'msg-file-unauthorized',
1415
+ message_type: 'file',
1416
+ chat_id: 'chat-1',
1417
+ content: JSON.stringify({ file_key: 'file-key-1', file_name: 'private.pdf' }),
1418
+ },
1419
+ },
1420
+ });
1421
+ strict_1.default.equal(resourceDownloads, 0);
1422
+ strict_1.default.equal(inboundMessage.text, '[File: private.pdf]');
1423
+ strict_1.default.deepEqual(inboundMessage.contentParts, [{ type: 'text', text: '[File: private.pdf]' }]);
1365
1424
  });
1366
1425
  (0, node_test_1.default)('lark group text messages strip the bot mention before dispatching', async () => {
1367
1426
  const sentMessages = [];
@@ -2055,3 +2114,24 @@ function findLarkPostMdText(content) {
2055
2114
  ['default', 'bot-b', 'cli_b', 'running'],
2056
2115
  ]);
2057
2116
  });
2117
+ (0, node_test_1.default)('lark gateway samples empty-render log per session/type within the dedup window', () => {
2118
+ const logs = [];
2119
+ const gateway = new local_core_lark_gateway_js_1.LocalCoreLarkGateway({
2120
+ store: {},
2121
+ readConfig: async () => null,
2122
+ getWorkspaceRouter: () => ({}),
2123
+ eventBus: { emit: () => { }, on: () => () => { } },
2124
+ log: (message) => logs.push(message),
2125
+ });
2126
+ const internals = gateway;
2127
+ for (let i = 0; i < 5; i += 1) {
2128
+ internals.logEmptyRender('session:thread-1', 'update_message');
2129
+ }
2130
+ internals.logEmptyRender('session:thread-1', 'preview_start');
2131
+ internals.logEmptyRender('session:thread-2', 'update_message');
2132
+ const emptyRenderLogs = logs.filter((line) => line.includes('produced empty render'));
2133
+ strict_1.default.equal(emptyRenderLogs.length, 3);
2134
+ strict_1.default.ok(emptyRenderLogs[0].includes('session:thread-1') && emptyRenderLogs[0].includes('type=update_message'));
2135
+ strict_1.default.ok(emptyRenderLogs[1].includes('type=preview_start'));
2136
+ strict_1.default.ok(emptyRenderLogs[2].includes('session:thread-2'));
2137
+ });
@@ -0,0 +1,41 @@
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 node_test_1 = __importDefault(require("node:test"));
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const local_core_errors_js_1 = require("../../services/local-ai-core/src/kernel/local-core-errors.js");
9
+ (0, node_test_1.default)('LocalCoreError coerces non-string message into a string', () => {
10
+ const err = new local_core_errors_js_1.LocalCoreError('internal_error', { weird: 'shape' });
11
+ strict_1.default.equal(typeof err.info.message, 'string');
12
+ strict_1.default.equal(err.message, err.info.message);
13
+ strict_1.default.ok(err.info.message.includes('"weird"'));
14
+ const line = (0, local_core_errors_js_1.formatLogError)(err.info);
15
+ strict_1.default.ok(!line.includes('[object Object]'), `log line leaked [object Object]: ${line}`);
16
+ });
17
+ (0, node_test_1.default)('toLocalCoreErrorInfo stringifies Error whose message is an object', () => {
18
+ const raw = new Error('');
19
+ raw.message = { nested: 'value' };
20
+ const info = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(raw);
21
+ strict_1.default.equal(typeof info.message, 'string');
22
+ const line = (0, local_core_errors_js_1.formatLogError)(info);
23
+ strict_1.default.ok(!line.includes('[object Object]'), `log line leaked [object Object]: ${line}`);
24
+ });
25
+ (0, node_test_1.default)('toLocalCoreErrorInfo preserves runtime_protocol_timeout classification for timeout string', () => {
26
+ const info = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(new Error('Timed out waiting for ACP session/prompt after 900000ms'));
27
+ strict_1.default.equal(info.code, 'runtime_protocol_timeout');
28
+ strict_1.default.equal(typeof info.message, 'string');
29
+ });
30
+ (0, node_test_1.default)('formatLogError renders cause suffix when present', () => {
31
+ const err = new local_core_errors_js_1.LocalCoreError('runtime_exited', 'child crashed', { cause: 'SIGTERM' });
32
+ const line = (0, local_core_errors_js_1.formatLogError)(err.info);
33
+ strict_1.default.equal(line, 'runtime_exited: child crashed cause=SIGTERM');
34
+ });
35
+ (0, node_test_1.default)('toLocalCoreErrorInfo carries details through LocalCoreError instances', () => {
36
+ const base = new local_core_errors_js_1.LocalCoreError('runtime_protocol_timeout', 'Timed out waiting for ACP session/prompt after 100ms');
37
+ const info = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(base, 'internal_error', { threadId: 'thread-x', runtimeId: 'hermes' });
38
+ strict_1.default.equal(info.code, 'runtime_protocol_timeout');
39
+ strict_1.default.equal(info.details?.threadId, 'thread-x');
40
+ strict_1.default.equal(info.details?.runtimeId, 'hermes');
41
+ });
@@ -5,10 +5,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const node_test_1 = __importDefault(require("node:test"));
7
7
  const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
9
  const node_fs_1 = require("node:fs");
9
10
  const node_os_1 = require("node:os");
10
11
  const node_path_1 = require("node:path");
12
+ const node_url_1 = require("node:url");
11
13
  const local_core_weixin_gateway_js_1 = require("../../services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js");
14
+ (0, node_test_1.default)('weixin inbound attachment source streams AES-decrypted files into the shared store', async () => {
15
+ const tempDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'weixin-file-receive-'));
16
+ const originalFetch = globalThis.fetch;
17
+ try {
18
+ const plaintext = Buffer.from('%PDF streamed file');
19
+ const aesKey = node_crypto_1.default.randomBytes(16);
20
+ const cipher = node_crypto_1.default.createCipheriv('aes-128-ecb', aesKey, null);
21
+ const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);
22
+ globalThis.fetch = (async () => new Response(encrypted));
23
+ const gateway = new local_core_weixin_gateway_js_1.LocalCoreWeixinGateway({
24
+ store: {},
25
+ readConfig: async () => null,
26
+ getWorkspaceRouter: () => ({}),
27
+ eventBus: { emit: () => { }, on: () => () => { } },
28
+ });
29
+ const downloaded = await gateway.downloadMediaItem({
30
+ type: 4,
31
+ file_item: {
32
+ file_name: 'report.pdf',
33
+ aeskey: aesKey.toString('hex'),
34
+ media: { encrypt_query_param: 'download-token' },
35
+ },
36
+ }, 'msg-1', 0, tempDir, { cdnBaseUrl: 'https://weixin.example' });
37
+ strict_1.default.equal(downloaded.kind, 'file');
38
+ strict_1.default.deepEqual((0, node_fs_1.readFileSync)(downloaded.path), plaintext);
39
+ strict_1.default.equal(downloaded.data, undefined);
40
+ }
41
+ finally {
42
+ globalThis.fetch = originalFetch;
43
+ (0, node_fs_1.rmSync)(tempDir, { recursive: true, force: true });
44
+ }
45
+ });
12
46
  (0, node_test_1.default)('weixin channel can encrypt, upload, and send a local file', async () => {
13
47
  const tempDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'weixin-file-send-'));
14
48
  const originalFetch = globalThis.fetch;
@@ -388,6 +422,7 @@ const local_core_weixin_gateway_js_1 = require("../../services/local-ai-core/src
388
422
  (0, node_test_1.default)('weixin downloaded image attachment keeps image data content part', () => {
389
423
  const part = (0, local_core_weixin_gateway_js_1.createWeixinAttachmentContentPart)({
390
424
  path: '/tmp/image.png',
425
+ uri: (0, node_url_1.pathToFileURL)('/tmp/image.png').href,
391
426
  kind: 'image',
392
427
  name: 'image.png',
393
428
  data: 'aW1n',
@@ -396,6 +431,7 @@ const local_core_weixin_gateway_js_1 = require("../../services/local-ai-core/src
396
431
  strict_1.default.deepEqual(part, {
397
432
  type: 'image',
398
433
  data: 'aW1n',
434
+ uri: (0, node_url_1.pathToFileURL)('/tmp/image.png').href,
399
435
  mimeType: 'image/png',
400
436
  fileName: 'image.png',
401
437
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.54",
3
+ "version": "0.1.56",
4
4
  "license": "PolyForm-Noncommercial-1.0.0",
5
5
  "type": "module",
6
6
  "main": "dist-electron/electron/main.js",
@@ -1,19 +0,0 @@
1
- import{c as ft,A as D,j as t,B as T,F as Wt,I as L,S as Kt,y as Xt,r as S}from"./index-CDWUe2Sw.js";import{M as it}from"./Modal-BvFew60s.js";import{S as Z}from"./Select-CAwaG7ol.js";import{E as Oe}from"./EmptyState-BGONB4VS.js";import{S as gt,a as Pe,P as qt}from"./Page-CLjmm8c6.js";import{c as Jt,d as Zt,e as es,t as ts,f as Ne,h as ss,i as as,j as ns,k as rs,m as os,n as is,p as lt}from"./desktop-CmZMgSXn.js";import{c as pt,D as ze,d as ls,e as De,f as Me,g as Ae,h as cs,j as ct,k as dt,l as ds}from"./desktop-JQkhNOF4.js";import{T as Te}from"./trash-2-DFKhii8D.js";import{P as Ce}from"./plus-hxAkcfQ0.js";import{B as ms}from"./bot-D-3jCeDr.js";import{P as us,S as we}from"./save-By5b-_0Q.js";import"./index-0gZsyozU.js";import"./chevron-down-D1tfS-tx.js";import"./check-Cf5Y5H-1.js";/**
2
- * @license lucide-react v0.487.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const hs=[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]],fs=ft("cloud",hs);/**
7
- * @license lucide-react v0.487.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const gs=[["rect",{width:"5",height:"5",x:"3",y:"3",rx:"1",key:"1tu5fj"}],["rect",{width:"5",height:"5",x:"16",y:"3",rx:"1",key:"1v8r4q"}],["rect",{width:"5",height:"5",x:"3",y:"16",rx:"1",key:"1x03jg"}],["path",{d:"M21 16h-3a2 2 0 0 0-2 2v3",key:"177gqh"}],["path",{d:"M21 21v.01",key:"ents32"}],["path",{d:"M12 7v3a2 2 0 0 1-2 2H7",key:"8crl2c"}],["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M12 3h.01",key:"n36tog"}],["path",{d:"M12 16v.01",key:"133mhm"}],["path",{d:"M16 12h1",key:"1slzba"}],["path",{d:"M21 12v.01",key:"1lwtk9"}],["path",{d:"M12 21v-1",key:"1880an"}]],mt=ft("qr-code",gs);var ps=Object.defineProperty,_e=Object.getOwnPropertySymbols,xt=Object.prototype.hasOwnProperty,vt=Object.prototype.propertyIsEnumerable,ut=(s,l,o)=>l in s?ps(s,l,{enumerable:!0,configurable:!0,writable:!0,value:o}):s[l]=o,Re=(s,l)=>{for(var o in l||(l={}))xt.call(l,o)&&ut(s,o,l[o]);if(_e)for(var o of _e(l))vt.call(l,o)&&ut(s,o,l[o]);return s},Ie=(s,l)=>{var o={};for(var m in s)xt.call(s,m)&&l.indexOf(m)<0&&(o[m]=s[m]);if(s!=null&&_e)for(var m of _e(s))l.indexOf(m)<0&&vt.call(s,m)&&(o[m]=s[m]);return o};/**
12
- * @license QR Code generator library (TypeScript)
13
- * Copyright (c) Project Nayuki.
14
- * SPDX-License-Identifier: MIT
15
- */var oe;(s=>{const l=class N{constructor(e,a,n,i){if(this.version=e,this.errorCorrectionLevel=a,this.modules=[],this.isFunction=[],e<N.MIN_VERSION||e>N.MAX_VERSION)throw new RangeError("Version value out of range");if(i<-1||i>7)throw new RangeError("Mask value out of range");this.size=e*4+17;let c=[];for(let u=0;u<this.size;u++)c.push(!1);for(let u=0;u<this.size;u++)this.modules.push(c.slice()),this.isFunction.push(c.slice());this.drawFunctionPatterns();const h=this.addEccAndInterleave(n);if(this.drawCodewords(h),i==-1){let u=1e9;for(let v=0;v<8;v++){this.applyMask(v),this.drawFormatBits(v);const _=this.getPenaltyScore();_<u&&(i=v,u=_),this.applyMask(v)}}g(0<=i&&i<=7),this.mask=i,this.applyMask(i),this.drawFormatBits(i),this.isFunction=[]}static encodeText(e,a){const n=s.QrSegment.makeSegments(e);return N.encodeSegments(n,a)}static encodeBinary(e,a){const n=s.QrSegment.makeBytes(e);return N.encodeSegments([n],a)}static encodeSegments(e,a,n=1,i=40,c=-1,h=!0){if(!(N.MIN_VERSION<=n&&n<=i&&i<=N.MAX_VERSION)||c<-1||c>7)throw new RangeError("Invalid value");let u,v;for(u=n;;u++){const w=N.getNumDataCodewords(u,a)*8,A=j.getTotalBits(e,u);if(A<=w){v=A;break}if(u>=i)throw new RangeError("Data too long")}for(const w of[N.Ecc.MEDIUM,N.Ecc.QUARTILE,N.Ecc.HIGH])h&&v<=N.getNumDataCodewords(u,w)*8&&(a=w);let _=[];for(const w of e){o(w.mode.modeBits,4,_),o(w.numChars,w.mode.numCharCountBits(u),_);for(const A of w.getData())_.push(A)}g(_.length==v);const p=N.getNumDataCodewords(u,a)*8;g(_.length<=p),o(0,Math.min(4,p-_.length),_),o(0,(8-_.length%8)%8,_),g(_.length%8==0);for(let w=236;_.length<p;w^=253)o(w,8,_);let P=[];for(;P.length*8<_.length;)P.push(0);return _.forEach((w,A)=>P[A>>>3]|=w<<7-(A&7)),new N(u,a,P,c)}getModule(e,a){return 0<=e&&e<this.size&&0<=a&&a<this.size&&this.modules[a][e]}getModules(){return this.modules}drawFunctionPatterns(){for(let n=0;n<this.size;n++)this.setFunctionModule(6,n,n%2==0),this.setFunctionModule(n,6,n%2==0);this.drawFinderPattern(3,3),this.drawFinderPattern(this.size-4,3),this.drawFinderPattern(3,this.size-4);const e=this.getAlignmentPatternPositions(),a=e.length;for(let n=0;n<a;n++)for(let i=0;i<a;i++)n==0&&i==0||n==0&&i==a-1||n==a-1&&i==0||this.drawAlignmentPattern(e[n],e[i]);this.drawFormatBits(0),this.drawVersion()}drawFormatBits(e){const a=this.errorCorrectionLevel.formatBits<<3|e;let n=a;for(let c=0;c<10;c++)n=n<<1^(n>>>9)*1335;const i=(a<<10|n)^21522;g(i>>>15==0);for(let c=0;c<=5;c++)this.setFunctionModule(8,c,m(i,c));this.setFunctionModule(8,7,m(i,6)),this.setFunctionModule(8,8,m(i,7)),this.setFunctionModule(7,8,m(i,8));for(let c=9;c<15;c++)this.setFunctionModule(14-c,8,m(i,c));for(let c=0;c<8;c++)this.setFunctionModule(this.size-1-c,8,m(i,c));for(let c=8;c<15;c++)this.setFunctionModule(8,this.size-15+c,m(i,c));this.setFunctionModule(8,this.size-8,!0)}drawVersion(){if(this.version<7)return;let e=this.version;for(let n=0;n<12;n++)e=e<<1^(e>>>11)*7973;const a=this.version<<12|e;g(a>>>18==0);for(let n=0;n<18;n++){const i=m(a,n),c=this.size-11+n%3,h=Math.floor(n/3);this.setFunctionModule(c,h,i),this.setFunctionModule(h,c,i)}}drawFinderPattern(e,a){for(let n=-4;n<=4;n++)for(let i=-4;i<=4;i++){const c=Math.max(Math.abs(i),Math.abs(n)),h=e+i,u=a+n;0<=h&&h<this.size&&0<=u&&u<this.size&&this.setFunctionModule(h,u,c!=2&&c!=4)}}drawAlignmentPattern(e,a){for(let n=-2;n<=2;n++)for(let i=-2;i<=2;i++)this.setFunctionModule(e+i,a+n,Math.max(Math.abs(i),Math.abs(n))!=1)}setFunctionModule(e,a,n){this.modules[a][e]=n,this.isFunction[a][e]=!0}addEccAndInterleave(e){const a=this.version,n=this.errorCorrectionLevel;if(e.length!=N.getNumDataCodewords(a,n))throw new RangeError("Invalid argument");const i=N.NUM_ERROR_CORRECTION_BLOCKS[n.ordinal][a],c=N.ECC_CODEWORDS_PER_BLOCK[n.ordinal][a],h=Math.floor(N.getNumRawDataModules(a)/8),u=i-h%i,v=Math.floor(h/i);let _=[];const p=N.reedSolomonComputeDivisor(c);for(let w=0,A=0;w<i;w++){let $=e.slice(A,A+v-c+(w<u?0:1));A+=$.length;const W=N.reedSolomonComputeRemainder($,p);w<u&&$.push(0),_.push($.concat(W))}let P=[];for(let w=0;w<_[0].length;w++)_.forEach((A,$)=>{(w!=v-c||$>=u)&&P.push(A[w])});return g(P.length==h),P}drawCodewords(e){if(e.length!=Math.floor(N.getNumRawDataModules(this.version)/8))throw new RangeError("Invalid argument");let a=0;for(let n=this.size-1;n>=1;n-=2){n==6&&(n=5);for(let i=0;i<this.size;i++)for(let c=0;c<2;c++){const h=n-c,v=(n+1&2)==0?this.size-1-i:i;!this.isFunction[v][h]&&a<e.length*8&&(this.modules[v][h]=m(e[a>>>3],7-(a&7)),a++)}}g(a==e.length*8)}applyMask(e){if(e<0||e>7)throw new RangeError("Mask value out of range");for(let a=0;a<this.size;a++)for(let n=0;n<this.size;n++){let i;switch(e){case 0:i=(n+a)%2==0;break;case 1:i=a%2==0;break;case 2:i=n%3==0;break;case 3:i=(n+a)%3==0;break;case 4:i=(Math.floor(n/3)+Math.floor(a/2))%2==0;break;case 5:i=n*a%2+n*a%3==0;break;case 6:i=(n*a%2+n*a%3)%2==0;break;case 7:i=((n+a)%2+n*a%3)%2==0;break;default:throw new Error("Unreachable")}!this.isFunction[a][n]&&i&&(this.modules[a][n]=!this.modules[a][n])}}getPenaltyScore(){let e=0;for(let c=0;c<this.size;c++){let h=!1,u=0,v=[0,0,0,0,0,0,0];for(let _=0;_<this.size;_++)this.modules[c][_]==h?(u++,u==5?e+=N.PENALTY_N1:u>5&&e++):(this.finderPenaltyAddHistory(u,v),h||(e+=this.finderPenaltyCountPatterns(v)*N.PENALTY_N3),h=this.modules[c][_],u=1);e+=this.finderPenaltyTerminateAndCount(h,u,v)*N.PENALTY_N3}for(let c=0;c<this.size;c++){let h=!1,u=0,v=[0,0,0,0,0,0,0];for(let _=0;_<this.size;_++)this.modules[_][c]==h?(u++,u==5?e+=N.PENALTY_N1:u>5&&e++):(this.finderPenaltyAddHistory(u,v),h||(e+=this.finderPenaltyCountPatterns(v)*N.PENALTY_N3),h=this.modules[_][c],u=1);e+=this.finderPenaltyTerminateAndCount(h,u,v)*N.PENALTY_N3}for(let c=0;c<this.size-1;c++)for(let h=0;h<this.size-1;h++){const u=this.modules[c][h];u==this.modules[c][h+1]&&u==this.modules[c+1][h]&&u==this.modules[c+1][h+1]&&(e+=N.PENALTY_N2)}let a=0;for(const c of this.modules)a=c.reduce((h,u)=>h+(u?1:0),a);const n=this.size*this.size,i=Math.ceil(Math.abs(a*20-n*10)/n)-1;return g(0<=i&&i<=9),e+=i*N.PENALTY_N4,g(0<=e&&e<=2568888),e}getAlignmentPatternPositions(){if(this.version==1)return[];{const e=Math.floor(this.version/7)+2,a=this.version==32?26:Math.ceil((this.version*4+4)/(e*2-2))*2;let n=[6];for(let i=this.size-7;n.length<e;i-=a)n.splice(1,0,i);return n}}static getNumRawDataModules(e){if(e<N.MIN_VERSION||e>N.MAX_VERSION)throw new RangeError("Version number out of range");let a=(16*e+128)*e+64;if(e>=2){const n=Math.floor(e/7)+2;a-=(25*n-10)*n-55,e>=7&&(a-=36)}return g(208<=a&&a<=29648),a}static getNumDataCodewords(e,a){return Math.floor(N.getNumRawDataModules(e)/8)-N.ECC_CODEWORDS_PER_BLOCK[a.ordinal][e]*N.NUM_ERROR_CORRECTION_BLOCKS[a.ordinal][e]}static reedSolomonComputeDivisor(e){if(e<1||e>255)throw new RangeError("Degree out of range");let a=[];for(let i=0;i<e-1;i++)a.push(0);a.push(1);let n=1;for(let i=0;i<e;i++){for(let c=0;c<a.length;c++)a[c]=N.reedSolomonMultiply(a[c],n),c+1<a.length&&(a[c]^=a[c+1]);n=N.reedSolomonMultiply(n,2)}return a}static reedSolomonComputeRemainder(e,a){let n=a.map(i=>0);for(const i of e){const c=i^n.shift();n.push(0),a.forEach((h,u)=>n[u]^=N.reedSolomonMultiply(h,c))}return n}static reedSolomonMultiply(e,a){if(e>>>8||a>>>8)throw new RangeError("Byte out of range");let n=0;for(let i=7;i>=0;i--)n=n<<1^(n>>>7)*285,n^=(a>>>i&1)*e;return g(n>>>8==0),n}finderPenaltyCountPatterns(e){const a=e[1];g(a<=this.size*3);const n=a>0&&e[2]==a&&e[3]==a*3&&e[4]==a&&e[5]==a;return(n&&e[0]>=a*4&&e[6]>=a?1:0)+(n&&e[6]>=a*4&&e[0]>=a?1:0)}finderPenaltyTerminateAndCount(e,a,n){return e&&(this.finderPenaltyAddHistory(a,n),a=0),a+=this.size,this.finderPenaltyAddHistory(a,n),this.finderPenaltyCountPatterns(n)}finderPenaltyAddHistory(e,a){a[0]==0&&(e+=this.size),a.pop(),a.unshift(e)}};l.MIN_VERSION=1,l.MAX_VERSION=40,l.PENALTY_N1=3,l.PENALTY_N2=3,l.PENALTY_N3=40,l.PENALTY_N4=10,l.ECC_CODEWORDS_PER_BLOCK=[[-1,7,10,15,20,26,18,20,24,30,18,20,24,26,30,22,24,28,30,28,28,28,28,30,30,26,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,10,16,26,18,24,16,18,22,22,26,30,22,22,24,24,28,28,26,26,26,26,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28],[-1,13,22,18,26,18,24,18,22,20,24,28,26,24,20,30,24,28,28,26,30,28,30,30,30,30,28,30,30,30,30,30,30,30,30,30,30,30,30,30,30],[-1,17,28,22,16,22,28,26,26,24,28,24,28,22,24,24,30,28,28,26,28,30,24,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30]],l.NUM_ERROR_CORRECTION_BLOCKS=[[-1,1,1,1,1,1,2,2,2,2,4,4,4,4,4,6,6,6,6,7,8,8,9,9,10,12,12,12,13,14,15,16,17,18,19,19,20,21,22,24,25],[-1,1,1,1,2,2,4,4,4,5,5,5,8,9,9,10,10,11,13,14,16,17,17,18,20,21,23,25,26,28,29,31,33,35,37,38,40,43,45,47,49],[-1,1,1,2,2,4,4,6,6,8,8,8,10,12,16,12,17,16,18,21,20,23,23,25,27,29,34,34,35,38,40,43,45,48,51,53,56,59,62,65,68],[-1,1,1,2,4,4,4,5,6,8,8,11,11,16,16,18,16,19,21,25,25,25,34,30,32,35,37,40,42,45,48,51,54,57,60,63,66,70,74,77,81]],s.QrCode=l;function o(b,e,a){if(e<0||e>31||b>>>e)throw new RangeError("Value out of range");for(let n=e-1;n>=0;n--)a.push(b>>>n&1)}function m(b,e){return(b>>>e&1)!=0}function g(b){if(!b)throw new Error("Assertion error")}const f=class I{constructor(e,a,n){if(this.mode=e,this.numChars=a,this.bitData=n,a<0)throw new RangeError("Invalid argument");this.bitData=n.slice()}static makeBytes(e){let a=[];for(const n of e)o(n,8,a);return new I(I.Mode.BYTE,e.length,a)}static makeNumeric(e){if(!I.isNumeric(e))throw new RangeError("String contains non-numeric characters");let a=[];for(let n=0;n<e.length;){const i=Math.min(e.length-n,3);o(parseInt(e.substring(n,n+i),10),i*3+1,a),n+=i}return new I(I.Mode.NUMERIC,e.length,a)}static makeAlphanumeric(e){if(!I.isAlphanumeric(e))throw new RangeError("String contains unencodable characters in alphanumeric mode");let a=[],n;for(n=0;n+2<=e.length;n+=2){let i=I.ALPHANUMERIC_CHARSET.indexOf(e.charAt(n))*45;i+=I.ALPHANUMERIC_CHARSET.indexOf(e.charAt(n+1)),o(i,11,a)}return n<e.length&&o(I.ALPHANUMERIC_CHARSET.indexOf(e.charAt(n)),6,a),new I(I.Mode.ALPHANUMERIC,e.length,a)}static makeSegments(e){return e==""?[]:I.isNumeric(e)?[I.makeNumeric(e)]:I.isAlphanumeric(e)?[I.makeAlphanumeric(e)]:[I.makeBytes(I.toUtf8ByteArray(e))]}static makeEci(e){let a=[];if(e<0)throw new RangeError("ECI assignment value out of range");if(e<128)o(e,8,a);else if(e<16384)o(2,2,a),o(e,14,a);else if(e<1e6)o(6,3,a),o(e,21,a);else throw new RangeError("ECI assignment value out of range");return new I(I.Mode.ECI,0,a)}static isNumeric(e){return I.NUMERIC_REGEX.test(e)}static isAlphanumeric(e){return I.ALPHANUMERIC_REGEX.test(e)}getData(){return this.bitData.slice()}static getTotalBits(e,a){let n=0;for(const i of e){const c=i.mode.numCharCountBits(a);if(i.numChars>=1<<c)return 1/0;n+=4+c+i.bitData.length}return n}static toUtf8ByteArray(e){e=encodeURI(e);let a=[];for(let n=0;n<e.length;n++)e.charAt(n)!="%"?a.push(e.charCodeAt(n)):(a.push(parseInt(e.substring(n+1,n+3),16)),n+=2);return a}};f.NUMERIC_REGEX=/^[0-9]*$/,f.ALPHANUMERIC_REGEX=/^[A-Z0-9 $%*+.\/:-]*$/,f.ALPHANUMERIC_CHARSET="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";let j=f;s.QrSegment=f})(oe||(oe={}));(s=>{(l=>{const o=class{constructor(g,f){this.ordinal=g,this.formatBits=f}};o.LOW=new o(0,1),o.MEDIUM=new o(1,0),o.QUARTILE=new o(2,3),o.HIGH=new o(3,2),l.Ecc=o})(s.QrCode||(s.QrCode={}))})(oe||(oe={}));(s=>{(l=>{const o=class{constructor(g,f){this.modeBits=g,this.numBitsCharCount=f}numCharCountBits(g){return this.numBitsCharCount[Math.floor((g+7)/17)]}};o.NUMERIC=new o(1,[10,12,14]),o.ALPHANUMERIC=new o(2,[9,11,13]),o.BYTE=new o(4,[8,16,16]),o.KANJI=new o(8,[8,10,12]),o.ECI=new o(7,[0,0,0]),l.Mode=o})(s.QrSegment||(s.QrSegment={}))})(oe||(oe={}));var ue=oe;/**
16
- * @license qrcode.react
17
- * Copyright (c) Paul O'Shannessy
18
- * SPDX-License-Identifier: ISC
19
- */var xs={L:ue.QrCode.Ecc.LOW,M:ue.QrCode.Ecc.MEDIUM,Q:ue.QrCode.Ecc.QUARTILE,H:ue.QrCode.Ecc.HIGH},bt=128,wt="L",yt="#FFFFFF",_t="#000000",Ct=!1,kt=1,vs=4,bs=0,ws=.1;function jt(s,l=0){const o=[];return s.forEach(function(m,g){let f=null;m.forEach(function(j,b){if(!j&&f!==null){o.push(`M${f+l} ${g+l}h${b-f}v1H${f+l}z`),f=null;return}if(b===m.length-1){if(!j)return;f===null?o.push(`M${b+l},${g+l} h1v1H${b+l}z`):o.push(`M${f+l},${g+l} h${b+1-f}v1H${f+l}z`);return}j&&f===null&&(f=b)})}),o.join("")}function Nt(s,l){return s.slice().map((o,m)=>m<l.y||m>=l.y+l.h?o:o.map((g,f)=>f<l.x||f>=l.x+l.w?g:!1))}function ys(s,l,o,m){if(m==null)return null;const g=s.length+o*2,f=Math.floor(l*ws),j=g/l,b=(m.width||f)*j,e=(m.height||f)*j,a=m.x==null?s.length/2-b/2:m.x*j,n=m.y==null?s.length/2-e/2:m.y*j,i=m.opacity==null?1:m.opacity;let c=null;if(m.excavate){let u=Math.floor(a),v=Math.floor(n),_=Math.ceil(b+a-u),p=Math.ceil(e+n-v);c={x:u,y:v,w:_,h:p}}const h=m.crossOrigin;return{x:a,y:n,h:e,w:b,excavation:c,opacity:i,crossOrigin:h}}function _s(s,l){return l!=null?Math.max(Math.floor(l),0):s?vs:bs}function Et({value:s,level:l,minVersion:o,includeMargin:m,marginSize:g,imageSettings:f,size:j,boostLevel:b}){let e=D.useMemo(()=>{const u=(Array.isArray(s)?s:[s]).reduce((v,_)=>(v.push(...ue.QrSegment.makeSegments(_)),v),[]);return ue.QrCode.encodeSegments(u,xs[l],o,void 0,void 0,b)},[s,l,o,b]);const{cells:a,margin:n,numCells:i,calculatedImageSettings:c}=D.useMemo(()=>{let h=e.getModules();const u=_s(m,g),v=h.length+u*2,_=ys(h,j,u,f);return{cells:h,margin:u,numCells:v,calculatedImageSettings:_}},[e,j,f,m,g]);return{qrcode:e,margin:n,cells:a,numCells:i,calculatedImageSettings:c}}var Cs=(function(){try{new Path2D().addPath(new Path2D)}catch{return!1}return!0})(),ks=D.forwardRef(function(l,o){const m=l,{value:g,size:f=bt,level:j=wt,bgColor:b=yt,fgColor:e=_t,includeMargin:a=Ct,minVersion:n=kt,boostLevel:i,marginSize:c,imageSettings:h}=m,v=Ie(m,["value","size","level","bgColor","fgColor","includeMargin","minVersion","boostLevel","marginSize","imageSettings"]),{style:_}=v,p=Ie(v,["style"]),P=h==null?void 0:h.src,w=D.useRef(null),A=D.useRef(null),$=D.useCallback(V=>{w.current=V,typeof o=="function"?o(V):o&&(o.current=V)},[o]),[W,C]=D.useState(!1),{margin:Q,cells:ie,numCells:q,calculatedImageSettings:G}=Et({value:g,level:j,minVersion:n,boostLevel:i,includeMargin:a,marginSize:c,imageSettings:h,size:f});D.useEffect(()=>{if(w.current!=null){const V=w.current,H=V.getContext("2d");if(!H)return;let M=ie;const J=A.current,te=G!=null&&J!==null&&J.complete&&J.naturalHeight!==0&&J.naturalWidth!==0;te&&G.excavation!=null&&(M=Nt(ie,G.excavation));const he=window.devicePixelRatio||1;V.height=V.width=f*he;const fe=f/q*he;H.scale(fe,fe),H.fillStyle=b,H.fillRect(0,0,q,q),H.fillStyle=e,Cs?H.fill(new Path2D(jt(M,Q))):ie.forEach(function(se,K){se.forEach(function(y,ce){y&&H.fillRect(ce+Q,K+Q,1,1)})}),G&&(H.globalAlpha=G.opacity),te&&H.drawImage(J,G.x+Q,G.y+Q,G.w,G.h)}}),D.useEffect(()=>{C(!1)},[P]);const pe=Re({height:f,width:f},_);let le=null;return P!=null&&(le=D.createElement("img",{src:P,key:P,style:{display:"none"},onLoad:()=>{C(!0)},ref:A,crossOrigin:G==null?void 0:G.crossOrigin})),D.createElement(D.Fragment,null,D.createElement("canvas",Re({style:pe,height:f,width:f,ref:$,role:"img"},p)),le)});ks.displayName="QRCodeCanvas";var Le=D.forwardRef(function(l,o){const m=l,{value:g,size:f=bt,level:j=wt,bgColor:b=yt,fgColor:e=_t,includeMargin:a=Ct,minVersion:n=kt,boostLevel:i,title:c,marginSize:h,imageSettings:u}=m,v=Ie(m,["value","size","level","bgColor","fgColor","includeMargin","minVersion","boostLevel","title","marginSize","imageSettings"]),{margin:_,cells:p,numCells:P,calculatedImageSettings:w}=Et({value:g,level:j,minVersion:n,boostLevel:i,includeMargin:a,marginSize:h,imageSettings:u,size:f});let A=p,$=null;u!=null&&w!=null&&(w.excavation!=null&&(A=Nt(p,w.excavation)),$=D.createElement("image",{href:u.src,height:w.h,width:w.w,x:w.x+_,y:w.y+_,preserveAspectRatio:"none",opacity:w.opacity,crossOrigin:w.crossOrigin}));const W=jt(A,_);return D.createElement("svg",Re({height:f,width:f,viewBox:`0 0 ${P} ${P}`,ref:o,role:"img"},v),!!c&&D.createElement("title",null,c),D.createElement("path",{fill:b,d:`M0,0 h${P}v${P}H0z`,shapeRendering:"crispEdges"}),D.createElement("path",{fill:e,d:W,shapeRendering:"crispEdges"}),$)});Le.displayName="QRCodeSVG";const ee="__custom__",Ee=["weixin","lark"],Fe=[{id:"openai",label:"OpenAI",name:"openai",base_url:"https://api.openai.com/v1",model:"gpt-4.1-mini"},{id:"openrouter",label:"OpenRouter",name:"openrouter",base_url:"https://openrouter.ai/api/v1",model:"openai/gpt-4.1-mini"},{id:"anthropic",label:"Anthropic",name:"anthropic",base_url:"https://api.anthropic.com/v1",model:"claude-3-5-haiku-latest"},{id:"deepseek",label:"DeepSeek",name:"deepseek",base_url:"https://api.deepseek.com",model:"deepseek-v4-flash"},{id:"minimax",label:"Minimax",name:"minimax",base_url:"https://api.minimax.chat/v1",model:"MiniMax-M2.5"},{id:"ollama",label:"Ollama",name:"ollama",base_url:"http://127.0.0.1:11434/v1",model:"qwen2.5-coder:7b"}],z={runtime_image_id:De("pi").id,server_url:"http://127.0.0.1:8080",image:"agentdock/pi-acp:local",api_key_env:"OPEN_SANDBOX_API_KEY",acp_port:"8080",state_scope:"project",timeout_seconds:"7200",sandbox_lifecycle:"per_thread",idle_seconds:"900",warm_pool_size:"0",cpu:"1000m",memory:"2Gi",workspace_mount_path:"/workspace",state_mount_path:"/agent-state"};function U(s){return JSON.parse(JSON.stringify(s))}function me(s){return Array.isArray(s.projects)||(s.projects=[]),s.projects}function js(s){const l=new Set(s.map(m=>m.name).filter(Boolean));let o=s.length+1;for(;l.has(`project-${o}`);)o+=1;return{name:`project-${o}`,agentType:ls,workDir:"",model:""}}function ge(s){var l,o,m,g;return{...s,agent:{...s.agent,options:{...((l=s.agent)==null?void 0:l.options)||{},model:pt((o=s.agent)==null?void 0:o.type,String(((g=(m=s.agent)==null?void 0:m.options)==null?void 0:g.model)||""))}},platforms:s.platforms||[]}}function ye(s){return{id:s.id,name:s.name,api_key:s.api_key||"",base_url:s.base_url||"",model:s.model||"",models:s.models||[],thinking:s.thinking||"",env:s.env||{}}}function St(s,l){return l.includes(s)?s:ee}function Ns(s){var l;return((l=Fe.find(o=>s.name===o.name||o.base_url&&s.base_url===o.base_url||o.model&&s.model===o.model&&s.name===o.name))==null?void 0:l.id)||ee}function Es(s,l){const o=Fe.find(m=>m.id===l);return o?{...s,name:o.name,base_url:o.base_url,model:o.model}:s}function Se(s="weixin"){var l;return{type:s,options:{instance_id:`${s}-${((l=crypto.randomUUID)==null?void 0:l.call(crypto))||Date.now().toString(36)}`}}}function re(s){var l;return String(((l=s==null?void 0:s.options)==null?void 0:l.instance_id)||"").trim()||"default"}function be(s){const l=s.type==="feishu"?"lark":s.type,o=s.options&&typeof s.options=="object"?{...s.options}:{};return l==="weixin"?{type:l,options:{...o,instance_id:String(o.instance_id||"").trim()}}:l==="lark"?{type:l,options:{...o,instance_id:String(o.instance_id||"").trim(),app_id:String(o.app_id||"").trim(),app_secret:String(o.app_secret||"").trim(),card_actions:o.card_actions===!0}}:{type:l,options:o}}function Ss(s){var l;if(s.type==="weixin")return"WeChat QR login";if(s.type==="lark"){const o=String(((l=s.options)==null?void 0:l.app_id)||"").trim();return o?`App ID ${o}`:"App ID and secret required"}return"Custom platform"}function Pt(s){var m,g;const l=String(((g=(m=s.agent)==null?void 0:m.options)==null?void 0:g.work_dir)||"").trim();return l?l.replace(/\/+$/,"").split("/").filter(Boolean).pop()||l:"No work directory"}function Ps(s){return s==="success"?"border-primary/20 bg-primary/10 text-primary dark:border-primary/25 dark:bg-primary/10 dark:text-blue-200":s==="warning"?"border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-400/20 dark:bg-amber-500/10 dark:text-amber-200":"border-red-200 bg-red-50 text-red-700 dark:border-red-400/20 dark:bg-red-500/10 dark:text-red-200"}function ht(s){return{enabled:!!(s!=null&&s.enabled),provider_id:(s==null?void 0:s.provider_id)||ze,runtime_image_id:(s==null?void 0:s.runtime_image_id)||z.runtime_image_id,server_url:(s==null?void 0:s.server_url)||z.server_url,image:(s==null?void 0:s.image)||z.image,api_key_env:(s==null?void 0:s.api_key_env)||z.api_key_env,acp_port:String((s==null?void 0:s.acp_port)||z.acp_port),state_scope:(s==null?void 0:s.state_scope)||z.state_scope,timeout_seconds:String((s==null?void 0:s.timeout_seconds)||z.timeout_seconds),sandbox_lifecycle:(s==null?void 0:s.sandbox_lifecycle)||z.sandbox_lifecycle,idle_seconds:String((s==null?void 0:s.idle_seconds)||z.idle_seconds),warm_pool_size:String((s==null?void 0:s.warm_pool_size)??z.warm_pool_size),cpu:(s==null?void 0:s.cpu)||z.cpu,memory:(s==null?void 0:s.memory)||z.memory,workspace_mount_path:(s==null?void 0:s.workspace_mount_path)||z.workspace_mount_path,state_mount_path:(s==null?void 0:s.state_mount_path)||z.state_mount_path}}function Ms(s){return{enabled:s.enabled,provider_id:s.provider_id.trim()||ze,runtime_image_id:s.runtime_image_id.trim()||z.runtime_image_id,state_scope:s.state_scope,timeout_seconds:Number(s.timeout_seconds)||Number(z.timeout_seconds),sandbox_lifecycle:s.sandbox_lifecycle,idle_seconds:Number(s.idle_seconds)||Number(z.idle_seconds),warm_pool_size:Math.max(0,Number(s.warm_pool_size)||0),cpu:s.cpu.trim()||z.cpu,memory:s.memory.trim()||z.memory}}function As({projects:s,selectedIndex:l,onAddProject:o,onSelectProject:m,onRemoveProject:g}){return t.jsx(gt,{title:"项目",actions:t.jsxs(T,{size:"sm",onClick:o,children:[t.jsx(Ce,{size:14})," 新建项目"]}),className:"app-panel lg:self-start",children:s.length===0?t.jsx(Oe,{message:"还没有项目。"}):t.jsx("div",{className:"space-y-2",children:s.map((f,j)=>{var b,e;return t.jsxs("div",{className:`flex items-center justify-between gap-2 ${j===l?"app-list-row app-list-row-active":"app-list-row"}`,children:[t.jsxs("button",{type:"button",onClick:()=>m(j,f),className:"min-w-0 flex-1 text-left",children:[t.jsx("p",{className:"truncate text-sm font-medium text-slate-950 dark:text-white",children:f.name||`Project ${j+1}`}),t.jsxs("p",{className:"mt-0.5 truncate text-xs text-muted-foreground",children:[((b=f.agent)==null?void 0:b.type)||"unknown"," · ",Pt(f)," · ",((e=f.platforms)==null?void 0:e.length)||0," platforms"]})]}),t.jsx(T,{variant:"ghost",size:"sm",className:"app-icon-button shrink-0",onClick:()=>g(j,f),"aria-label":`Remove ${f.name}`,children:t.jsx(Te,{size:14})})]},`${f.name}-${j}`)})})})}function Rs({project:s,sandbox:l}){var o,m;return t.jsxs("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-4",children:[t.jsxs("div",{className:"app-surface p-4",children:[t.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[t.jsx(ms,{size:14})," Agent"]}),t.jsx("p",{className:"mt-2 truncate text-sm font-semibold text-foreground",children:((o=s.agent)==null?void 0:o.type)||"unknown"})]}),t.jsxs("div",{className:"app-surface p-4",children:[t.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[t.jsx(Wt,{size:14})," Workspace"]}),t.jsx("p",{className:"mt-2 truncate text-sm font-semibold text-foreground",children:Pt(s)})]}),t.jsxs("div",{className:"app-surface p-4",children:[t.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[t.jsx(us,{size:14})," Platforms"]}),t.jsxs("p",{className:"mt-2 truncate text-sm font-semibold text-foreground",children:[((m=s.platforms)==null?void 0:m.length)||0," configured"]})]}),t.jsxs("div",{className:"app-surface p-4",children:[t.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[t.jsx(fs,{size:14})," Sandbox"]}),t.jsx("p",{className:"mt-2 truncate text-sm font-semibold text-foreground",children:l.enabled?"Cloud enabled":"Local runtime"})]})]})}function Is({project:s,updateProject:l}){var o,m,g,f,j,b;return t.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2",children:[t.jsx(L,{label:"Project name",value:s.name,onChange:e=>l(a=>({...a,name:e.target.value}))}),t.jsxs(Z,{label:"Agent type",value:St(((o=s.agent)==null?void 0:o.type)||"",Me),onChange:e=>l(a=>{var i;const n=e.target.value===ee?a.agent.type:e.target.value;return{...a,agent:{...a.agent,type:n,options:{...a.agent.options||{},model:pt(n,String(((i=a.agent.options)==null?void 0:i.model)||""))}}}}),children:[Me.map(e=>t.jsx("option",{value:e,children:e},e)),t.jsx("option",{value:ee,children:"custom"})]}),t.jsx(L,{label:"Host workspace path",value:String(((g=(m=s.agent)==null?void 0:m.options)==null?void 0:g.work_dir)||""),onChange:e=>l(a=>({...a,agent:{...a.agent,options:{...a.agent.options||{},work_dir:e.target.value}}}))}),t.jsx(L,{label:"Default model",value:String(((j=(f=s.agent)==null?void 0:f.options)==null?void 0:j.model)||""),onChange:e=>l(a=>({...a,agent:{...a.agent,options:{...a.agent.options||{},model:e.target.value}}})),placeholder:Ae((b=s.agent)==null?void 0:b.type)||"Use agent default model"})]})}function Ls({project:s,modelProviders:l,providerDrafts:o,updateProject:m,updateProviderDraft:g,onAddProvider:f,onSaveProvider:j,onDeleteProvider:b}){var e,a,n,i;return t.jsxs("section",{className:"space-y-3",children:[t.jsxs("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2",children:[t.jsxs(Z,{label:"Project provider",value:String(((a=(e=s.agent)==null?void 0:e.options)==null?void 0:a.provider_id)||""),onChange:c=>m(h=>({...h,agent:{...h.agent,options:{...h.agent.options||{},provider_id:c.target.value}}})),children:[t.jsx("option",{value:"",children:"No provider"}),l.map(c=>t.jsx("option",{value:c.id,children:c.name},c.id))]}),t.jsx(L,{label:"Model override",value:String(((i=(n=s.agent)==null?void 0:n.options)==null?void 0:i.model)||""),onChange:c=>m(h=>({...h,agent:{...h.agent,options:{...h.agent.options||{},model:c.target.value}}})),placeholder:"Use provider default model"})]}),t.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-semibold text-slate-950 dark:text-white",children:"Shared providers"}),t.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Providers are shared and selected by projects."})]}),t.jsxs(T,{size:"sm",variant:"secondary",onClick:f,children:[t.jsx(Ce,{size:14})," Add provider"]})]}),l.length===0?t.jsx("div",{className:"rounded-xl border border-black/10 px-4 py-4 text-sm text-muted-foreground dark:border-white/[0.08]",children:"No shared providers configured."}):t.jsx("div",{className:"space-y-3",children:l.map(c=>{const h=o[c.id]||ye(c);return t.jsx("div",{className:"app-surface p-4",children:t.jsxs("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2",children:[t.jsxs(Z,{label:"Preset",value:Ns(h),onChange:u=>{u.target.value!==ee&&g(c.id,v=>Es(v,u.target.value))},children:[Fe.map(u=>t.jsx("option",{value:u.id,children:u.label},u.id)),t.jsx("option",{value:ee,children:"custom"})]}),t.jsx(L,{label:"Name",value:h.name||"",onChange:u=>g(c.id,v=>({...v,name:u.target.value}))}),t.jsx(L,{label:"API key",type:"password",value:h.api_key||"",onChange:u=>g(c.id,v=>({...v,api_key:u.target.value}))}),t.jsx(L,{label:"Base URL",value:h.base_url||"",onChange:u=>g(c.id,v=>({...v,base_url:u.target.value}))}),t.jsx(L,{label:"Default model",value:h.model||"",onChange:u=>g(c.id,v=>({...v,model:u.target.value}))}),t.jsxs("div",{className:"flex items-end gap-2",children:[t.jsxs(T,{variant:"secondary",size:"sm",onClick:()=>j(c.id),children:[t.jsx(we,{size:14})," Save"]}),t.jsxs(T,{variant:"danger",size:"sm",onClick:()=>b(c.id),children:[t.jsx(Te,{size:14})," Remove"]})]})]})},c.id)})})]})}function Os({project:s,updateProject:l,onOpenPlatformDialog:o}){return t.jsxs("section",{className:"space-y-3",children:[t.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-semibold text-slate-950 dark:text-white",children:"Platforms"}),t.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Configure each platform with its own required connection fields."})]}),t.jsxs(T,{size:"sm",variant:"secondary",onClick:()=>o(null),children:[t.jsx(Ce,{size:14})," Platform"]})]}),(s.platforms||[]).length===0?t.jsx(Oe,{message:"No platforms configured."}):t.jsx("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2",children:(s.platforms||[]).map((m,g)=>t.jsxs("div",{className:"app-list-row flex items-center justify-between gap-3",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"truncate text-sm font-medium text-slate-950 dark:text-white",children:m.type}),t.jsx("p",{className:"mt-1 truncate text-xs text-muted-foreground",children:Ss(m)})]}),t.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[t.jsx(T,{variant:"secondary",size:"sm",className:"app-icon-button",onClick:()=>o(g),"aria-label":`Configure ${m.type}`,children:t.jsx(Kt,{size:14})}),t.jsx(T,{variant:"danger",size:"sm",className:"app-icon-button",onClick:()=>l(f=>{const j=[...f.platforms||[]];return j.splice(g,1),{...f,platforms:j}}),children:t.jsx(Te,{size:14})})]})]},`${m.type}-${g}`))})]})}function zs({project:s,sandbox:l,profile:o,sandboxProvider:m,runtimeImage:g,updateSandbox:f,updateDeploymentProfile:j}){return t.jsxs("section",{className:"space-y-4",children:[t.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[t.jsxs("div",{children:[t.jsx("h3",{className:"text-sm font-semibold text-slate-950 dark:text-white",children:"云端模式"}),t.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"通过 OpenSandbox 为 Agent 运行启动独立容器。"})]}),t.jsx(Pe,{tone:l.enabled?"success":"neutral",children:l.enabled?"Enabled":"Local"})]}),t.jsxs("label",{className:"app-toolbar flex items-center gap-3 text-sm font-medium text-slate-950 dark:text-white",children:[t.jsx("input",{type:"checkbox",className:"h-4 w-4 rounded border-black/20 dark:border-white/20",checked:l.enabled,onChange:b=>f(e=>{var a;return{...e,enabled:b.target.checked,provider_id:e.provider_id||ze,runtime_image_id:e.runtime_image_id||De(((a=s==null?void 0:s.agent)==null?void 0:a.type)||"pi").id}})}),"启用云端模式(Sandbox)"]}),l.enabled?t.jsxs("div",{className:"space-y-4",children:[t.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2",children:[t.jsx(Z,{label:"Deployment",value:o.id,onChange:b=>j(b.target.value),children:cs.map(b=>t.jsx("option",{value:b.id,children:b.label},b.id))}),t.jsxs(Z,{label:"State scope",value:l.state_scope,onChange:b=>f(e=>({...e,state_scope:b.target.value})),children:[t.jsx("option",{value:"user",children:"User"}),t.jsx("option",{value:"project",children:"Project"}),t.jsx("option",{value:"thread",children:"Thread"}),t.jsx("option",{value:"run",children:"Run"})]}),t.jsx(L,{label:"CPU",value:l.cpu,onChange:b=>f(e=>({...e,cpu:b.target.value}))}),t.jsx(L,{label:"Memory",value:l.memory,onChange:b=>f(e=>({...e,memory:b.target.value}))}),t.jsx(L,{label:"Timeout seconds",type:"number",value:l.timeout_seconds,onChange:b=>f(e=>({...e,timeout_seconds:b.target.value}))}),t.jsxs(Z,{label:"Sandbox lifecycle",value:l.sandbox_lifecycle,onChange:b=>f(e=>({...e,sandbox_lifecycle:b.target.value})),children:[t.jsx("option",{value:"per_thread",children:"Keep warm per thread"}),t.jsx("option",{value:"per_run",children:"Close after each run"})]}),t.jsx(L,{label:"Idle seconds",type:"number",value:l.idle_seconds,onChange:b=>f(e=>({...e,idle_seconds:b.target.value}))}),t.jsx(L,{label:"Warm pool",type:"number",value:l.warm_pool_size,onChange:b=>f(e=>({...e,warm_pool_size:b.target.value}))})]}),t.jsxs("div",{className:"rounded-xl border border-black/10 px-4 py-3 text-sm text-muted-foreground dark:border-white/[0.08]",children:[t.jsx("div",{className:"font-medium text-slate-950 dark:text-white",children:"当前运行配置"}),t.jsxs("div",{className:"mt-2 grid grid-cols-1 gap-2 md:grid-cols-2",children:[t.jsxs("div",{children:["OpenSandbox: ",m.server_url||"not configured"]}),t.jsxs("div",{children:["Image: ",g.image]}),t.jsxs("div",{children:["ACP port: ",g.acp_port]}),t.jsxs("div",{children:["Sandbox workspace path: ",g.workspace_mount_path||o.workspaceMountPath]}),t.jsxs("div",{children:["State mount: ",g.state_mount_path||o.stateMountPath]}),t.jsxs("div",{children:["API key env: ",m.api_key_env||"OPEN_SANDBOX_API_KEY"]})]})]}),t.jsxs("details",{className:"rounded-xl border border-black/10 px-4 py-3 text-sm dark:border-white/[0.08]",children:[t.jsx("summary",{className:"cursor-pointer font-medium text-slate-950 dark:text-white",children:"Advanced"}),t.jsx("div",{className:"mt-3 text-muted-foreground",children:"Host workspace path 是 OpenSandbox 挂载源;Sandbox workspace path 是 Agent 容器内的工作目录。Core 只启动代理进程,不直接使用 host workspace path 作为代理工作目录。"})]})]}):t.jsx("div",{className:"rounded-xl border border-black/10 px-4 py-3 text-sm text-muted-foreground dark:border-white/[0.08]",children:"当前项目会继续使用本地 Agent runtime。"})]})}function Zs(){var He,Ye,Ve,We,Ke,Xe,qe,Je,Ze,et,tt,st;const[s,l]=Xt(),o=s.get("project")||"",[m,g]=S.useState(null),[f,j]=S.useState(null),[b,e]=S.useState([]),[a,n]=S.useState({}),[i,c]=S.useState(0),[h,u]=S.useState("basic"),[v,_]=S.useState(null),[p,P]=S.useState(null),[w,A]=S.useState(null),[$,W]=S.useState(!1),[C,Q]=S.useState(null),[ie,q]=S.useState(!1),[G,pe]=S.useState(!0),[le,V]=S.useState(""),[H,M]=S.useState(null),J=S.useRef(null),te=S.useRef(null),he=S.useRef(i),fe=S.useRef(""),se=S.useCallback(async(r="")=>{pe(!0);try{const[d,x]=await Promise.all([Jt(),Zt()]),k=U(d.config||{});if(k.projects=me(k).map(E=>ge(E)),g(k),j(U(k)),e(x.providers||[]),n(Object.fromEntries((x.providers||[]).map(E=>[E.id,ye(E)]))),r){const E=(k.projects||[]).findIndex(O=>O.name===r);c(E>=0?E:0)}}catch(d){M({tone:"error",message:d instanceof Error?d.message:String(d)})}finally{pe(!1)}},[]);S.useEffect(()=>{se(o)},[se]);const K=(m==null?void 0:m.projects)||[],y=K[i]||null,ce=ht((Ye=(He=y==null?void 0:y.agent)==null?void 0:He.options)==null?void 0:Ye.sandbox),Be=ct(String((m==null?void 0:m.deployment_profile)||"").trim()),Mt=((m==null?void 0:m.sandbox_providers)||[]).find(r=>r.id===ce.provider_id)||dt(Be.id),At=((m==null?void 0:m.sandbox_runtime_images)||[]).find(r=>r.id===ce.runtime_image_id)||De(((Ve=y==null?void 0:y.agent)==null?void 0:Ve.type)||"pi"),Ue=JSON.stringify(m||{})!==JSON.stringify(f||{});S.useEffect(()=>{J.current=m},[m]),S.useEffect(()=>{te.current=p},[p]),S.useEffect(()=>{he.current=i,fe.current=(y==null?void 0:y.name)||""},[i,y==null?void 0:y.name]),S.useEffect(()=>{if(!m||!o)return;const r=K.findIndex(d=>d.name===o);r>=0&&r!==i&&c(r)},[m,K,o,i]);const de=S.useCallback(r=>{g(d=>{if(!d)return d;const x=U(d),k=me(x),E=k[i];return E?(k[i]=ge(r(E)),x):d})},[i]),Rt=S.useCallback(r=>{de(d=>{var x;return{...d,agent:{...d.agent,options:{...d.agent.options||{},sandbox:Ms(r(ht((x=d.agent.options)==null?void 0:x.sandbox)))}}}})},[de]),It=S.useCallback(r=>{const d=ct(r);g(x=>{if(!x)return x;const k=U(x);k.deployment_profile=d.id;const E=dt(d.id),O=Array.isArray(k.sandbox_providers)?[...k.sandbox_providers]:[],B=O.findIndex(F=>F.id===E.id);return B>=0?O[B]={...O[B],server_url:E.server_url}:O.push(E),k.sandbox_providers=O,k})},[]),Lt=()=>{_(js(K))},Ot=S.useCallback((r,d)=>{n(x=>{const k=x[r];return k?{...x,[r]:d(k)}:x})},[]),zt=async()=>{try{const r=await ss({name:`provider-${b.length+1}`});e(d=>[...d,r].sort((x,k)=>x.name.localeCompare(k.name))),n(d=>({...d,[r.id]:ye(r)})),M({tone:"success",message:"Provider created."})}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}},Dt=async r=>{const d=a[r];if(d)try{const x=await as(r,d);e(k=>k.map(E=>E.id===x.id?x:E).sort((E,O)=>E.name.localeCompare(O.name))),n(k=>({...k,[x.id]:ye(x)})),M({tone:"success",message:"Provider saved."})}catch(x){M({tone:"error",message:x instanceof Error?x.message:String(x)})}},Tt=async r=>{try{await ns(r),e(d=>d.filter(x=>x.id!==r)),n(d=>{const x={...d};return delete x[r],x}),M({tone:"success",message:"Provider removed."})}catch(d){M({tone:"error",message:d instanceof Error?d.message:String(d)})}},xe=r=>{_(d=>d&&{...d,...r})},Ft=()=>{if(!v)return;const r=v.name.trim(),d=v.agentType.trim(),x=v.workDir.trim(),k=v.model.trim();if(!r||!d||!x){M({tone:"warning",message:"Project name, agent type, and work directory are required."});return}if(K.some(B=>B.name===r)){M({tone:"warning",message:`Project "${r}" already exists.`});return}const E=ge({name:r,agent:{type:d,options:{model:k||Ae(d),work_dir:x},providers:[]},platforms:[],admin_from:"",disabled_commands:[]}),O=K.length;g(B=>{const F=U(B||{});return me(F).push(E),F}),c(O),l({project:r}),_(null),M(null)},Bt=r=>{g(d=>{if(!d)return d;const x=U(d),k=me(x);return k.splice(r,1),c(Math.max(0,Math.min(r,k.length-1))),x})},Ut=r=>{var x;if(A(null),Q(null),r===null){P({index:r,draft:Se()});return}const d=(x=y==null?void 0:y.platforms)==null?void 0:x[r];d&&P({index:r,draft:U(d)})},ae=r=>{P(d=>d&&{...d,draft:r(d.draft)})},$t=()=>{if(!p)return;const r=be(p.draft);de(d=>{const x=[...d.platforms||[]];return p.index===null?x.push(r):x[p.index]=r,{...d,platforms:x}}),P(null),A(null),Q(null)},$e=async()=>{if(!p||!m)return p==null?void 0:p.draft;const r=U(m),d=me(r),x=d[i];if(!x)return p.draft;const k=[...x.platforms||[]],E=be(p.draft);p.index===null?k.push(E):k[p.index]=E,d[i]=ge({...x,platforms:k});const O=await Ne(r),B=U(O.config||r);return j(B),g(U(B)),P(F=>F&&{index:F.index??k.length-1,draft:E}),E},Qt=async()=>{if(!(!(y!=null&&y.name)||!m)){W(!0);try{await $e();const r=await rs(y.name,re(p==null?void 0:p.draft));A({...r,status:"wait",createdAt:Date.now()}),M(null)}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}finally{W(!1)}}},Gt=async()=>{if(!(!(y!=null&&y.name)||!m)){q(!0);try{await $e();const r=await os(y.name,re(p==null?void 0:p.draft));Q({...r,status:"wait",createdAt:Date.now()}),M(null)}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}finally{q(!1)}}},Ht=async()=>{if(!(!(y!=null&&y.name)||!(w!=null&&w.ticket))){W(!0);try{const r=await is(y.name,w.ticket,re(p==null?void 0:p.draft));A(d=>d&&{...d,status:r.status}),r.status==="confirmed"&&M({tone:"success",message:"WeChat QR code confirmed."})}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}finally{W(!1)}}},Qe=S.useCallback(async(r,d)=>{const x=await es(r,d);if(x.status!=="running"||x.connected!==!0)throw new Error(x.lastError||"Lark bot credentials were saved, but the gateway is not connected yet.");const k=await ts(r,d);if(!k.success)throw new Error(k.error||"Lark bot credentials were saved, but the connection test failed.")},[]),ke=S.useCallback(async r=>{var nt,rt,ot;const d=fe.current,x=re((nt=te.current)==null?void 0:nt.draft),k=J.current;if(!k)return;const E=U(k),O=me(E),B=he.current,F=O[B];if(!F)return;const R=[...F.platforms||[]],Y=te.current,X=(Y==null?void 0:Y.index)??R.findIndex(ne=>be(ne).type==="lark"&&re(ne)===x),ve=X>=0?R[X]:(Y==null?void 0:Y.draft)||Se("lark"),je=be({...ve,type:"lark",options:{...ve.options||{},instance_id:x,app_id:r.appId,app_secret:r.appSecret,verification_token:r.verificationToken||((rt=ve.options)==null?void 0:rt.verification_token)||"",encrypt_key:r.encryptKey||((ot=ve.options)==null?void 0:ot.encrypt_key)||"",card_actions:!0,subscribed_events:"im.message.receive_v1 card.action.trigger",subscribed_callbacks:"card.action.trigger"}});X>=0?R[X]=je:R.push(je),O[B]=ge({...F,platforms:R});const Vt=await Ne(E),at=U(Vt.config||E);j(at),g(U(at)),P(ne=>ne&&{...ne,index:ne.index??(X>=0?X:R.length-1),draft:je}),await Qe(d,x),M({tone:"success",message:"Lark bot bound, saved, and ready to send messages."}),await se(d)},[Qe,se]),Yt=async()=>{if(!(!(y!=null&&y.name)||!(C!=null&&C.ticket)||!m)){q(!0);try{const r=await lt(y.name,C.ticket,re(p==null?void 0:p.draft));Q(d=>{var x;return d&&{...d,status:r.status,botName:(x=r.credentials)==null?void 0:x.botName}}),r.status==="confirmed"&&r.credentials?await ke(r.credentials):r.status==="expired"&&M({tone:"warning",message:"Lark QR code expired. Generate a new QR code and scan again."})}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}finally{q(!1)}}};S.useEffect(()=>{if(!(y!=null&&y.name)||!(C!=null&&C.ticket)||(p==null?void 0:p.draft.type)!=="lark"||C.status&&!["wait","signed"].includes(C.status))return;let r=!1,d;const k=(C.createdAt||Date.now())+Math.max(C.expiresIn||0,1)*1e3,E=Math.max(3,Math.min(Number(C.interval||5)||5,15))*1e3,O=F=>{d=window.setTimeout(()=>{B()},F)},B=async()=>{var F;if(!r){if(Date.now()>=k){Q(R=>(R==null?void 0:R.ticket)===C.ticket?{...R,status:"expired"}:R),M({tone:"warning",message:"Lark QR code expired. Generate a new QR code and scan again."});return}try{const R=await lt(y.name,C.ticket,re((F=te.current)==null?void 0:F.draft));if(r)return;if(Q(Y=>{var X;return(Y==null?void 0:Y.ticket)===C.ticket?{...Y,status:R.status,botName:(X=R.credentials)==null?void 0:X.botName}:Y}),R.status==="confirmed"&&R.credentials){await ke(R.credentials);return}if(R.status==="expired"){M({tone:"warning",message:"Lark QR code expired. Generate a new QR code and scan again."});return}O(E)}catch(R){if(r)return;M({tone:"error",message:R instanceof Error?R.message:String(R)})}}};return O(Math.min(2e3,E)),()=>{r=!0,d&&window.clearTimeout(d)}},[C==null?void 0:C.createdAt,C==null?void 0:C.expiresIn,C==null?void 0:C.interval,C==null?void 0:C.status,C==null?void 0:C.ticket,p==null?void 0:p.draft.type,ke,y==null?void 0:y.name]);const Ge=async()=>{if(m){V("config");try{const r=await Ne(m);j(U(r.config||m)),g(U(r.config||m)),M({tone:"success",message:"Project changes saved."}),await se()}catch(r){M({tone:"error",message:r instanceof Error?r.message:String(r)})}finally{V("")}}};return G&&!m?t.jsx("div",{className:"flex h-64 items-center justify-center text-sm text-slate-400 animate-pulse",children:"Loading workspace..."}):t.jsxs("div",{className:"space-y-6 animate-fade-in",children:[t.jsx(qt,{title:"工作区",description:"创建项目,配置 Agent、工作目录、Provider 和平台接入。"}),H?t.jsx("div",{role:"status",className:`rounded-xl border px-4 py-3 text-sm ${Ps(H.tone)}`,children:H.message}):null,Ue?t.jsxs("div",{className:"app-toolbar flex flex-col gap-3 border-amber-200 bg-amber-50 text-sm text-amber-700 dark:border-amber-400/20 dark:bg-amber-500/10 dark:text-amber-200 sm:flex-row sm:items-center sm:justify-between",children:[t.jsx("span",{children:"You have unsaved project changes."}),t.jsxs(T,{size:"sm",onClick:()=>void Ge(),loading:le==="config",children:[t.jsx(we,{size:14})," Save changes"]})]}):null,t.jsxs("div",{className:"grid min-w-0 grid-cols-1 gap-4 lg:grid-cols-[340px_minmax(0,1fr)]",children:[t.jsx(As,{projects:K,selectedIndex:i,onAddProject:Lt,onSelectProject:(r,d)=>{c(r),l(d.name?{project:d.name}:{})},onRemoveProject:r=>Bt(r)}),t.jsx(gt,{title:(y==null?void 0:y.name)||"Project details",description:y?t.jsxs("span",{className:"break-all",children:[((We=y.agent)==null?void 0:We.type)||"unknown"," · ",String(((Xe=(Ke=y.agent)==null?void 0:Ke.options)==null?void 0:Xe.work_dir)||"No work directory")]}):void 0,className:"app-panel",children:y?t.jsxs("div",{className:"space-y-6",children:[t.jsx(Rs,{project:y,sandbox:ce}),t.jsx("div",{className:"flex gap-2 overflow-x-auto border-b border-black/10 pb-4 [scrollbar-width:none] dark:border-white/[0.08] [&::-webkit-scrollbar]:hidden sm:flex-wrap",children:[["basic","基本信息"],["providers","Provider"],["platforms","平台接入"],["sandbox","云端模式"]].map(([r,d])=>t.jsx("button",{type:"button",onClick:()=>u(r),className:`app-segment ${h===r?"app-segment-active":"app-segment-idle"}`,children:d},r))}),h==="basic"?t.jsx(Is,{project:y,updateProject:de}):null,h==="providers"?t.jsx(Ls,{project:y,modelProviders:b,providerDrafts:a,updateProject:de,updateProviderDraft:Ot,onAddProvider:()=>void zt(),onSaveProvider:r=>void Dt(r),onDeleteProvider:r=>void Tt(r)}):null,h==="platforms"?t.jsx(Os,{project:y,updateProject:de,onOpenPlatformDialog:Ut}):null,h==="sandbox"?t.jsx(zs,{project:y,sandbox:ce,profile:Be,sandboxProvider:Mt,runtimeImage:At,updateSandbox:Rt,updateDeploymentProfile:It}):null,t.jsx("div",{className:"flex flex-wrap gap-2 border-t border-black/10 pt-5 dark:border-white/[0.08]",children:t.jsxs(T,{className:"w-full sm:w-auto",onClick:()=>void Ge(),loading:le==="config",disabled:!Ue&&le!=="config",children:[t.jsx(we,{size:14})," 保存更改"]})})]}):t.jsx(Oe,{message:"选择或新建项目后开始配置。"})})]}),t.jsx(it,{open:!!v,onClose:()=>_(null),title:"新建项目",children:v?t.jsxs("div",{className:"space-y-4",children:[t.jsx(L,{label:"Project name",value:v.name,onChange:r=>xe({name:r.target.value}),autoFocus:!0}),t.jsx(Z,{label:"Agent type",value:v.agentType,onChange:r=>{const d=r.target.value;xe({agentType:d})},children:Me.map(r=>t.jsx("option",{value:r,children:r},r))}),t.jsx(L,{label:"Host workspace path",value:v.workDir,onChange:r=>xe({workDir:r.target.value}),placeholder:"/Users/yinyin/code/my-project"}),t.jsx(L,{label:"Default model",value:v.model,onChange:r=>xe({model:r.target.value}),placeholder:Ae(v.agentType)||"Use agent default model"}),t.jsxs("div",{className:"flex flex-col-reverse gap-2 pt-2 sm:flex-row sm:justify-end",children:[t.jsx(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>_(null),children:"Cancel"}),t.jsxs(T,{className:"w-full sm:w-auto",onClick:Ft,children:[t.jsx(Ce,{size:14})," 新建项目"]})]})]}):null}),t.jsx(it,{open:!!p,onClose:()=>{P(null),A(null),Q(null)},title:(p==null?void 0:p.index)===null?"Add platform":"Configure platform",children:p?t.jsxs("div",{className:"space-y-4",children:[t.jsxs(Z,{label:"Platform",value:St(p.draft.type,[...Ee]),onChange:r=>{const d=r.target.value===ee?p.draft.type:r.target.value;ae(()=>Se(d)),A(null),Q(null)},children:[Ee.map(r=>t.jsx("option",{value:r,children:r},r)),ds.filter(r=>!Ee.includes(r)).map(r=>t.jsx("option",{value:r,children:r},r)),t.jsx("option",{value:ee,children:"custom"})]}),p.draft.type==="lark"?t.jsxs("div",{className:"grid grid-cols-1 gap-3",children:[C!=null&&C.qrCodeUrl?t.jsxs("div",{className:"flex flex-col items-center gap-3 rounded-lg border border-black/10 p-4 dark:border-white/[0.08]",children:[t.jsx("div",{className:"rounded-lg border border-black/10 bg-white p-3",children:t.jsx(Le,{value:C.qrCodeUrl,size:176,includeMargin:!0})}),t.jsx(Pe,{tone:C.status==="confirmed"?"success":C.status==="expired"?"danger":"warning",children:C.botName||C.status||"wait"})]}):null,t.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:flex-wrap",children:[t.jsxs(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>void Gt(),loading:ie,children:[t.jsx(mt,{size:14})," Generate QR"]}),t.jsx(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>void Yt(),loading:ie,disabled:!(C!=null&&C.ticket),children:"Check status"})]}),t.jsx(L,{label:"App ID",value:String(((qe=p.draft.options)==null?void 0:qe.app_id)||""),onChange:r=>ae(d=>({...d,options:{...d.options||{},app_id:r.target.value}})),placeholder:"cli_xxx"}),t.jsx(L,{label:"App Secret",type:"password",value:String(((Je=p.draft.options)==null?void 0:Je.app_secret)||""),onChange:r=>ae(d=>({...d,options:{...d.options||{},app_secret:r.target.value}}))}),t.jsx(L,{label:"Verification token",value:String(((Ze=p.draft.options)==null?void 0:Ze.verification_token)||""),onChange:r=>ae(d=>({...d,options:{...d.options||{},verification_token:r.target.value}}))}),t.jsx(L,{label:"Encrypt key",value:String(((et=p.draft.options)==null?void 0:et.encrypt_key)||""),onChange:r=>ae(d=>({...d,options:{...d.options||{},encrypt_key:r.target.value}}))}),t.jsxs("label",{className:"flex items-center gap-3 text-sm text-foreground",children:[t.jsx("input",{type:"checkbox",checked:((tt=p.draft.options)==null?void 0:tt.auto_approve)===!0,onChange:r=>ae(d=>({...d,options:{...d.options||{},auto_approve:r.target.checked}}))}),"Auto-approve Lark users"]}),t.jsxs("label",{className:"flex items-center gap-3 text-sm text-foreground",children:[t.jsx("input",{type:"checkbox",checked:((st=p.draft.options)==null?void 0:st.card_actions)===!0,onChange:r=>ae(d=>({...d,options:{...d.options||{},card_actions:r.target.checked}}))}),"Enable Lark card action buttons"]})]}):null,p.draft.type==="weixin"?t.jsxs("div",{className:"space-y-3",children:[t.jsx("div",{className:"rounded-lg border border-black/10 bg-black/[0.03] px-3 py-3 text-sm text-muted-foreground dark:border-white/[0.08] dark:bg-white/[0.04]",children:"WeChat does not need an App ID or secret. Save this platform, then generate a QR code and scan it to finish login."}),w!=null&&w.qrCodeUrl?t.jsxs("div",{className:"flex flex-col items-center gap-3 rounded-lg border border-black/10 p-4 dark:border-white/[0.08]",children:[t.jsx("div",{className:"rounded-lg border border-black/10 bg-white p-3",children:t.jsx(Le,{value:w.qrCodeUrl,size:176,includeMargin:!0})}),t.jsx(Pe,{tone:w.status==="confirmed"?"success":w.status==="expired"?"danger":"warning",children:w.status||"wait"})]}):null,t.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:flex-wrap",children:[t.jsxs(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>void Qt(),loading:$,children:[t.jsx(mt,{size:14})," Generate QR"]}),t.jsx(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>void Ht(),loading:$,disabled:!(w!=null&&w.ticket),children:"Check status"})]})]}):null,p.draft.type!=="lark"&&p.draft.type!=="weixin"?t.jsx("div",{className:"rounded-lg border border-black/10 bg-black/[0.03] px-3 py-3 text-sm text-muted-foreground dark:border-white/[0.08] dark:bg-white/[0.04]",children:"This platform has no daily UI fields yet. Existing advanced options are preserved in config."}):null,t.jsxs("div",{className:"flex flex-col-reverse gap-2 border-t border-black/10 pt-4 dark:border-white/[0.08] sm:flex-row sm:justify-end",children:[t.jsx(T,{className:"w-full sm:w-auto",variant:"secondary",onClick:()=>P(null),children:"Cancel"}),t.jsxs(T,{className:"w-full sm:w-auto",onClick:$t,children:[t.jsx(we,{size:14})," Apply"]})]})]}):null})]})}export{Zs as default};
@@ -1 +0,0 @@
1
- import{D as t}from"./index-CDWUe2Sw.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};