@kafca/agentdock 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/renderer/assets/{Badge-C2K5apfV.js → Badge-Bn2h-Qkf.js} +1 -1
- package/dist/renderer/assets/{Chat-DI2YeVKb.js → Chat-Cgo9aneg.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-DMAr15Oi.js → ChatMarkdown-CYzHfSiR.js} +1 -1
- package/dist/renderer/assets/{Config-7rP3EuUf.js → Config-DljB2-eP.js} +1 -1
- package/dist/renderer/assets/{CronList-81QslYE8.js → CronList-DeVbiY9a.js} +1 -1
- package/dist/renderer/assets/{Dashboard-Db2T7rSZ.js → Dashboard-fSqx5sm8.js} +2 -2
- package/dist/renderer/assets/{EmptyState-BBJ3cTvB.js → EmptyState-DgqKDwlq.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-Dz_6flG3.js → KnowledgeDetail-u8s2SmPV.js} +1 -1
- package/dist/renderer/assets/{KnowledgeHome-DIh046mN.js → KnowledgeHome-BdQw8nbY.js} +1 -1
- package/dist/renderer/assets/{Logs-BXBtHJLf.js → Logs-DSbndMpy.js} +1 -1
- package/dist/renderer/assets/{Modal-BB2Av_Xs.js → Modal-0d0EmAuK.js} +1 -1
- package/dist/renderer/assets/{Page-DPSdvMgU.js → Page-CVbOH_Kh.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-C6EWGvGg.js → ProjectDetail-C91tF7uA.js} +1 -1
- package/dist/renderer/assets/{ProjectList-BBo5ygnS.js → ProjectList-D78Pc-BQ.js} +1 -1
- package/dist/renderer/assets/{Select-CNX-Tx_O.js → Select-BbKzAIuO.js} +1 -1
- package/dist/renderer/assets/{SessionChat-BIn46jqZ.js → SessionChat-BERvL5e4.js} +1 -1
- package/dist/renderer/assets/{SessionList-CZt6f1Rd.js → SessionList-Bomz335M.js} +1 -1
- package/dist/renderer/assets/ThreadChat-CLr3amU2.js +23 -0
- package/dist/renderer/assets/{Workspace-C_4tdpjX.js → Workspace-In91z4W2.js} +1 -1
- package/dist/renderer/assets/{arrow-left-cHr5wkpq.js → arrow-left-FBnVKKBl.js} +1 -1
- package/dist/renderer/assets/{book-open-4nx5C8T-.js → book-open-4_CuP6Sa.js} +1 -1
- package/dist/renderer/assets/{check-exTS-R-x.js → check-vsoVjvac.js} +1 -1
- package/dist/renderer/assets/{chevron-down-DSvxXQa0.js → chevron-down-DFpmFTJW.js} +1 -1
- package/dist/renderer/assets/{circle-DyvEovdw.js → circle-vRULegER.js} +1 -1
- package/dist/renderer/assets/desktop-BkMW-h5p.js +4 -0
- package/dist/renderer/assets/{desktop-B-KVT10D.js → desktop-ul0Tpzyc.js} +1 -1
- package/dist/renderer/assets/{funnel-DA9qVdTy.js → funnel-Gu0E_hJ_.js} +1 -1
- package/dist/renderer/assets/{heart-DuEV0ZRJ.js → heart-DsdofOHf.js} +1 -1
- package/dist/renderer/assets/{index-Biz-aexG.js → index-BD3aCyBa.js} +3 -3
- package/dist/renderer/assets/{index-BgflqkCN.js → index-pJUFobU7.js} +1 -1
- package/dist/renderer/assets/{pencil-DBDxeNmO.js → pencil-DbKmV8nD.js} +1 -1
- package/dist/renderer/assets/{play-IzlP83_7.js → play-BDMsRxSm.js} +1 -1
- package/dist/renderer/assets/{plug-CuT-qFnW.js → plug-t2dMl78-.js} +1 -1
- package/dist/renderer/assets/{plus-DEqgkn63.js → plus-BUb6zOAe.js} +1 -1
- package/dist/renderer/assets/projects-4F6D_Q8t.js +1 -0
- package/dist/renderer/assets/{save-D4sRo07y.js → save-C-_5rQdv.js} +1 -1
- package/dist/renderer/assets/{search-DbPZLuV8.js → search-R3ekHFPM.js} +1 -1
- package/dist/renderer/assets/{server-D1jUQmwN.js → server-BTuvHf5n.js} +1 -1
- package/dist/renderer/assets/{session-utils-Aife8ep2.js → session-utils-ClX6VPFG.js} +1 -1
- package/dist/renderer/assets/{sessions-DaH3H7gC.js → sessions-AFKIC-ub.js} +1 -1
- package/dist/renderer/assets/{shield-check-BGwUFWNr.js → shield-check-CqMW8CHe.js} +1 -1
- package/dist/renderer/assets/{trash-2-CIFBioBa.js → trash-2-BNLcHyUw.js} +1 -1
- package/dist/renderer/assets/{user-CnKcvHdo.js → user-BCCN8FYK.js} +1 -1
- package/dist/renderer/assets/{wifi-off-ClO53WGa.js → wifi-off-BsNsx3oX.js} +1 -1
- package/dist/renderer/index.html +1 -1
- package/dist-electron/electron/agent-runtime-detector.test.js +64 -0
- package/dist-electron/electron/architecture-docs.test.js +56 -0
- package/dist-electron/electron/channel-content.test.js +37 -0
- package/dist-electron/electron/lac-cli.test.js +297 -4
- package/dist-electron/electron/local-core-acp-content.test.js +39 -0
- package/dist-electron/electron/local-core-contracts.test.js +67 -0
- package/dist-electron/electron/local-core-refactor.test.js +789 -3
- package/dist-electron/electron/plugin-kernel.test.js +108 -0
- package/dist-electron/electron/renderer-packaging.test.js +77 -0
- package/dist-electron/electron/workspace-task-store.test.js +181 -0
- package/dist-electron/packages/contracts/src/local-core.js +110 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +67 -6
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-content.js +25 -4
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-permission-lifecycle.js +76 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-progress.js +201 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +3 -2
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +29 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +74 -46
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +112 -210
- package/dist-electron/services/local-ai-core/src/acp/local-core-slash-commands.js +60 -0
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +5 -48
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +83 -28
- package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +11 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/content.js +23 -0
- package/dist-electron/services/local-ai-core/src/channel/shared/file-utils.js +13 -1
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +31 -29
- package/dist-electron/services/local-ai-core/src/cli/lac.js +22 -17
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +1 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +9 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +221 -10
- package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +39 -9
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +1 -0
- package/dist-electron/services/local-ai-core/src/runtime/runtime-detection-service.js +1 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +439 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +208 -303
- package/dist-electron/services/local-ai-core/src/scheduler/job-id.js +15 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +30 -5
- package/dist-electron/shared/desktop.js +34 -8
- package/dist-electron/src/pages/Threads/thread-chat-message-blocks.js +187 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +58 -0
- package/dist-electron/src/pages/Threads/thread-chat-page-state.js +96 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.js +18 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +347 -0
- package/package.json +4 -2
- package/dist/renderer/assets/ThreadChat-BotD0gKQ.js +0 -23
- package/dist/renderer/assets/desktop-CVibRyAw.js +0 -4
- package/dist/renderer/assets/projects-DDtDN1rc.js +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createScheduledJobId = createScheduledJobId;
|
|
4
|
+
exports.toPublicScheduledJobId = toPublicScheduledJobId;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
function createScheduledJobId() {
|
|
7
|
+
return (0, node_crypto_1.randomUUID)().split('-')[0] || (0, node_crypto_1.randomUUID)();
|
|
8
|
+
}
|
|
9
|
+
function toPublicScheduledJobId(jobId) {
|
|
10
|
+
const normalized = jobId.startsWith('job:') ? jobId.slice(4) : jobId;
|
|
11
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(normalized)) {
|
|
12
|
+
return normalized.split('-')[0] || normalized;
|
|
13
|
+
}
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SchedulerService = void 0;
|
|
4
4
|
const node_events_1 = require("node:events");
|
|
5
|
+
const job_id_js_1 = require("./job-id.js");
|
|
5
6
|
const scheduler_run_lifecycle_js_1 = require("./scheduler-run-lifecycle.js");
|
|
6
7
|
class SchedulerService extends node_events_1.EventEmitter {
|
|
7
8
|
options;
|
|
@@ -34,7 +35,8 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
34
35
|
return this.options.store.listScheduledJobs(workspaceId);
|
|
35
36
|
}
|
|
36
37
|
getJob(jobId) {
|
|
37
|
-
|
|
38
|
+
const resolvedJobId = this.resolveJobId(jobId);
|
|
39
|
+
return resolvedJobId ? this.options.store.getScheduledJob(resolvedJobId) : undefined;
|
|
38
40
|
}
|
|
39
41
|
createJob(input) {
|
|
40
42
|
const job = this.options.store.createScheduledJob(input);
|
|
@@ -43,24 +45,47 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
43
45
|
return job;
|
|
44
46
|
}
|
|
45
47
|
updateJob(jobId, input) {
|
|
46
|
-
const job = this.options.store.updateScheduledJob(jobId, input);
|
|
48
|
+
const job = this.options.store.updateScheduledJob(this.resolveRequiredJobId(jobId), input);
|
|
47
49
|
this.emit('job', job);
|
|
48
50
|
this.options.eventBus.emit({ type: 'scheduler.job.updated', payload: job });
|
|
49
51
|
return job;
|
|
50
52
|
}
|
|
51
53
|
deleteJob(jobId) {
|
|
52
|
-
return this.options.store.deleteScheduledJob(jobId);
|
|
54
|
+
return this.options.store.deleteScheduledJob(this.resolveRequiredJobId(jobId));
|
|
53
55
|
}
|
|
54
56
|
listJobRuns(jobId) {
|
|
55
|
-
return this.options.store.listScheduledJobRuns(jobId);
|
|
57
|
+
return this.options.store.listScheduledJobRuns(this.resolveRequiredJobId(jobId));
|
|
56
58
|
}
|
|
57
59
|
async runJobNow(jobId) {
|
|
58
|
-
const
|
|
60
|
+
const resolvedJobId = this.resolveRequiredJobId(jobId);
|
|
61
|
+
const job = this.options.store.getScheduledJob(resolvedJobId);
|
|
59
62
|
if (!job) {
|
|
60
63
|
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
61
64
|
}
|
|
62
65
|
return this.executeJob(job, new Date().toISOString(), true);
|
|
63
66
|
}
|
|
67
|
+
resolveJobId(jobId) {
|
|
68
|
+
if (this.options.store.getScheduledJob(jobId)) {
|
|
69
|
+
return jobId;
|
|
70
|
+
}
|
|
71
|
+
const matches = this.options.store
|
|
72
|
+
.listScheduledJobs()
|
|
73
|
+
.filter((job) => (0, job_id_js_1.toPublicScheduledJobId)(job.id) === jobId);
|
|
74
|
+
if (matches.length === 0) {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
if (matches.length > 1) {
|
|
78
|
+
throw new Error(`Scheduled job id is ambiguous: ${jobId}`);
|
|
79
|
+
}
|
|
80
|
+
return matches[0].id;
|
|
81
|
+
}
|
|
82
|
+
resolveRequiredJobId(jobId) {
|
|
83
|
+
const resolvedJobId = this.resolveJobId(jobId);
|
|
84
|
+
if (!resolvedJobId) {
|
|
85
|
+
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
86
|
+
}
|
|
87
|
+
return resolvedJobId;
|
|
88
|
+
}
|
|
64
89
|
async tick() {
|
|
65
90
|
if (this.pollInFlight) {
|
|
66
91
|
return;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CHANNEL_PROTOCOL_INSTRUCTION = exports.SCHEDULER_PROTOCOL_INSTRUCTION = exports.LOCALCORE_ACP_AGENT_TYPE = exports.DESKTOP_INTERACTIVE_PERMISSION_AGENT_TYPES = exports.DESKTOP_PROVIDER_THINKING_OPTIONS = exports.DESKTOP_PROVIDER_PRESET_OPTIONS = exports.DESKTOP_PLATFORM_TYPE_OPTIONS = exports.DESKTOP_AGENT_TYPE_OPTIONS = exports.DESKTOP_LARK_SDK_PACKAGE = exports.DESKTOP_CLAUDECODE_ACP_PACKAGE = exports.DESKTOP_CODEX_ACP_PACKAGE = exports.DEFAULT_DESKTOP_CLAUDECODE_MODEL = exports.DEFAULT_DESKTOP_OPENCODE_MODEL = exports.DEFAULT_DESKTOP_AGENT_TYPE = void 0;
|
|
3
|
+
exports.CHANNEL_PROTOCOL_INSTRUCTION = exports.SCHEDULER_PROTOCOL_INSTRUCTION = exports.LOCALCORE_ACP_AGENT_TYPE = exports.DESKTOP_INTERACTIVE_PERMISSION_AGENT_TYPES = exports.DESKTOP_PROVIDER_THINKING_OPTIONS = exports.DESKTOP_PROVIDER_PRESET_OPTIONS = exports.DESKTOP_PLATFORM_TYPE_OPTIONS = exports.DESKTOP_AGENT_TYPE_OPTIONS = exports.DESKTOP_LARK_SDK_PACKAGE = exports.DESKTOP_CLAUDECODE_ACP_PACKAGE = exports.DESKTOP_CODEX_ACP_PACKAGE = exports.DESKTOP_PI_CODING_AGENT_PACKAGE = exports.DESKTOP_PI_ACP_PACKAGE = exports.DEFAULT_DESKTOP_CLAUDECODE_MODEL = exports.DEFAULT_DESKTOP_OPENCODE_MODEL = exports.DEFAULT_DESKTOP_AGENT_TYPE = void 0;
|
|
4
4
|
exports.deriveDesktopRuntimePhase = deriveDesktopRuntimePhase;
|
|
5
5
|
exports.deriveDesktopRuntimeRoles = deriveDesktopRuntimeRoles;
|
|
6
6
|
exports.normalizeDesktopPlatformType = normalizeDesktopPlatformType;
|
|
@@ -12,13 +12,16 @@ exports.isPermissionButtonOption = isPermissionButtonOption;
|
|
|
12
12
|
exports.normalizeDesktopBridgeButtonOption = normalizeDesktopBridgeButtonOption;
|
|
13
13
|
exports.supportsInteractivePermission = supportsInteractivePermission;
|
|
14
14
|
exports.isAcpAgentType = isAcpAgentType;
|
|
15
|
-
exports.DEFAULT_DESKTOP_AGENT_TYPE = '
|
|
15
|
+
exports.DEFAULT_DESKTOP_AGENT_TYPE = 'pi';
|
|
16
16
|
exports.DEFAULT_DESKTOP_OPENCODE_MODEL = 'opencode/minimax-m2.5-free';
|
|
17
17
|
exports.DEFAULT_DESKTOP_CLAUDECODE_MODEL = '';
|
|
18
|
+
exports.DESKTOP_PI_ACP_PACKAGE = 'pi-acp';
|
|
19
|
+
exports.DESKTOP_PI_CODING_AGENT_PACKAGE = '@mariozechner/pi-coding-agent';
|
|
18
20
|
exports.DESKTOP_CODEX_ACP_PACKAGE = '@zed-industries/codex-acp';
|
|
19
21
|
exports.DESKTOP_CLAUDECODE_ACP_PACKAGE = '@agentclientprotocol/claude-agent-acp';
|
|
20
22
|
exports.DESKTOP_LARK_SDK_PACKAGE = '@larksuiteoapi/node-sdk';
|
|
21
23
|
exports.DESKTOP_AGENT_TYPE_OPTIONS = [
|
|
24
|
+
'pi',
|
|
22
25
|
'opencode',
|
|
23
26
|
'codex',
|
|
24
27
|
'claudecode',
|
|
@@ -53,7 +56,7 @@ exports.DESKTOP_PROVIDER_PRESET_OPTIONS = [
|
|
|
53
56
|
'ollama',
|
|
54
57
|
];
|
|
55
58
|
exports.DESKTOP_PROVIDER_THINKING_OPTIONS = ['', 'enabled', 'disabled'];
|
|
56
|
-
exports.DESKTOP_INTERACTIVE_PERMISSION_AGENT_TYPES = ['opencode', 'codex', 'claudecode', 'acp', 'localcore-acp'];
|
|
59
|
+
exports.DESKTOP_INTERACTIVE_PERMISSION_AGENT_TYPES = ['pi', 'opencode', 'codex', 'claudecode', 'acp', 'localcore-acp'];
|
|
57
60
|
exports.LOCALCORE_ACP_AGENT_TYPE = 'localcore-acp';
|
|
58
61
|
exports.SCHEDULER_PROTOCOL_INSTRUCTION = [
|
|
59
62
|
'[Scheduler Tools]',
|
|
@@ -62,13 +65,14 @@ exports.SCHEDULER_PROTOCOL_INSTRUCTION = [
|
|
|
62
65
|
'lac scheduler add --cron "<5-field cron>" --message "<exact message to send>" --desc "<short label>" [--execution-mode same-thread|side-thread]',
|
|
63
66
|
'lac scheduler list',
|
|
64
67
|
'lac scheduler list --thread',
|
|
65
|
-
'lac scheduler info <job-id>',
|
|
66
|
-
'lac scheduler edit <job-id> [--cron "<5-field cron>"] [--message "<exact message>"] [--desc "<short label>"] [--enabled true|false] [--execution-mode same-thread|side-thread]',
|
|
67
|
-
'lac scheduler del <job-id>',
|
|
68
|
-
'lac scheduler run <job-id>',
|
|
68
|
+
'lac scheduler info <short-job-id>',
|
|
69
|
+
'lac scheduler edit <short-job-id> [--cron "<5-field cron>"] [--message "<exact message>"] [--desc "<short label>"] [--enabled true|false] [--execution-mode same-thread|side-thread]',
|
|
70
|
+
'lac scheduler del <short-job-id>',
|
|
71
|
+
'lac scheduler run <short-job-id>',
|
|
69
72
|
'Environment variables LOCAL_AI_WORKSPACE_ID, LOCAL_AI_THREAD_ID, LOCAL_AI_PLATFORM, LOCAL_AI_CHAT_ID, and LOCAL_AI_PLATFORM_USER_ID are already set when available.',
|
|
70
73
|
'Prefer relying on those variables instead of inventing your own route or creating session-only cron jobs.',
|
|
71
74
|
'By default, `lac scheduler list` shows all scheduled tasks in the current workspace. Use `lac scheduler list --thread` to show only the current conversation thread.',
|
|
75
|
+
'Use the short job id shown by `lac scheduler list`; do not add a `job:` prefix or expand it to a full UUID.',
|
|
72
76
|
'Use `--execution-mode same-thread` to reuse the current thread, or `--execution-mode side-thread` to run in a dedicated scheduled thread.',
|
|
73
77
|
'Only use the scheduler CLI when the user explicitly asks for scheduled automation.',
|
|
74
78
|
'[/Scheduler Tools]',
|
|
@@ -169,7 +173,28 @@ function normalizePermissionResponse(input) {
|
|
|
169
173
|
if (!input) {
|
|
170
174
|
return null;
|
|
171
175
|
}
|
|
172
|
-
|
|
176
|
+
const normalized = String(input).trim().toLowerCase();
|
|
177
|
+
const mapped = PERMISSION_RESPONSE_MAP[normalized];
|
|
178
|
+
if (mapped) {
|
|
179
|
+
return mapped;
|
|
180
|
+
}
|
|
181
|
+
if (normalized.includes('allow_all') ||
|
|
182
|
+
normalized.includes('allow-always') ||
|
|
183
|
+
normalized.includes('allow_always') ||
|
|
184
|
+
normalized.includes('allow always') ||
|
|
185
|
+
normalized.includes('always allow') ||
|
|
186
|
+
normalized.includes('allow all') ||
|
|
187
|
+
normalized.includes('始终允许') ||
|
|
188
|
+
normalized.includes('永久允许')) {
|
|
189
|
+
return 'allow all';
|
|
190
|
+
}
|
|
191
|
+
if (normalized.startsWith('reject') || normalized.startsWith('deny')) {
|
|
192
|
+
return 'deny';
|
|
193
|
+
}
|
|
194
|
+
if (normalized.startsWith('allow')) {
|
|
195
|
+
return 'allow';
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
173
198
|
}
|
|
174
199
|
function isPermissionButtonOption(option) {
|
|
175
200
|
return Boolean(normalizePermissionResponse(option?.data));
|
|
@@ -213,6 +238,7 @@ function supportsInteractivePermission(agentType) {
|
|
|
213
238
|
function isAcpAgentType(agentType) {
|
|
214
239
|
const normalized = String(agentType || '').trim().toLowerCase();
|
|
215
240
|
return normalized === 'acp'
|
|
241
|
+
|| normalized === 'pi'
|
|
216
242
|
|| normalized === 'opencode'
|
|
217
243
|
|| normalized === 'codex'
|
|
218
244
|
|| normalized === 'claudecode'
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInteractivePermissionMessage = isInteractivePermissionMessage;
|
|
4
|
+
exports.parseToolResultCard = parseToolResultCard;
|
|
5
|
+
exports.toolCallToResultCard = toolCallToResultCard;
|
|
6
|
+
exports.isEmptyRunningToolUpdateContent = isEmptyRunningToolUpdateContent;
|
|
7
|
+
exports.isHiddenProgressMessage = isHiddenProgressMessage;
|
|
8
|
+
exports.shouldCollapseToolResultByDefault = shouldCollapseToolResultByDefault;
|
|
9
|
+
exports.parsePermissionCardContent = parsePermissionCardContent;
|
|
10
|
+
const thread_chat_permission_1 = require("./thread-chat-permission");
|
|
11
|
+
function isInteractivePermissionMessage(message, pendingPermissionRequest) {
|
|
12
|
+
if (message.role === 'system') {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return (0, thread_chat_permission_1.isStructuredPermissionMessage)({
|
|
16
|
+
id: message.id,
|
|
17
|
+
role: message.role,
|
|
18
|
+
actionMode: message.actionMode,
|
|
19
|
+
actionInteractive: message.actionInteractive,
|
|
20
|
+
}, pendingPermissionRequest);
|
|
21
|
+
}
|
|
22
|
+
function parseToolResultCard(content) {
|
|
23
|
+
const statusFirstMatch = content.match(/^\s*🔧\s*(.+?)\s*:\s*(running|completed|failed|error|cancelled|canceled)(?:\s*-\s*([\s\S]+?))?\s*$/i);
|
|
24
|
+
if (statusFirstMatch) {
|
|
25
|
+
const [, toolName, status, payload = ''] = statusFirstMatch;
|
|
26
|
+
return {
|
|
27
|
+
title: toolName.trim() || 'Tool call',
|
|
28
|
+
status: status.trim(),
|
|
29
|
+
output: parseToolResultPayload(payload),
|
|
30
|
+
label: /^running$/i.test(status) ? '工具调用' : '工具结果',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const namedStatusMatch = content.match(/^\s*🔧\s*(.+?)\s*:\s*([\s\S]*?)\s*-\s*(running|completed|failed|error|cancelled|canceled)(?:\s*-\s*([\s\S]+?))?\s*$/i);
|
|
34
|
+
if (namedStatusMatch) {
|
|
35
|
+
const [, toolName, detail, status, payload = ''] = namedStatusMatch;
|
|
36
|
+
const trimmedDetail = detail.trim();
|
|
37
|
+
return {
|
|
38
|
+
title: toolName.trim() || 'Tool call',
|
|
39
|
+
status: status.trim(),
|
|
40
|
+
output: parseToolResultPayload(payload),
|
|
41
|
+
label: /^running$/i.test(status) ? '工具调用' : '工具结果',
|
|
42
|
+
subtitle: trimmedDetail || undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const namedUpdateMatch = content.match(/^\s*🔧\s*(.+?)\s*:\s*(Tool update)\s*-\s*([^-]+?)\s*-\s*([\s\S]+?)\s*$/i);
|
|
46
|
+
if (namedUpdateMatch) {
|
|
47
|
+
const [, toolName, updateTitle, status, payload] = namedUpdateMatch;
|
|
48
|
+
const trimmedPayload = payload.trim();
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(trimmedPayload);
|
|
51
|
+
const value = typeof parsed.output === 'string'
|
|
52
|
+
? parsed.output
|
|
53
|
+
: parsed.output ?? parsed.error ?? parsed;
|
|
54
|
+
return {
|
|
55
|
+
title: toolName.trim() || updateTitle,
|
|
56
|
+
status: status.trim(),
|
|
57
|
+
output: typeof value === 'string' ? value : JSON.stringify(value, null, 2),
|
|
58
|
+
label: '工具结果',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return {
|
|
63
|
+
title: toolName.trim() || updateTitle,
|
|
64
|
+
status: status.trim(),
|
|
65
|
+
output: trimmedPayload,
|
|
66
|
+
label: '工具结果',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const updateMatch = content.match(/^\s*(?:🔧\s*)?(Tool update)\s*-\s*([^-]+?)\s*-\s*([\s\S]+?)\s*$/i);
|
|
71
|
+
if (updateMatch) {
|
|
72
|
+
const [, title, status, payload] = updateMatch;
|
|
73
|
+
const trimmedPayload = payload.trim();
|
|
74
|
+
if (isEmptyRunningToolUpdateContent(title, status.trim(), trimmedPayload)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(trimmedPayload);
|
|
79
|
+
const value = typeof parsed.output === 'string'
|
|
80
|
+
? parsed.output
|
|
81
|
+
: parsed.output ?? parsed.error ?? parsed;
|
|
82
|
+
return {
|
|
83
|
+
title,
|
|
84
|
+
status: status.trim(),
|
|
85
|
+
output: typeof value === 'string' ? value : JSON.stringify(value, null, 2),
|
|
86
|
+
label: '工具结果',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return {
|
|
91
|
+
title,
|
|
92
|
+
status: status.trim(),
|
|
93
|
+
output: trimmedPayload,
|
|
94
|
+
label: '工具结果',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const callMatch = content.match(/^\s*🔧\s*(.+?)\s*$/);
|
|
99
|
+
if (callMatch) {
|
|
100
|
+
const rawTitle = callMatch[1].trim();
|
|
101
|
+
if (/^Tool update\s*-\s*running(?:\s*-\s*)?$/i.test(rawTitle)) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const [name, ...rest] = rawTitle.split(':');
|
|
105
|
+
const output = rest.join(':').trim();
|
|
106
|
+
const statusMatch = output.match(/^(.*?)\s*-\s*(running|completed|failed|error|cancelled|canceled)\s*$/i);
|
|
107
|
+
return {
|
|
108
|
+
title: name.trim() || 'Tool call',
|
|
109
|
+
status: statusMatch?.[2]?.trim() || 'running',
|
|
110
|
+
output: statusMatch?.[1]?.trim() || output,
|
|
111
|
+
label: statusMatch && !/^running$/i.test(statusMatch[2]) ? '工具结果' : '工具调用',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function toolCallToResultCard(toolCall) {
|
|
117
|
+
if (!toolCall) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const status = toolCall.status.trim() || 'running';
|
|
121
|
+
return {
|
|
122
|
+
title: toolCall.name.trim() || 'Tool call',
|
|
123
|
+
status,
|
|
124
|
+
output: toolCall.output || '',
|
|
125
|
+
label: toolCall.label || (/^running$/i.test(status) ? '工具调用' : '工具结果'),
|
|
126
|
+
subtitle: toolCall.detail?.trim() || summarizeToolCallInput(toolCall.input),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function summarizeToolCallInput(input) {
|
|
130
|
+
if (!input || typeof input !== 'object') {
|
|
131
|
+
return typeof input === 'string' && input.trim() ? input.trim() : undefined;
|
|
132
|
+
}
|
|
133
|
+
const record = input;
|
|
134
|
+
for (const key of ['command', 'cmd', 'path', 'file', 'query']) {
|
|
135
|
+
const value = record[key];
|
|
136
|
+
if (typeof value === 'string' && value.trim()) {
|
|
137
|
+
return value.trim();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const entries = Object.entries(record)
|
|
141
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
142
|
+
.slice(0, 2)
|
|
143
|
+
.map(([key, value]) => `${key}: ${typeof value === 'string' ? value : JSON.stringify(value)}`);
|
|
144
|
+
return entries.length > 0 ? entries.join(', ') : undefined;
|
|
145
|
+
}
|
|
146
|
+
function parseToolResultPayload(payload) {
|
|
147
|
+
const trimmedPayload = payload.trim();
|
|
148
|
+
if (!trimmedPayload) {
|
|
149
|
+
return '';
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const parsed = JSON.parse(trimmedPayload);
|
|
153
|
+
const value = typeof parsed.output === 'string'
|
|
154
|
+
? parsed.output
|
|
155
|
+
: parsed.output ?? parsed.error ?? parsed;
|
|
156
|
+
return typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return trimmedPayload;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function isEmptyRunningToolUpdateContent(title, status, payload) {
|
|
163
|
+
return /^Tool update$/i.test(title.trim()) && /^running$/i.test(status.trim()) && !payload.trim();
|
|
164
|
+
}
|
|
165
|
+
function isHiddenProgressMessage(content) {
|
|
166
|
+
const normalized = content.trim();
|
|
167
|
+
return /^🔧\s*Tool update\s*-\s*running(?:\s*-\s*)?$/i.test(normalized);
|
|
168
|
+
}
|
|
169
|
+
function shouldCollapseToolResultByDefault(card) {
|
|
170
|
+
return card.label === '工具结果' && Boolean(card.output.trim());
|
|
171
|
+
}
|
|
172
|
+
function parsePermissionCardContent(content) {
|
|
173
|
+
const lines = content
|
|
174
|
+
.split('\n')
|
|
175
|
+
.map((line) => line.trim())
|
|
176
|
+
.filter(Boolean);
|
|
177
|
+
const fallbackIndex = lines.findIndex((line) => line.includes('若按钮没有显示'));
|
|
178
|
+
const visibleLines = fallbackIndex >= 0 ? lines.slice(0, fallbackIndex) : lines;
|
|
179
|
+
const title = visibleLines[0] || '等待工具确认';
|
|
180
|
+
const bodyLines = visibleLines
|
|
181
|
+
.slice(1)
|
|
182
|
+
.filter((line) => !line.includes('请选择一个选项继续执行'));
|
|
183
|
+
return {
|
|
184
|
+
title,
|
|
185
|
+
bodyLines,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
@@ -5,6 +5,9 @@ exports.isInternalProgressMessage = isInternalProgressMessage;
|
|
|
5
5
|
exports.isAwaitingInputMessage = isAwaitingInputMessage;
|
|
6
6
|
exports.findStreamingPreviewMessage = findStreamingPreviewMessage;
|
|
7
7
|
exports.shouldReplacePreviewWithReply = shouldReplacePreviewWithReply;
|
|
8
|
+
exports.advancePreviewContent = advancePreviewContent;
|
|
9
|
+
exports.settlePreviewMessages = settlePreviewMessages;
|
|
10
|
+
exports.finalizeTurnMessageKinds = finalizeTurnMessageKinds;
|
|
8
11
|
exports.extractVisibleMessageContent = extractVisibleMessageContent;
|
|
9
12
|
exports.sessionMatchesDesktop = sessionMatchesDesktop;
|
|
10
13
|
exports.toMessages = toMessages;
|
|
@@ -65,6 +68,60 @@ function shouldReplacePreviewWithReply(message, replyContent, replyCtx) {
|
|
|
65
68
|
const content = message.streamTargetContent ?? message.content;
|
|
66
69
|
return Boolean(replyContent && content === replyContent && !isInternalProgressMessage(content));
|
|
67
70
|
}
|
|
71
|
+
function advancePreviewContent(content, target) {
|
|
72
|
+
if (!target) {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
if (!content || !target.startsWith(content)) {
|
|
76
|
+
return target.slice(0, Math.min(target.length, Math.max(1, Math.ceil(target.length / 24))));
|
|
77
|
+
}
|
|
78
|
+
if (content === target) {
|
|
79
|
+
return target;
|
|
80
|
+
}
|
|
81
|
+
const remaining = target.length - content.length;
|
|
82
|
+
const step = remaining > 160 ? 14 : remaining > 80 ? 8 : remaining > 24 ? 4 : 2;
|
|
83
|
+
return target.slice(0, Math.min(target.length, content.length + step));
|
|
84
|
+
}
|
|
85
|
+
function settlePreviewMessages(messages, turnKey) {
|
|
86
|
+
let changed = false;
|
|
87
|
+
const next = messages.map((message) => {
|
|
88
|
+
if (!message.preview) {
|
|
89
|
+
return message;
|
|
90
|
+
}
|
|
91
|
+
if (turnKey && message.turnKey !== turnKey) {
|
|
92
|
+
return message;
|
|
93
|
+
}
|
|
94
|
+
changed = true;
|
|
95
|
+
return {
|
|
96
|
+
...message,
|
|
97
|
+
content: message.streamTargetContent ?? message.content,
|
|
98
|
+
streamTargetContent: undefined,
|
|
99
|
+
preview: false,
|
|
100
|
+
previewPlainText: false,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
return changed ? next : messages;
|
|
104
|
+
}
|
|
105
|
+
function finalizeTurnMessageKinds(messages, turnKey) {
|
|
106
|
+
if (!turnKey) {
|
|
107
|
+
return messages;
|
|
108
|
+
}
|
|
109
|
+
const candidates = messages.filter((message) => message.turnKey === turnKey && !message.preview);
|
|
110
|
+
if (candidates.length === 0) {
|
|
111
|
+
return messages;
|
|
112
|
+
}
|
|
113
|
+
const finalMessage = [...candidates].reverse().find((message) => !isInternalProgressMessage(message.content));
|
|
114
|
+
const finalId = finalMessage?.id;
|
|
115
|
+
return messages.map((message) => {
|
|
116
|
+
if (message.turnKey !== turnKey || message.preview) {
|
|
117
|
+
return message;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
...message,
|
|
121
|
+
kind: finalId && message.id === finalId ? 'final' : 'progress',
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
68
125
|
function extractVisibleMessageContent(content) {
|
|
69
126
|
if (!content) {
|
|
70
127
|
return '';
|
|
@@ -93,6 +150,7 @@ function toMessagesFromThread(history) {
|
|
|
93
150
|
id: message.id || `${index}-${message.timestamp || message.role}`,
|
|
94
151
|
role: message.role === 'user' ? 'user' : message.role === 'system' ? 'system' : 'assistant',
|
|
95
152
|
content: message.role === 'user' ? extractVisibleMessageContent(message.content) : message.content,
|
|
153
|
+
toolCall: message.toolCall,
|
|
96
154
|
kind: message.kind === 'progress'
|
|
97
155
|
? 'progress'
|
|
98
156
|
: message.kind === 'system'
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toSelectedKnowledgeBases = toSelectedKnowledgeBases;
|
|
4
|
+
exports.filterKnowledgeBases = filterKnowledgeBases;
|
|
5
|
+
exports.orderKnowledgeBases = orderKnowledgeBases;
|
|
6
|
+
exports.getVisibleSessionGroups = getVisibleSessionGroups;
|
|
7
|
+
exports.getVisibleProjects = getVisibleProjects;
|
|
8
|
+
exports.hasVisibleSessions = hasVisibleSessions;
|
|
9
|
+
exports.toComposerPermissionCard = toComposerPermissionCard;
|
|
10
|
+
exports.shouldRenderThreadChatMessage = shouldRenderThreadChatMessage;
|
|
11
|
+
exports.getComposerPlaceholder = getComposerPlaceholder;
|
|
12
|
+
exports.canSubmitComposer = canSubmitComposer;
|
|
13
|
+
const thread_chat_message_blocks_1 = require("./thread-chat-message-blocks");
|
|
14
|
+
function toSelectedKnowledgeBases(knowledgeBaseIds, availableKnowledgeBases) {
|
|
15
|
+
return knowledgeBaseIds.map((knowledgeBaseId) => {
|
|
16
|
+
const matched = availableKnowledgeBases.find((base) => base.id === knowledgeBaseId);
|
|
17
|
+
return {
|
|
18
|
+
id: knowledgeBaseId,
|
|
19
|
+
name: matched?.name || knowledgeBaseId,
|
|
20
|
+
fileCount: matched?.fileCount || 0,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function filterKnowledgeBases(knowledgeBases, search) {
|
|
25
|
+
const query = search.trim().toLowerCase();
|
|
26
|
+
if (!query) {
|
|
27
|
+
return knowledgeBases;
|
|
28
|
+
}
|
|
29
|
+
return knowledgeBases.filter((base) => [base.name, base.description, base.id].join(' ').toLowerCase().includes(query));
|
|
30
|
+
}
|
|
31
|
+
function orderKnowledgeBases(knowledgeBases, selectedKnowledgeBaseIds) {
|
|
32
|
+
const selectedIds = new Set(selectedKnowledgeBaseIds);
|
|
33
|
+
return [...knowledgeBases].sort((a, b) => {
|
|
34
|
+
const aSelected = selectedIds.has(a.id);
|
|
35
|
+
const bSelected = selectedIds.has(b.id);
|
|
36
|
+
if (aSelected !== bSelected) {
|
|
37
|
+
return aSelected ? -1 : 1;
|
|
38
|
+
}
|
|
39
|
+
return a.name.localeCompare(b.name, 'zh-CN');
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function getVisibleSessionGroups(sessionGroups, selectedProject) {
|
|
43
|
+
if (!selectedProject) {
|
|
44
|
+
return sessionGroups;
|
|
45
|
+
}
|
|
46
|
+
return sessionGroups.filter((group) => group.project === selectedProject);
|
|
47
|
+
}
|
|
48
|
+
function getVisibleProjects(projects, selectedProject) {
|
|
49
|
+
return selectedProject && !projects.includes(selectedProject) ? [selectedProject, ...projects] : projects;
|
|
50
|
+
}
|
|
51
|
+
function hasVisibleSessions(sessionGroups) {
|
|
52
|
+
return sessionGroups.some((group) => group.sessions.length > 0);
|
|
53
|
+
}
|
|
54
|
+
function toComposerPermissionCard(pendingPermissionRequest) {
|
|
55
|
+
if (!pendingPermissionRequest) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
id: pendingPermissionRequest.id,
|
|
60
|
+
content: pendingPermissionRequest.content,
|
|
61
|
+
actions: pendingPermissionRequest.actions,
|
|
62
|
+
actionReplyCtx: pendingPermissionRequest.actionReplyCtx,
|
|
63
|
+
actionPending: pendingPermissionRequest.actionPending,
|
|
64
|
+
actionStatus: pendingPermissionRequest.actionStatus,
|
|
65
|
+
actionMode: 'permission',
|
|
66
|
+
actionInteractive: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function shouldRenderThreadChatMessage(message, composerPermissionCard) {
|
|
70
|
+
if (message.kind === 'progress' && (0, thread_chat_message_blocks_1.isHiddenProgressMessage)(message.content)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return !(0, thread_chat_message_blocks_1.isInteractivePermissionMessage)(message, composerPermissionCard);
|
|
74
|
+
}
|
|
75
|
+
function getComposerPlaceholder(input) {
|
|
76
|
+
if (!input.serviceRunning) {
|
|
77
|
+
return input.startFirstPlaceholder;
|
|
78
|
+
}
|
|
79
|
+
if (!input.transportReady) {
|
|
80
|
+
return input.waitingRuntimePlaceholder;
|
|
81
|
+
}
|
|
82
|
+
if (input.taskState === 'awaiting_input') {
|
|
83
|
+
return 'Agent 正在等待你的回复,可直接继续输入。';
|
|
84
|
+
}
|
|
85
|
+
if (input.taskInputLocked) {
|
|
86
|
+
return '任务正在运行,点击停止可中断当前执行。';
|
|
87
|
+
}
|
|
88
|
+
return input.sendPlaceholder;
|
|
89
|
+
}
|
|
90
|
+
function canSubmitComposer(input) {
|
|
91
|
+
return Boolean(input.draft.trim() &&
|
|
92
|
+
input.serviceRunning &&
|
|
93
|
+
input.transportReady &&
|
|
94
|
+
!input.sending &&
|
|
95
|
+
input.selectedProject);
|
|
96
|
+
}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.permissionSubmittedStatus = void 0;
|
|
3
4
|
exports.shouldEchoBridgeActionResponse = shouldEchoBridgeActionResponse;
|
|
5
|
+
exports.isStructuredPermissionMessage = isStructuredPermissionMessage;
|
|
4
6
|
exports.toPendingPermissionRequest = toPendingPermissionRequest;
|
|
7
|
+
exports.markPermissionMessageSubmitted = markPermissionMessageSubmitted;
|
|
8
|
+
exports.permissionSubmittedStatus = 'Permission sent. Waiting for the agent to continue…';
|
|
5
9
|
function shouldEchoBridgeActionResponse(message) {
|
|
6
10
|
return !(message.actionMode === 'permission' && message.actionInteractive);
|
|
7
11
|
}
|
|
12
|
+
function isStructuredPermissionMessage(message, pendingPermissionRequest) {
|
|
13
|
+
if (pendingPermissionRequest?.id === message.id) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return message.role !== 'user' && message.actionMode === 'permission' && Boolean(message.actionInteractive);
|
|
17
|
+
}
|
|
8
18
|
function toPendingPermissionRequest(message) {
|
|
9
19
|
if (!message.id ||
|
|
10
20
|
message.role !== 'assistant' ||
|
|
@@ -28,3 +38,11 @@ function toPendingPermissionRequest(message) {
|
|
|
28
38
|
actionInteractive: true,
|
|
29
39
|
};
|
|
30
40
|
}
|
|
41
|
+
function markPermissionMessageSubmitted(message) {
|
|
42
|
+
return {
|
|
43
|
+
...message,
|
|
44
|
+
actions: [],
|
|
45
|
+
actionPending: false,
|
|
46
|
+
actionStatus: exports.permissionSubmittedStatus,
|
|
47
|
+
};
|
|
48
|
+
}
|