@kafca/agentdock 0.1.51 → 0.1.53

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 (71) hide show
  1. package/README.md +4 -0
  2. package/dist/renderer/assets/{Badge-DpYXv6XT.js → Badge-pBiMqECO.js} +1 -1
  3. package/dist/renderer/assets/{Chat-C_aNxLPf.js → Chat-pQVBr82B.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-DZgHg5zH.js → ChatMarkdown-SCxRo6-e.js} +1 -1
  5. package/dist/renderer/assets/Config-DRtyF20X.js +21 -0
  6. package/dist/renderer/assets/{CronList-BuvMxOmF.js → CronList-BA5hVrYp.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-3nbUcH91.js → Dashboard-p3yI0Fck.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-LMG_D0FN.js → EmptyState-Dgh25c2x.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-DPuV1KoJ.js → KnowledgeDetail-CuC3Cjg1.js} +2 -2
  10. package/dist/renderer/assets/{KnowledgeHome-VFIxwTp4.js → KnowledgeHome-CH4GqtEZ.js} +2 -2
  11. package/dist/renderer/assets/{Logs-BymclbsW.js → Logs-BQrm2cq-.js} +1 -1
  12. package/dist/renderer/assets/{Modal-Dn_4NhR5.js → Modal-DfZsUS3Q.js} +3 -3
  13. package/dist/renderer/assets/{MonitorList-B1rSH7zN.js → MonitorList-CDWGIf1Q.js} +1 -1
  14. package/dist/renderer/assets/{Page-6cEj45pt.js → Page-CpmZ134Z.js} +1 -1
  15. package/dist/renderer/assets/ProjectDetail-B-Kwqodz.js +11 -0
  16. package/dist/renderer/assets/{ProjectList-CZbAGDMS.js → ProjectList-DtNT6dv-.js} +1 -1
  17. package/dist/renderer/assets/{Select-DE1pzt5p.js → Select--_s_a1uj.js} +1 -1
  18. package/dist/renderer/assets/{SessionChat-DyBDEXW9.js → SessionChat-BHfKpufe.js} +1 -1
  19. package/dist/renderer/assets/{SessionList-C8sTJnX6.js → SessionList-B0kQz-Ms.js} +1 -1
  20. package/dist/renderer/assets/{ThreadChat-CpAia9qR.js → ThreadChat-CRb6Z42k.js} +1 -1
  21. package/dist/renderer/assets/{Workspace-CKpVbGne.js → Workspace-j-O-14yC.js} +2 -2
  22. package/dist/renderer/assets/{arrow-left-455KUtQh.js → arrow-left-DnhnG-Tj.js} +1 -1
  23. package/dist/renderer/assets/{book-open-C_s_nHj6.js → book-open-Dgp3xcUz.js} +1 -1
  24. package/dist/renderer/assets/{bot-D0cidv6D.js → bot-BollztzX.js} +1 -1
  25. package/dist/renderer/assets/{check-DS7qvqek.js → check-BHj-iSsR.js} +1 -1
  26. package/dist/renderer/assets/{chevron-down-C43oRpZM.js → chevron-down-CeXCREMg.js} +1 -1
  27. package/dist/renderer/assets/{circle-aYyg1o0e.js → circle-B3eGQ-H3.js} +1 -1
  28. package/dist/renderer/assets/desktop-B5cYIqJH.js +1 -0
  29. package/dist/renderer/assets/{funnel-COrEnKiW.js → funnel-BkgiQrZC.js} +1 -1
  30. package/dist/renderer/assets/{heart-BO4CV3kx.js → heart-C-H_BPOT.js} +1 -1
  31. package/dist/renderer/assets/{index-CbvYBkud.js → index-C97cND_H.js} +2 -2
  32. package/dist/renderer/assets/{index-C4ZGOKQv.js → index-CYaol0bB.js} +9 -9
  33. package/dist/renderer/assets/{pencil-DR14wZjZ.js → pencil-DBHjVmSd.js} +1 -1
  34. package/dist/renderer/assets/{play-CRTtErO_.js → play-Cu9TIeSO.js} +1 -1
  35. package/dist/renderer/assets/{plus-Bswb_LiK.js → plus-PaUGBkMK.js} +1 -1
  36. package/dist/renderer/assets/projects-BmW4zbEE.js +1 -0
  37. package/dist/renderer/assets/{save-CKgtUije.js → save-dm5NifZE.js} +1 -1
  38. package/dist/renderer/assets/{search-RCAjElg9.js → search-Cq8cwrp6.js} +1 -1
  39. package/dist/renderer/assets/{server-DlKngwyt.js → server-DwiMsKFq.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-CZHYpZpR.js → session-utils-CD2tqK35.js} +1 -1
  41. package/dist/renderer/assets/{sessions-ChGwwlqi.js → sessions-quZ-oFVW.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-BRY90_8q.js → shield-check-B9UsjycW.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-CwTS-NZu.js → trash-2-CitZGPQS.js} +1 -1
  44. package/dist/renderer/assets/{user-mhOSrZ1d.js → user-BgVotGiF.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-5-ojceU3.js → wifi-off-CMgxdgfX.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/packages/core-sdk/src/index.js +6 -10
  48. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +29 -0
  49. package/dist-electron/services/local-ai-core/src/acp/store/runtime-config-store.js +164 -0
  50. package/dist-electron/services/local-ai-core/src/acp/store/schema.js +8 -0
  51. package/dist-electron/services/local-ai-core/src/agents/shared/launch-utils.js +1 -2
  52. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +2 -2
  53. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +1 -1
  54. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +8 -7
  55. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +6 -9
  56. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +4 -8
  57. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +32 -35
  58. package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +0 -89
  59. package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +4 -7
  60. package/dist-electron/services/local-ai-core/src/sandbox/sandbox-config.js +4 -4
  61. package/dist-electron/services/local-ai-core/src/scheduler/channel-execution-policy.js +11 -2
  62. package/dist-electron/tests/electron/plugin-kernel.test.js +72 -34
  63. package/dist-electron/tests/electron/runtime-config-store.test.js +176 -0
  64. package/dist-electron/tests/electron/sandbox-config.test.js +5 -5
  65. package/dist-electron/tests/electron/workspace-task-store.test.js +5 -5
  66. package/dist-electron/tests/integration/local-core-refactor.test.js +79 -0
  67. package/package.json +1 -1
  68. package/dist/renderer/assets/Config-DQAgYmCU.js +0 -21
  69. package/dist/renderer/assets/ProjectDetail-BcoxhPqE.js +0 -11
  70. package/dist/renderer/assets/desktop-CqHMtdOi.js +0 -1
  71. package/dist/renderer/assets/projects-BSilkED5.js +0 -1
@@ -0,0 +1,176 @@
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 node_fs_1 = require("node:fs");
9
+ const node_os_1 = require("node:os");
10
+ const node_path_1 = require("node:path");
11
+ const local_core_acp_store_js_1 = require("../../services/local-ai-core/src/acp/local-core-acp-store.js");
12
+ const server_routes_js_1 = require("../../services/local-ai-core/src/runtime/server-routes.js");
13
+ (0, node_test_1.default)('runtime config migrates legacy config.toml into sqlite without rewriting the file', () => {
14
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-runtime-config-'));
15
+ try {
16
+ const runtimeDir = (0, node_path_1.join)(userDataPath, 'runtime');
17
+ const legacyPath = (0, node_path_1.join)(runtimeDir, 'config.toml');
18
+ (0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
19
+ (0, node_fs_1.writeFileSync)(legacyPath, `
20
+ [[projects]]
21
+ name = "legacy-workspace"
22
+
23
+ [projects.agent]
24
+ type = "pi"
25
+
26
+ [projects.agent.options]
27
+ work_dir = "relative-workspace"
28
+ `, 'utf8');
29
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
30
+ const config = store.readRuntimeConfig();
31
+ strict_1.default.equal(config.storage, 'sqlite');
32
+ strict_1.default.equal(config.databasePath, (0, node_path_1.join)(runtimeDir, 'local-core.db'));
33
+ strict_1.default.equal(config.baseDir, runtimeDir);
34
+ strict_1.default.equal(config.migratedFromPath, legacyPath);
35
+ strict_1.default.equal(config.config.config_version, 2);
36
+ strict_1.default.equal(config.config.projects?.[0]?.name, 'legacy-workspace');
37
+ strict_1.default.equal((0, node_fs_1.existsSync)(legacyPath), true);
38
+ store.close();
39
+ const reopened = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
40
+ const persisted = reopened.readRuntimeConfig();
41
+ strict_1.default.equal(persisted.config.projects?.[0]?.name, 'legacy-workspace');
42
+ strict_1.default.equal(persisted.migratedFromPath, legacyPath);
43
+ reopened.close();
44
+ }
45
+ finally {
46
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
47
+ }
48
+ });
49
+ (0, node_test_1.default)('runtime config reports malformed legacy toml without saving an empty sqlite config', () => {
50
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-runtime-config-'));
51
+ try {
52
+ const runtimeDir = (0, node_path_1.join)(userDataPath, 'runtime');
53
+ const legacyPath = (0, node_path_1.join)(runtimeDir, 'config.toml');
54
+ (0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
55
+ (0, node_fs_1.writeFileSync)(legacyPath, '[[projects]\nname = "broken"\n', 'utf8');
56
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
57
+ const broken = store.readRuntimeConfig();
58
+ strict_1.default.match(broken.error || '', /Unexpected character/);
59
+ strict_1.default.equal(broken.migratedFromPath, legacyPath);
60
+ strict_1.default.deepEqual(broken.config.projects, []);
61
+ (0, node_fs_1.writeFileSync)(legacyPath, `
62
+ [[projects]]
63
+ name = "fixed-workspace"
64
+
65
+ [projects.agent]
66
+ type = "pi"
67
+ `, 'utf8');
68
+ const fixed = store.readRuntimeConfig();
69
+ strict_1.default.equal(fixed.error, undefined);
70
+ strict_1.default.equal(fixed.config.projects?.[0]?.name, 'fixed-workspace');
71
+ store.close();
72
+ }
73
+ finally {
74
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
75
+ }
76
+ });
77
+ (0, node_test_1.default)('runtime config migrates legacy custom configPath from settings before default path', () => {
78
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-runtime-config-'));
79
+ try {
80
+ const runtimeDir = (0, node_path_1.join)(userDataPath, 'runtime');
81
+ const customDir = (0, node_path_1.join)(userDataPath, 'custom-config');
82
+ const customPath = (0, node_path_1.join)(customDir, 'agentdock.toml');
83
+ const defaultPath = (0, node_path_1.join)(runtimeDir, 'config.toml');
84
+ (0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
85
+ (0, node_fs_1.mkdirSync)(customDir, { recursive: true });
86
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(runtimeDir, 'local-core-settings.json'), JSON.stringify({
87
+ configPath: customPath,
88
+ defaultProject: '',
89
+ autoStartService: true,
90
+ knowledge: {},
91
+ plugins: {},
92
+ }), 'utf8');
93
+ (0, node_fs_1.writeFileSync)(defaultPath, `
94
+ [[projects]]
95
+ name = "default-workspace"
96
+
97
+ [projects.agent]
98
+ type = "pi"
99
+ `, 'utf8');
100
+ (0, node_fs_1.writeFileSync)(customPath, `
101
+ [[projects]]
102
+ name = "custom-workspace"
103
+
104
+ [projects.agent]
105
+ type = "codex"
106
+ `, 'utf8');
107
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
108
+ const config = store.readRuntimeConfig();
109
+ strict_1.default.equal(config.migratedFromPath, customPath);
110
+ strict_1.default.equal(config.config.projects?.[0]?.name, 'custom-workspace');
111
+ strict_1.default.equal(config.config.projects?.[0]?.agent.type, 'codex');
112
+ store.close();
113
+ }
114
+ finally {
115
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
116
+ }
117
+ });
118
+ (0, node_test_1.default)('runtime config defaults to an empty sqlite-backed desktop config', () => {
119
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-runtime-config-'));
120
+ try {
121
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
122
+ const config = store.readRuntimeConfig();
123
+ strict_1.default.deepEqual(config.config.projects, []);
124
+ strict_1.default.equal(config.config.config_version, 2);
125
+ strict_1.default.equal((0, node_fs_1.existsSync)((0, node_path_1.join)(userDataPath, 'runtime', 'config.toml')), false);
126
+ store.close();
127
+ }
128
+ finally {
129
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
130
+ }
131
+ });
132
+ (0, node_test_1.default)('runtime config save persists structured config across store reopen', () => {
133
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-runtime-config-'));
134
+ try {
135
+ const store = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
136
+ store.saveRuntimeConfig({
137
+ projects: [{
138
+ name: 'sqlite-workspace',
139
+ agent: {
140
+ type: 'pi',
141
+ options: { work_dir: '/tmp/sqlite-workspace' },
142
+ },
143
+ platforms: [],
144
+ }],
145
+ sandbox_providers: [{
146
+ id: 'opensandbox-default',
147
+ type: 'opensandbox',
148
+ name: 'OpenSandbox',
149
+ server_url: 'http://127.0.0.1:8080',
150
+ api_key_env: 'OPEN_SANDBOX_API_KEY',
151
+ }],
152
+ });
153
+ store.close();
154
+ const reopened = new local_core_acp_store_js_1.LocalCoreAcpStore(userDataPath);
155
+ const config = reopened.readRuntimeConfig();
156
+ strict_1.default.equal(config.config.projects?.[0]?.name, 'sqlite-workspace');
157
+ strict_1.default.equal(config.config.sandbox_providers?.[0]?.id, 'opensandbox-default');
158
+ reopened.close();
159
+ }
160
+ finally {
161
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
162
+ }
163
+ });
164
+ (0, node_test_1.default)('runtime config routes expose sqlite config and reject raw toml save route', () => {
165
+ strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/runtime/runtime-config'), {
166
+ name: 'runtime.runtime-config.read',
167
+ });
168
+ strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('POST', '/api/local/v1/runtime/runtime-config'), {
169
+ name: 'runtime.runtime-config.save',
170
+ });
171
+ strict_1.default.deepEqual((0, server_routes_js_1.parseLocalAiCoreRoute)('GET', '/api/local/v1/runtime/config'), {
172
+ name: 'runtime.runtime-config.read',
173
+ });
174
+ strict_1.default.equal((0, server_routes_js_1.parseLocalAiCoreRoute)('POST', '/api/local/v1/runtime/config/raw'), null);
175
+ strict_1.default.equal((0, server_routes_js_1.parseLocalAiCoreRoute)('POST', '/api/local/v1/runtime/config/structured'), null);
176
+ });
@@ -16,10 +16,10 @@ const config_migration_js_1 = require("../../services/local-ai-core/src/runtime/
16
16
  const deployment_diagnostics_js_1 = require("../../services/local-ai-core/src/runtime/deployment-diagnostics.js");
17
17
  function configState(path) {
18
18
  return {
19
- path,
20
- exists: true,
21
- raw: '',
22
- parsed: { projects: [] },
19
+ storage: 'sqlite',
20
+ databasePath: (0, node_path_1.join)((0, node_path_1.dirname)(path), 'local-core.db'),
21
+ baseDir: (0, node_path_1.dirname)(path),
22
+ config: { projects: [] },
23
23
  };
24
24
  }
25
25
  function project(sandbox) {
@@ -208,7 +208,7 @@ function launchConfig() {
208
208
  const root = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-sandbox-'));
209
209
  try {
210
210
  const state = configState((0, node_path_1.join)(root, 'runtime', 'config.toml'));
211
- state.parsed = {
211
+ state.config = {
212
212
  projects: [],
213
213
  sandbox_runtime_images: [{
214
214
  id: 'fake-acp',
@@ -112,7 +112,7 @@ const env_utils_js_1 = require("../../services/local-ai-core/src/runtime/env-uti
112
112
  log: () => { },
113
113
  });
114
114
  const controller = new local_core_controller_js_1.LocalCoreController(userDataPath, runtime);
115
- await controller.saveStructuredConfigFile({
115
+ await controller.saveRuntimeConfig({
116
116
  projects: [{
117
117
  name: 'workspace-a',
118
118
  agent: {
@@ -128,9 +128,9 @@ const env_utils_js_1 = require("../../services/local-ai-core/src/runtime/env-uti
128
128
  platforms: [],
129
129
  }],
130
130
  });
131
- const config = await controller.readConfigFile();
132
- strict_1.default.equal(config.parsed?.projects?.[0]?.agent.options?.provider_id, 'deepseek');
133
- strict_1.default.equal(config.parsed?.projects?.[0]?.agent.providers, undefined);
131
+ const config = await controller.readRuntimeConfig();
132
+ strict_1.default.equal(config.config?.projects?.[0]?.agent.options?.provider_id, 'deepseek');
133
+ strict_1.default.equal(config.config?.projects?.[0]?.agent.providers, undefined);
134
134
  const providers = controller.store.listModelProviders();
135
135
  strict_1.default.equal(providers[0]?.id, 'deepseek');
136
136
  strict_1.default.equal(providers[0]?.name, 'deepseek');
@@ -155,7 +155,7 @@ const env_utils_js_1 = require("../../services/local-ai-core/src/runtime/env-uti
155
155
  base_url: 'https://api.deepseek.com',
156
156
  model: 'deepseek-v4-flash',
157
157
  });
158
- await controller.saveStructuredConfigFile({
158
+ await controller.saveRuntimeConfig({
159
159
  projects: [{
160
160
  name: 'workspace-a',
161
161
  agent: {
@@ -898,6 +898,85 @@ const thread_slash_command_dispatcher_js_1 = require("../../services/local-ai-co
898
898
  agentType: 'claudecode',
899
899
  });
900
900
  });
901
+ (0, node_test_1.default)('lark side-thread execution policy skips reusable threads with a different preferred agent', async () => {
902
+ const job = {
903
+ id: 'job-1',
904
+ workspaceId: '知识库',
905
+ platform: 'lark',
906
+ route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1', threadId: 'thread-origin' },
907
+ executionMode: 'side-thread',
908
+ triggerType: 'cron',
909
+ cronExpr: '*/2 * * * *',
910
+ promptTemplate: 'ping',
911
+ description: 'two-minute ping',
912
+ enabled: true,
913
+ concurrencyPolicy: 'skip_if_running',
914
+ createdAt: '2026-04-22T06:00:00.000Z',
915
+ updatedAt: '2026-04-22T06:00:00.000Z',
916
+ };
917
+ const createThreadCalls = [];
918
+ const policy = (0, lark_execution_policies_js_1.createLarkExecutionPolicy)(job, {
919
+ store: {},
920
+ workspaceRouter: {
921
+ getThreadSessionKey: (threadId) => `session:${threadId}`,
922
+ listThreads: async () => [
923
+ { id: 'thread-old-codex', title: '[Scheduled:Lark] two-minute ping', agentType: 'codex' },
924
+ ],
925
+ createThread: async (workspaceId, title, agentType) => {
926
+ createThreadCalls.push({ workspaceId, title: title || '', agentType });
927
+ return { id: 'thread-new-claudecode' };
928
+ },
929
+ },
930
+ getChannelRuntime: () => ({
931
+ registerScheduledThreadBridge: () => () => { },
932
+ }),
933
+ }, async () => 'thread-origin', () => 'claudecode');
934
+ const target = await policy.resolveTarget(job);
935
+ strict_1.default.equal(target.threadId, 'thread-new-claudecode');
936
+ strict_1.default.equal(createThreadCalls.length, 1);
937
+ strict_1.default.deepEqual(createThreadCalls[0], {
938
+ workspaceId: '知识库',
939
+ title: '[Scheduled:Lark] two-minute ping',
940
+ agentType: 'claudecode',
941
+ });
942
+ });
943
+ (0, node_test_1.default)('lark side-thread execution policy reuses a thread with the preferred agent', async () => {
944
+ const job = {
945
+ id: 'job-1',
946
+ workspaceId: '知识库',
947
+ platform: 'lark',
948
+ route: { type: 'channel.chat', channelId: 'chat-1', participantId: 'user-1', threadId: 'thread-origin' },
949
+ executionMode: 'side-thread',
950
+ triggerType: 'cron',
951
+ cronExpr: '*/2 * * * *',
952
+ promptTemplate: 'ping',
953
+ description: 'two-minute ping',
954
+ enabled: true,
955
+ concurrencyPolicy: 'skip_if_running',
956
+ createdAt: '2026-04-22T06:00:00.000Z',
957
+ updatedAt: '2026-04-22T06:00:00.000Z',
958
+ };
959
+ let created = false;
960
+ const policy = (0, lark_execution_policies_js_1.createLarkExecutionPolicy)(job, {
961
+ store: {},
962
+ workspaceRouter: {
963
+ getThreadSessionKey: (threadId) => `session:${threadId}`,
964
+ listThreads: async () => [
965
+ { id: 'thread-matching-claudecode', title: '[Scheduled:Lark] two-minute ping', agentType: 'claudecode' },
966
+ ],
967
+ createThread: async () => {
968
+ created = true;
969
+ return { id: 'thread-new' };
970
+ },
971
+ },
972
+ getChannelRuntime: () => ({
973
+ registerScheduledThreadBridge: () => () => { },
974
+ }),
975
+ }, async () => 'thread-origin', () => 'claudecode');
976
+ const target = await policy.resolveTarget(job);
977
+ strict_1.default.equal(target.threadId, 'thread-matching-claudecode');
978
+ strict_1.default.equal(created, false);
979
+ });
901
980
  (0, node_test_1.default)('lark side-thread execution policy falls back to workspace default when no preferred agent is set', async () => {
902
981
  const job = {
903
982
  id: 'job-1',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "license": "PolyForm-Noncommercial-1.0.0",
5
5
  "type": "module",
6
6
  "main": "dist-electron/electron/main.js",
@@ -1,21 +0,0 @@
1
- import{c as m,u as B,r as n,j as e,B as c,R as E,L as H,a0 as $,I as q,a1 as T,a2 as V}from"./index-C4ZGOKQv.js";import{g as F,q as X,v as R,w as G,x as J}from"./desktop-CqHMtdOi.js";import{B as x}from"./Badge-DpYXv6XT.js";import{P as O,S as l,a as C}from"./Page-6cEj45pt.js";import{S as Q}from"./shield-check-BRY90_8q.js";import{S as W,P as Y}from"./save-CKgtUije.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 Z=[["path",{d:"M10 12.5 8 15l2 2.5",key:"1tg20x"}],["path",{d:"m14 12.5 2 2.5-2 2.5",key:"yinavb"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z",key:"1mlx9k"}]],ee=m("file-code",Z);/**
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 se=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],te=m("rotate-ccw",se);/**
12
- * @license lucide-react v0.487.0 - ISC
13
- *
14
- * This source code is licensed under the ISC license.
15
- * See the LICENSE file in the root directory of this source tree.
16
- */const ae=[["path",{d:"M15 12h-5",key:"r7krc0"}],["path",{d:"M15 8h-5",key:"1khuty"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4",key:"zz82l3"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3",key:"1ph1d7"}]],ne=m("scroll-text",ae);/**
17
- * @license lucide-react v0.487.0 - ISC
18
- *
19
- * This source code is licensed under the ISC license.
20
- * See the LICENSE file in the root directory of this source tree.
21
- */const re=[["path",{d:"M11 2v2",key:"1539x4"}],["path",{d:"M5 2v2",key:"1yf1q8"}],["path",{d:"M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1",key:"rb5t3r"}],["path",{d:"M8 15a6 6 0 0 0 12 0v-3",key:"x18d4x"}],["circle",{cx:"20",cy:"10",r:"2",key:"ts1r5v"}]],ie=m("stethoscope",re);function le(a){return a==="api_ready"?"success":a==="error"?"danger":a==="starting"?"warning":"neutral"}function xe(){const{t:a}=B(),[t,h]=n.useState(null),[o,M]=n.useState(null),[p,f]=n.useState([]),[d,I]=n.useState(null),[u,j]=n.useState(""),[D,v]=n.useState(""),[P,y]=n.useState(!0),[w,N]=n.useState(!1),[z,k]=n.useState(!1),[b,i]=n.useState(""),g=n.useCallback(async()=>{y(!0);try{const[s,r,S]=await Promise.allSettled([F(),X(),R()]);s.status==="fulfilled"&&(h(s.value),j(s.value.settings.knowledge.baseUrl||""),v(s.value.settings.knowledge.baseUrl||"")),r.status==="fulfilled"&&M(r.value),S.status==="fulfilled"&&f(S.value)}finally{y(!1)}},[]);n.useEffect(()=>{g()},[g]);const A=async()=>{if(confirm(a("system.restartConfirm")))try{await T(),i(a("common.success")),await g()}catch(s){i(s.message)}},L=async()=>{if(confirm(a("system.reloadConfirm")))try{await V(),i(a("common.success")),await g()}catch(s){i(s.message)}},U=async()=>{N(!0);try{const s=await G({knowledge:{baseUrl:u,authMode:(t==null?void 0:t.settings.knowledge.authMode)||"none",token:(t==null?void 0:t.settings.knowledge.token)||"",headerName:(t==null?void 0:t.settings.knowledge.headerName)||"X-API-Key",defaultCollection:(t==null?void 0:t.settings.knowledge.defaultCollection)||"personal_knowledge"}});h(r=>r&&{...r,settings:s}),v(s.knowledge.baseUrl||""),i(a("common.success"))}catch(s){i(s.message)}finally{N(!1)}},_=async()=>{k(!0);try{const s=await J();I(s),f(await R()),i(`Diagnostics completed with ${s.status} status.`)}catch(s){i(s.message)}finally{k(!1)}},K=u!==D;return e.jsxs("div",{className:"space-y-6 animate-fade-in",children:[e.jsx(O,{title:a("nav.system"),description:"Runtime health, logs, and plugin diagnostics. Advanced config is available read-only from the diagnostics drawer.",actions:e.jsxs(e.Fragment,{children:[e.jsxs(c,{variant:"secondary",onClick:L,children:[e.jsx(E,{size:16})," ",a("system.reload")]}),e.jsxs(c,{variant:"danger",onClick:A,children:[e.jsx(te,{size:16})," ",a("system.restart")]}),e.jsx(H,{to:"/system/logs",children:e.jsxs(c,{variant:"secondary",children:[e.jsx(ne,{size:16})," ",a("system.logs")]})})]})}),b?e.jsx("div",{role:"status",className:"rounded-lg border border-primary/20 bg-primary/10 px-4 py-3 text-sm text-primary",children:b}):null,e.jsxs("div",{className:"grid grid-cols-1 gap-4 lg:grid-cols-3",children:[e.jsxs(l,{className:"app-panel",title:"Runtime",description:P?"Loading...":"Local service status.",children:[e.jsx(C,{tone:le(t==null?void 0:t.phase),children:(t==null?void 0:t.phase)||"unknown"}),e.jsx("p",{className:"mt-3 text-sm text-muted-foreground",children:t!=null&&t.pendingRestart?"Restart required to apply saved changes.":"No pending restart."})]}),e.jsx(l,{className:"app-panel",title:"Config",description:"Active config file location.",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(ee,{size:18,className:"mt-0.5 text-primary"}),e.jsx("p",{className:"break-all font-mono text-xs leading-5 text-muted-foreground",children:(t==null?void 0:t.settings.configPath)||(t==null?void 0:t.configFile.path)||"-"})]})}),e.jsxs(l,{className:"app-panel",title:"Plugins",description:"Health summary only.",children:[e.jsx("p",{className:"text-2xl font-semibold text-foreground",children:o?`${o.enabledPluginCount}/${o.pluginCount}`:"-"}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"enabled plugins"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-4 xl:grid-cols-2",children:[e.jsx(l,{className:"app-panel",title:"Diagnostics",description:"Structured runtime and channel health checks.",actions:e.jsxs(c,{size:"sm",variant:"secondary",onClick:()=>void _(),loading:z,children:[e.jsx(ie,{size:14})," Run doctor"]}),children:d?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(C,{tone:d.status==="pass"?"success":d.status==="warn"?"warning":"danger",children:d.status}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Checked ",new Date(d.checkedAt).toLocaleString()]})]}),e.jsx("div",{className:"space-y-2",children:d.checks.map(s=>{var r;return e.jsx("div",{className:"app-list-row",children:e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-foreground",children:s.label}),e.jsx("p",{className:"mt-1 text-xs leading-5 text-muted-foreground",children:s.summary}),(r=s.errorInfo)!=null&&r.suggestedAction?e.jsx("p",{className:"mt-1 text-xs leading-5 text-amber-700 dark:text-amber-200",children:s.errorInfo.suggestedAction}):null]}),e.jsx(x,{variant:s.status==="pass"?"success":s.status==="warn"?"warning":"danger",children:s.status})]})},s.id)})})]}):e.jsxs("div",{className:"flex items-start gap-3 rounded-lg border border-dashed border-border px-4 py-3 text-sm text-muted-foreground",children:[e.jsx(Q,{size:16,className:"mt-0.5 shrink-0"}),e.jsx("p",{children:"Run doctor to validate config, runtime readiness, channel health, and log access."})]})}),e.jsx(l,{className:"app-panel",title:"Recent Errors",description:"Aggregated runtime and channel failures from the current window.",children:p.length===0?e.jsx("div",{className:"py-8 text-sm text-muted-foreground",children:"No aggregated errors in the current diagnostics window."}):e.jsx("div",{className:"space-y-3",children:p.map(s=>e.jsx("div",{className:"app-list-row",children:e.jsx("div",{className:"flex items-start justify-between gap-3",children:e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx($,{size:14,className:"text-amber-500"}),e.jsx("p",{className:"text-sm font-medium text-foreground",children:s.errorInfo.userMessage}),e.jsx(x,{variant:s.errorInfo.severity==="error"?"danger":s.errorInfo.severity==="warning"?"warning":"info",children:s.errorInfo.code})]}),e.jsx("p",{className:"mt-1 text-xs leading-5 text-muted-foreground",children:s.errorInfo.message}),s.errorInfo.suggestedAction?e.jsx("p",{className:"mt-1 text-xs leading-5 text-amber-700 dark:text-amber-200",children:s.errorInfo.suggestedAction}):null,e.jsxs("p",{className:"mt-2 text-xs text-muted-foreground",children:[s.count," occurrence(s), last seen ",new Date(s.lastSeenAt).toLocaleString()]})]})})},s.key))})})]}),e.jsx(l,{className:"app-panel",title:"Knowledge",description:"System-wide knowledge API connection.",actions:e.jsxs(c,{size:"sm",onClick:()=>void U(),loading:w,disabled:!K&&!w,children:[e.jsx(W,{size:14})," Save"]}),children:e.jsx(q,{label:"Knowledge base URL",value:u,onChange:s=>j(s.target.value),placeholder:"http://127.0.0.1:16007"})}),e.jsx(l,{className:"app-panel",title:a("system.plugins"),description:"Plugin state is read-only in the daily UI. Use backend config for advanced changes.",children:o?o.plugins.length===0?e.jsx("div",{className:"py-8 text-sm text-muted-foreground",children:"No plugins registered."}):e.jsx("div",{className:"divide-y divide-border",children:o.plugins.map(s=>e.jsxs("div",{className:"flex items-start justify-between gap-4 py-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Y,{size:15,className:"text-muted-foreground"}),e.jsx("p",{className:"truncate text-sm font-medium text-foreground",children:s.pluginId})]}),e.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:s.health.summary||s.manifest.provides.join(", ")||"No declared capabilities"})]}),e.jsx(x,{variant:s.health.status==="healthy"?"success":s.health.status==="failed"?"danger":"warning",children:s.health.status})]},s.pluginId))}):e.jsx("div",{className:"py-8 text-sm text-muted-foreground",children:"Loading..."})})]})}export{xe as default};
@@ -1,11 +0,0 @@
1
- import{c as oe,D as M,u as we,E as Ne,r as c,j as s,L as Se,B as h,Z as Ce,g as Y,C as w,I as j,G as ke,H as Pe}from"./index-C4ZGOKQv.js";import{B as A}from"./Badge-DpYXv6XT.js";import{M as ee}from"./Modal-Dn_4NhR5.js";import{S as se}from"./Select-DE1pzt5p.js";import{E as ae}from"./EmptyState-LMG_D0FN.js";import{P as ze,S as B}from"./Page-6cEj45pt.js";import{g as Ie}from"./projects-BSilkED5.js";import{d as Ae,c as P,h as Ee,f as E,j as Me}from"./desktop-CqHMtdOi.js";import{D as T,e as Le}from"./desktop-JQkhNOF4.js";import{A as $e}from"./arrow-left-455KUtQh.js";import{S as He}from"./shield-check-BRY90_8q.js";import{H as te}from"./heart-BO4CV3kx.js";import{P as Re,S as De}from"./save-CKgtUije.js";import{P as Be}from"./plus-Bswb_LiK.js";import{C as Te}from"./check-DS7qvqek.js";import{T as Fe}from"./trash-2-CwTS-NZu.js";import{P as Oe}from"./play-CRTtErO_.js";import"./index-CbvYBkud.js";import"./chevron-down-C43oRpZM.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 Ue=[["path",{d:"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",key:"zw3jo"}],["path",{d:"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",key:"1wduqc"}],["path",{d:"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",key:"kqbvx6"}]],qe=oe("layers",Ue);/**
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 Ge=[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]],Je=oe("pause",Ge),Ke=e=>M.get(`/projects/${e}/heartbeat`),Ze=e=>M.post(`/projects/${e}/heartbeat/pause`),Ve=e=>M.post(`/projects/${e}/heartbeat/resume`),We=e=>M.post(`/projects/${e}/heartbeat/run`),Xe=(e,r)=>M.post(`/projects/${e}/heartbeat/interval`,{minutes:r});function F(e){return JSON.parse(JSON.stringify(e||{}))}function Qe(e,r){var i,o,d;const n=(i=e==null?void 0:e.projects)==null?void 0:i.find(m=>m.name===r);return String(((d=(o=n==null?void 0:n.agent)==null?void 0:o.options)==null?void 0:d.provider_id)||"")}function re(e,r,n){var f;const i=F(e),o=Array.isArray(i.projects)?i.projects:[],d=o.findIndex(_=>_.name===r);if(d<0)throw new Error(`Project not found in config: ${r}`);const m=o[d];return o[d]={...m,agent:{...m.agent,options:{...((f=m.agent)==null?void 0:f.options)||{},provider_id:n}}},i.projects=o,i}function Ye(e,r,n){var f;const i=F(e),o=Array.isArray(i.projects)?i.projects:[],d=o.findIndex(_=>_.name===r);if(d<0)throw new Error(`Project not found in config: ${r}`);const m=o[d];return o[d]={...m,agent:{...m.agent,options:{...((f=m.agent)==null?void 0:f.options)||{},model:n}}},i.projects=o,i}function es(e,r){const n=F(e),i=Array.isArray(n.projects)?n.projects:[];return n.projects=i.map(o=>{var d,m,f;return((m=(d=o.agent)==null?void 0:d.options)==null?void 0:m.provider_id)!==r?o:{...o,agent:{...o.agent,options:{...((f=o.agent)==null?void 0:f.options)||{},provider_id:""}}}}),n}const l={enabled:!1,provider_id:T,runtime_image_id:Le("pi").id,server_url:"http://127.0.0.1:8080",image:"agentdock/pi-acp:local",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 ss(e){const r=new Set,n=String((e==null?void 0:e.model)||"").trim();n&&r.add(n);for(const i of(e==null?void 0:e.models)||[]){const o=String((i==null?void 0:i.model)||"").trim();o&&r.add(o)}return[...r]}function ws(){var K,Z;const{t:e}=we(),{name:r}=Ne(),[n,i]=c.useState("overview"),[o,d]=c.useState(null),[m,f]=c.useState([]),[_,ne]=c.useState(""),[u,ie]=c.useState(null),[O,le]=c.useState([]),[ce,de]=c.useState(""),[me,U]=c.useState(!0),[g,b]=c.useState(l),[xe,q]=c.useState(!1),[G,x]=c.useState(""),[he,L]=c.useState(!1),[v,z]=c.useState({name:"",api_key:"",base_url:"",model:""}),[pe,$]=c.useState(!1),[J,fe]=c.useState("30"),p=c.useCallback(async()=>{var a,t,N,y,S;if(r)try{U(!0);const[C,I,V,W]=await Promise.allSettled([Ie(r),Ae(),Ke(r),P()]);C.status==="fulfilled"&&d(C.value);const X=I.status==="fulfilled"?I.value.providers||[]:[];if(I.status==="fulfilled"&&f(X),V.status==="fulfilled"&&ie(V.value),W.status==="fulfilled"){const H=W.value.parsed,k=(a=H==null?void 0:H.projects)==null?void 0:a.find(D=>D.name===r),Q=Qe(H,r),R=X.find(D=>D.id===Q);ne(Q),le(ss(R)),de(String(((N=(t=k==null?void 0:k.agent)==null?void 0:t.options)==null?void 0:N.model)||(R==null?void 0:R.model)||"")),b(as((S=(y=k==null?void 0:k.agent)==null?void 0:y.options)==null?void 0:S.sandbox))}}finally{U(!1)}},[r]);c.useEffect(()=>{p();const a=()=>p();return window.addEventListener("cc:refresh",a),()=>window.removeEventListener("cc:refresh",a)},[p]);const ue=async()=>{if(!(!r||!v.name)){x("");try{const a=await Ee(v),t=await P();if(!t.parsed)throw new Error("Config file is unavailable.");await E(re(t.parsed,r,a.id)),L(!1),z({name:"",api_key:"",base_url:"",model:""}),x("Provider created."),await p()}catch(a){x(a instanceof Error?a.message:String(a))}}},ge=async a=>{if(r){x("");try{const t=await P();if(!t.parsed)throw new Error("Config file is unavailable.");await E(re(t.parsed,r,a)),x("Provider selected."),await p()}catch(t){x(t instanceof Error?t.message:String(t))}}},ve=async a=>{if(r){x("");try{const t=await P();if(!t.parsed)throw new Error("Config file is unavailable.");await E(es(t.parsed,a)),await Me(a),x("Provider removed."),await p()}catch(t){x(t instanceof Error?t.message:String(t))}}},je=async a=>{if(r){x("");try{const t=await P();if(!t.parsed)throw new Error("Config file is unavailable.");await E(Ye(t.parsed,r,a)),x("Model selected."),await p()}catch(t){x(t instanceof Error?t.message:String(t))}}},be=async()=>{r&&(await Xe(r,parseInt(J)),$(!1),p())},_e=[{key:"overview",icon:qe},{key:"providers",icon:Ce},{key:"sandbox",icon:He},{key:"heartbeat",icon:te}],ye=async()=>{var a;if(r){q(!0),x("");try{const N=(await P()).parsed||{},y=Array.isArray(N.projects)?[...N.projects]:[],S=y.findIndex(I=>I.name===r);if(S<0)throw new Error(`Project not found in config: ${r}`);const C=y[S];y[S]={...C,agent:{...C.agent,options:{...((a=C.agent)==null?void 0:a.options)||{},sandbox:ts(g)}}},await E({...N,projects:y}),x("Sandbox settings saved."),await p()}catch(t){x((t==null?void 0:t.message)||String(t))}finally{q(!1)}}};return me&&!o?s.jsx("div",{className:"flex items-center justify-center h-64 text-muted-foreground animate-pulse",children:"Loading..."}):s.jsxs("div",{className:"space-y-6 animate-fade-in",children:[s.jsx(ze,{title:r,description:"Project overview, providers, and heartbeat status. Low-frequency settings are no longer editable in the daily UI.",actions:s.jsx(Se,{to:"/projects",children:s.jsxs(h,{variant:"secondary",size:"sm",children:[s.jsx($e,{size:14})," Back"]})})}),o?s.jsxs("div",{className:"app-toolbar flex flex-wrap items-center gap-2",children:[s.jsx(A,{variant:"info",children:o.agent_type}),s.jsx(A,{variant:o.heartbeat_enabled?"success":"secondary",children:o.heartbeat_enabled?"heartbeat on":"heartbeat off"}),s.jsxs("span",{className:"text-xs text-muted-foreground",children:[o.sessions_count," sessions"]})]}):null,G?s.jsx("div",{role:"status",className:"rounded-lg border border-primary/20 bg-primary/10 px-4 py-3 text-sm text-primary",children:G}):null,s.jsx("div",{className:"flex gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:_e.map(({key:a,icon:t})=>s.jsxs("button",{onClick:()=>i(a),className:Y("app-segment flex items-center gap-2",n===a?"app-segment-active":"app-segment-idle"),children:[s.jsx(t,{size:16}),e(`projects.tabs.${a}`)]},a))}),n==="overview"&&o&&s.jsxs("div",{className:"space-y-4",children:[s.jsx(B,{className:"app-panel",title:e("projects.platforms"),children:s.jsx("div",{className:"flex flex-wrap gap-2",children:(K=o.platforms)==null?void 0:K.map(a=>s.jsxs(A,{variant:a.connected?"success":"danger",children:[s.jsx(Re,{size:12,className:"mr-1"})," ",a.type," ",a.connected?"✓":"✗"]},a.type))})}),s.jsxs(B,{className:"app-panel",title:e("sessions.title"),children:[s.jsxs("p",{className:"text-sm text-muted-foreground",children:[o.sessions_count," ",e("nav.sessions").toLowerCase()]}),((Z=o.active_session_keys)==null?void 0:Z.length)>0&&s.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:o.active_session_keys.map(a=>s.jsx(A,{variant:"default",children:a},a))})]})]}),n==="providers"&&s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"flex justify-between items-center",children:[s.jsx("h3",{className:"text-sm font-semibold text-foreground",children:e("providers.title")}),s.jsxs(h,{size:"sm",onClick:()=>L(!0),children:[s.jsx(Be,{size:14})," ",e("providers.add")]})]}),m.length===0?s.jsx(ae,{message:e("common.noData")}):s.jsx("div",{className:"space-y-2",children:m.map(a=>s.jsx(w,{className:"app-panel",children:s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("span",{className:"font-medium text-foreground",children:a.name}),a.id===_&&s.jsx(A,{variant:"success",children:e("providers.active")})]}),s.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[a.model," ",a.base_url?`· ${a.base_url}`:""]})]}),s.jsxs("div",{className:"flex gap-2",children:[a.id!==_&&s.jsxs(h,{size:"sm",variant:"secondary",onClick:()=>{ge(a.id)},children:[s.jsx(Te,{size:14})," ",e("providers.activate")]}),a.id!==_&&s.jsx(h,{size:"sm",variant:"danger",onClick:()=>{ve(a.id)},children:s.jsx(Fe,{size:14})})]})]})},a.id))}),O.length>0&&s.jsxs(w,{children:[s.jsx("h3",{className:"text-sm font-semibold text-foreground mb-3",children:e("providers.models")}),s.jsx("div",{className:"flex flex-wrap gap-2",children:O.map(a=>s.jsx("button",{onClick:()=>{je(a)},className:Y("px-3 py-1.5 rounded-lg text-xs font-medium transition-all",a===ce?"bg-primary/15 text-primary border border-primary/30":"bg-secondary text-secondary-foreground hover:bg-secondary/80"),children:a},a))})]}),s.jsx(ee,{open:he,onClose:()=>L(!1),title:e("providers.add"),children:s.jsxs("div",{className:"space-y-3",children:[s.jsx(j,{label:e("providers.name"),value:v.name,onChange:a=>z({...v,name:a.target.value})}),s.jsx(j,{label:"API Key",type:"password",value:v.api_key,onChange:a=>z({...v,api_key:a.target.value})}),s.jsx(j,{label:e("providers.baseUrl"),value:v.base_url,onChange:a=>z({...v,base_url:a.target.value}),placeholder:"https://api.example.com"}),s.jsx(j,{label:e("providers.model"),value:v.model,onChange:a=>z({...v,model:a.target.value})}),s.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[s.jsx(h,{variant:"secondary",onClick:()=>L(!1),children:e("common.cancel")}),s.jsx(h,{onClick:ue,children:e("providers.add")})]})]})})]}),n==="sandbox"&&s.jsx(B,{title:"Sandbox",description:"Run this project agent inside an OpenSandbox container.",actions:s.jsxs(h,{size:"sm",onClick:()=>void ye(),loading:xe,children:[s.jsx(De,{size:14})," Save"]}),children:s.jsxs("div",{className:"space-y-4",children:[s.jsxs("label",{className:"flex items-center gap-3 text-sm font-medium text-foreground",children:[s.jsx("input",{type:"checkbox",className:"h-4 w-4 rounded border-border",checked:g.enabled,onChange:a=>b(t=>({...t,enabled:a.target.checked}))}),"Enable sandbox mode"]}),g.enabled?s.jsxs("div",{className:"space-y-3",children:[s.jsxs("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2",children:[s.jsxs(se,{label:"State scope",value:g.state_scope,onChange:a=>b(t=>({...t,state_scope:a.target.value})),children:[s.jsx("option",{value:"user",children:"User"}),s.jsx("option",{value:"project",children:"Project"}),s.jsx("option",{value:"thread",children:"Thread"}),s.jsx("option",{value:"run",children:"Run"})]}),s.jsx(j,{label:"Timeout seconds",type:"number",value:g.timeout_seconds,onChange:a=>b(t=>({...t,timeout_seconds:a.target.value}))}),s.jsxs(se,{label:"Sandbox lifecycle",value:g.sandbox_lifecycle,onChange:a=>b(t=>({...t,sandbox_lifecycle:a.target.value})),children:[s.jsx("option",{value:"per_thread",children:"Keep warm per thread"}),s.jsx("option",{value:"per_run",children:"Close after each run"})]}),s.jsx(j,{label:"Idle seconds",type:"number",value:g.idle_seconds,onChange:a=>b(t=>({...t,idle_seconds:a.target.value}))}),s.jsx(j,{label:"Warm pool",type:"number",value:g.warm_pool_size,onChange:a=>b(t=>({...t,warm_pool_size:a.target.value}))}),s.jsx(j,{label:"CPU",value:g.cpu,onChange:a=>b(t=>({...t,cpu:a.target.value}))}),s.jsx(j,{label:"Memory",value:g.memory,onChange:a=>b(t=>({...t,memory:a.target.value}))})]}),s.jsx("p",{className:"text-sm text-muted-foreground",children:"OpenSandbox URL, API key env, image, ACP port, and sandbox mount paths are resolved from the global sandbox provider and runtime image registry."})]}):s.jsx("p",{className:"text-sm text-muted-foreground",children:"Local bundled runtime execution is active for this project."})]})}),n==="heartbeat"&&s.jsxs("div",{className:"space-y-4",children:[u?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[s.jsxs(w,{children:[s.jsx("p",{className:"text-xs text-muted-foreground",children:e("heartbeat.status")}),s.jsx("p",{className:"text-lg font-bold text-foreground mt-1",children:u.paused?e("heartbeat.paused"):e("heartbeat.running")})]}),s.jsxs(w,{children:[s.jsx("p",{className:"text-xs text-muted-foreground",children:e("heartbeat.interval")}),s.jsxs("p",{className:"text-lg font-bold text-foreground mt-1",children:[u.interval_mins,"m"]})]}),s.jsxs(w,{children:[s.jsx("p",{className:"text-xs text-muted-foreground",children:e("heartbeat.runCount")}),s.jsx("p",{className:"text-lg font-bold text-foreground mt-1",children:u.run_count})]}),s.jsxs(w,{children:[s.jsx("p",{className:"text-xs text-muted-foreground",children:e("heartbeat.errorCount")}),s.jsx("p",{className:"text-lg font-bold text-foreground mt-1",children:u.error_count})]})]}),s.jsx(w,{children:s.jsxs("div",{className:"space-y-2 text-sm",children:[s.jsxs("p",{className:"text-muted-foreground",children:[e("heartbeat.lastRun"),": ",s.jsx("span",{className:"text-foreground",children:ke(u.last_run)})]}),s.jsxs("p",{className:"text-muted-foreground",children:[e("heartbeat.skippedBusy"),": ",s.jsx("span",{className:"text-foreground",children:u.skipped_busy})]}),u.last_error&&s.jsx("p",{className:"text-destructive",children:u.last_error})]})}),s.jsxs("div",{className:"flex gap-2",children:[u.paused?s.jsxs(h,{onClick:()=>{Ve(r).then(p)},children:[s.jsx(Oe,{size:14})," ",e("heartbeat.resume")]}):s.jsxs(h,{variant:"secondary",onClick:()=>{Ze(r).then(p)},children:[s.jsx(Je,{size:14})," ",e("heartbeat.pause")]}),s.jsxs(h,{variant:"secondary",onClick:()=>{We(r).then(p)},children:[s.jsx(te,{size:14})," ",e("heartbeat.trigger")]}),s.jsxs(h,{variant:"secondary",onClick:()=>$(!0),children:[s.jsx(Pe,{size:14})," ",e("heartbeat.setInterval")]})]})]}):s.jsx(ae,{message:e("common.noData")}),s.jsx(ee,{open:pe,onClose:()=>$(!1),title:e("heartbeat.setInterval"),children:s.jsxs("div",{className:"space-y-3",children:[s.jsx(j,{label:`${e("heartbeat.interval")} (min)`,type:"number",value:J,onChange:a=>fe(a.target.value)}),s.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[s.jsx(h,{variant:"secondary",onClick:()=>$(!1),children:e("common.cancel")}),s.jsx(h,{onClick:be,children:e("common.save")})]})]})})]})]})}function as(e){return{enabled:!!(e!=null&&e.enabled),provider_id:(e==null?void 0:e.provider_id)||T,runtime_image_id:(e==null?void 0:e.runtime_image_id)||l.runtime_image_id,server_url:(e==null?void 0:e.server_url)||l.server_url,image:(e==null?void 0:e.image)||l.image,acp_port:String((e==null?void 0:e.acp_port)||l.acp_port),state_scope:(e==null?void 0:e.state_scope)||l.state_scope,timeout_seconds:String((e==null?void 0:e.timeout_seconds)||l.timeout_seconds),sandbox_lifecycle:(e==null?void 0:e.sandbox_lifecycle)||l.sandbox_lifecycle,idle_seconds:String((e==null?void 0:e.idle_seconds)||l.idle_seconds),warm_pool_size:String((e==null?void 0:e.warm_pool_size)??l.warm_pool_size),cpu:(e==null?void 0:e.cpu)||l.cpu,memory:(e==null?void 0:e.memory)||l.memory,workspace_mount_path:(e==null?void 0:e.workspace_mount_path)||l.workspace_mount_path,state_mount_path:(e==null?void 0:e.state_mount_path)||l.state_mount_path}}function ts(e){return{enabled:e.enabled,provider_id:e.provider_id.trim()||T,runtime_image_id:e.runtime_image_id.trim()||l.runtime_image_id,state_scope:e.state_scope,timeout_seconds:Number(e.timeout_seconds)||Number(l.timeout_seconds),sandbox_lifecycle:e.sandbox_lifecycle,idle_seconds:Number(e.idle_seconds)||Number(l.idle_seconds),warm_pool_size:Math.max(0,Number(e.warm_pool_size)||0),cpu:e.cpu.trim()||l.cpu,memory:e.memory.trim()||l.memory}}export{ws as default};
@@ -1 +0,0 @@
1
- import{a3 as l,s as g,a4 as c,a5 as u,a6 as h,a7 as C,a8 as v,a9 as k,aa as p,ab as w,ac as S,ad as P,ae as m,af as L,ag as y,ah as D,ai as R,aj as f,ak as b,al as G,am as Q,an as E,ao as M,ap as B,aq as A,ar as F,as as I,at as W,au as K,av as x,aw as T,ax as $,ay as j,az as U,aA as z,aB as q,aC as _,aD as H,aE as J,aF as N,p as i,m as O,aG as V,aH as X,aI as Y,aJ as Z,aK as ee,aL as te,aM as ae,aN as se,i as ne}from"./index-C4ZGOKQv.js";function n(){if(!window.desktop)throw new Error("Desktop APIs are unavailable in the browser build");return window.desktop}const re={getRuntimeStatus:()=>n().getRuntimeStatus(),startService:()=>n().startService(),stopService:()=>n().stopService(),restartService:()=>n().restartService(),getLogs:e=>n().getLogs(e),listInstalledAgentRuntimes:()=>_().then(e=>e.runtimes),refreshInstalledAgentRuntimes:()=>q().then(e=>e.runtimes),readConfigFile:()=>n().readConfigFile(),saveRawConfigFile:e=>n().saveRawConfigFile(e),saveStructuredConfigFile:e=>n().saveStructuredConfigFile(e),listModelProviders:()=>z(),createModelProvider:e=>U(e),updateModelProvider:(e,t)=>j(e,t),deleteModelProvider:e=>$(e),getThreadKnowledgeBases:(e,t)=>n().getThreadKnowledgeBases(e,t),updateThreadKnowledgeBases:(e,t,a)=>n().updateThreadKnowledgeBases(e,t,a),deleteThreadKnowledgeBases:(e,t)=>n().deleteThreadKnowledgeBases(e,t),saveSettings:e=>n().saveSettings(e),getCapabilitySnapshot:()=>T(),getPluginDiagnostics:()=>x(),listDiagnosticErrors:()=>K().then(e=>e.errors),runDiagnosticsDoctor:()=>W(),runDeploymentDiagnostics:()=>I(),listChannelGateways:e=>F(e).then(t=>t.gateways),getChannelGatewayStatus:(e,t,a)=>A(e,t,a),testChannelConnection:(e,t,a)=>B(e,t,a),enableChannelGateway:(e,t,a)=>M(e,t,a),disableChannelGateway:(e,t,a)=>E(e,t,a),listChannelPendingPairings:(e,t)=>Q(e,t).then(a=>a.pairings),approveChannelPairing:(e,t)=>G(e,t),rejectChannelPairing:(e,t)=>b(e,t),listChannelAuthorizedUsers:(e,t)=>f(e,t).then(a=>a.users),getChannelQrCode:(e,t,a)=>R(e,t,a),checkChannelQrCodeStatus:(e,t,a,r)=>D(e,t,a,r),getWeixinQrCode:(e,t)=>y(e,t),checkWeixinQrCodeStatus:(e,t,a)=>L(e,t,a),getLarkQrCode:(e,t)=>m(e,t),checkLarkQrCodeStatus:(e,t,a)=>P(e,t,a),listLarkGateways:()=>S().then(e=>e.gateways),getLarkGatewayStatus:(e,t)=>w(e,t),testLarkConnection:(e,t)=>p(e,t),enableLarkGateway:(e,t)=>k(e,t),disableLarkGateway:(e,t)=>v(e,t),listLarkPendingPairings:e=>C(e).then(t=>t.pairings),approveLarkPairing:e=>h(e),rejectLarkPairing:e=>u(e),listLarkAuthorizedUsers:e=>c(e).then(t=>t.users),probeWorkspaceStreaming:e=>n().probeWorkspaceStreaming(e),onRuntimeEvent:e=>n().onRuntimeEvent(e),onRuntimeDetectionEvent:e=>g(t=>{(t.type.startsWith("runtime.detect.")||t.type==="runtime.status.changed")&&e(t)}),onBridgeEvent:e=>l(e)},o={getRuntimeStatus:()=>se(),startService:()=>ae(),stopService:()=>te(),restartService:()=>ee(),getLogs:e=>Z(e),listInstalledAgentRuntimes:()=>_().then(e=>e.runtimes),refreshInstalledAgentRuntimes:()=>q().then(e=>e.runtimes),readConfigFile:()=>Y(),saveRawConfigFile:e=>X(e),saveStructuredConfigFile:e=>V(e),listModelProviders:()=>z(),createModelProvider:e=>U(e),updateModelProvider:(e,t)=>j(e,t),deleteModelProvider:e=>$(e),getThreadKnowledgeBases:(e,t)=>O(t).then(a=>a.selectedKnowledgeBaseIds||[]),updateThreadKnowledgeBases:(e,t,a)=>i(t,a).then(r=>r.knowledgeBaseIds),deleteThreadKnowledgeBases:(e,t)=>i(t,[]).then(()=>({deleted:!0})),saveSettings:e=>N(e),getCapabilitySnapshot:()=>T(),getPluginDiagnostics:()=>x(),listDiagnosticErrors:()=>K().then(e=>e.errors),runDiagnosticsDoctor:()=>W(),runDeploymentDiagnostics:()=>I(),listChannelGateways:e=>F(e).then(t=>t.gateways),getChannelGatewayStatus:(e,t,a)=>A(e,t,a),testChannelConnection:(e,t,a)=>B(e,t,a),enableChannelGateway:(e,t,a)=>M(e,t,a),disableChannelGateway:(e,t,a)=>E(e,t,a),listChannelPendingPairings:(e,t)=>Q(e,t).then(a=>a.pairings),approveChannelPairing:(e,t)=>G(e,t),rejectChannelPairing:(e,t)=>b(e,t),listChannelAuthorizedUsers:(e,t)=>f(e,t).then(a=>a.users),getChannelQrCode:(e,t,a)=>R(e,t,a),checkChannelQrCodeStatus:(e,t,a,r)=>D(e,t,a,r),getWeixinQrCode:(e,t)=>y(e,t),checkWeixinQrCodeStatus:(e,t,a)=>L(e,t,a),getLarkQrCode:(e,t)=>m(e,t),checkLarkQrCodeStatus:(e,t,a)=>P(e,t,a),listLarkGateways:()=>S().then(e=>e.gateways),getLarkGatewayStatus:(e,t)=>w(e,t),testLarkConnection:(e,t)=>p(e,t),enableLarkGateway:(e,t)=>k(e,t),disableLarkGateway:(e,t)=>v(e,t),listLarkPendingPairings:e=>C(e).then(t=>t.pairings),approveLarkPairing:e=>h(e),rejectLarkPairing:e=>u(e),listLarkAuthorizedUsers:e=>c(e).then(t=>t.users),probeWorkspaceStreaming:e=>J(e),onRuntimeEvent:e=>H(e),onRuntimeDetectionEvent:e=>g(t=>{(t.type.startsWith("runtime.detect.")||t.type==="runtime.status.changed")&&e(t)}),onBridgeEvent:e=>l(e)};let d=null;function ie(e){return e==="electron"&&window.desktop?re:o}function s(){const e=d||ie(ne());if(!e)throw new Error("Managed desktop APIs are unavailable in this build");return d=e,e}const de=()=>s().getRuntimeStatus(),le=()=>s().startService(),ge=()=>s().listInstalledAgentRuntimes(),ce=()=>s().refreshInstalledAgentRuntimes(),ue=()=>s().readConfigFile(),he=e=>s().saveStructuredConfigFile(e),Ce=()=>s().listModelProviders(),ve=e=>s().createModelProvider(e),ke=(e,t)=>s().updateModelProvider(e,t),pe=e=>s().deleteModelProvider(e),we=(e,t,a)=>s().updateThreadKnowledgeBases(e,t,a),Se=e=>s().saveSettings(e),Pe=()=>s().getPluginDiagnostics(),me=()=>s().listDiagnosticErrors(),Le=()=>s().runDiagnosticsDoctor(),ye=(e,t)=>s().getWeixinQrCode(e,t),De=(e,t,a)=>s().checkWeixinQrCodeStatus(e,t,a),Re=(e,t)=>s().getLarkQrCode(e,t),fe=(e,t,a)=>s().checkLarkQrCodeStatus(e,t,a),be=(e,t)=>s().testLarkConnection(e,t),Ge=(e,t)=>s().enableLarkGateway(e,t),Qe=e=>s().onRuntimeEvent(e),Ee=e=>s().onRuntimeDetectionEvent(e),Me=e=>s().onBridgeEvent(e);export{Ee as a,Me as b,ue as c,Ce as d,Ge as e,he as f,de as g,ve as h,ke as i,pe as j,ye as k,ge as l,Re as m,De as n,Qe as o,fe as p,Pe as q,ce as r,le as s,be as t,we as u,me as v,Se as w,Le as x};
@@ -1 +0,0 @@
1
- import{D as t}from"./index-C4ZGOKQv.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};