ec-web 0.0.9 → 0.0.11
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/dist/ipc-client.js +16 -1
- package/dist/sources/session-codex.js +17 -2
- package/dist/static/app.js +24 -2
- package/dist/static/index.html +1 -1
- package/dist/static/style.css +11 -0
- package/package.json +1 -1
package/dist/ipc-client.js
CHANGED
|
@@ -7,7 +7,22 @@
|
|
|
7
7
|
* watch 用到的只读查询:aun-aids / aun-aid-stats / status / evolagent.list / ping
|
|
8
8
|
*/
|
|
9
9
|
import net from 'net';
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
const LOCAL_CONTROL_COMMANDS = new Set(['menu.exec', 'monitor-snapshot']);
|
|
10
13
|
export function ipcQuery(socketPath, cmd, timeoutMs = 3000) {
|
|
14
|
+
let request = cmd;
|
|
15
|
+
if (LOCAL_CONTROL_COMMANDS.has(cmd.type) && typeof cmd.controlToken !== 'string') {
|
|
16
|
+
try {
|
|
17
|
+
const tokenPath = process.platform === 'win32'
|
|
18
|
+
? path.join(process.env.EVOLCORE_HOME || '', 'data', 'instance', 'control.token')
|
|
19
|
+
: path.join(path.dirname(socketPath), 'control.token');
|
|
20
|
+
const controlToken = fs.readFileSync(tokenPath, 'utf8').trim();
|
|
21
|
+
if (controlToken)
|
|
22
|
+
request = { ...cmd, controlToken };
|
|
23
|
+
}
|
|
24
|
+
catch { }
|
|
25
|
+
}
|
|
11
26
|
return new Promise((resolve) => {
|
|
12
27
|
const conn = net.connect(socketPath);
|
|
13
28
|
let buf = '';
|
|
@@ -16,7 +31,7 @@ export function ipcQuery(socketPath, cmd, timeoutMs = 3000) {
|
|
|
16
31
|
resolve(null);
|
|
17
32
|
}, timeoutMs);
|
|
18
33
|
conn.on('connect', () => {
|
|
19
|
-
conn.write(JSON.stringify(
|
|
34
|
+
conn.write(JSON.stringify(request) + '\n');
|
|
20
35
|
});
|
|
21
36
|
conn.on('data', (data) => {
|
|
22
37
|
buf += data.toString();
|
|
@@ -430,6 +430,18 @@ function toolOutputText(output) {
|
|
|
430
430
|
return String(output);
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
|
+
function classifyCodexToolRejection(text) {
|
|
434
|
+
const normalized = text.replace(/\\(["'])/g, '$1');
|
|
435
|
+
if (!/Rejected\(\s*["']rejected by user["']\s*\)/i.test(normalized))
|
|
436
|
+
return undefined;
|
|
437
|
+
const isManagedEcSend = /(?:^|[/'\s])ec\s+(?:msg|group)\s+send\b/i.test(text);
|
|
438
|
+
return {
|
|
439
|
+
kind: 'approval_rejected',
|
|
440
|
+
source: isManagedEcSend ? 'evolcore-policy' : 'codex-approval',
|
|
441
|
+
reason: 'rejected_by_user',
|
|
442
|
+
executed: false,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
433
445
|
export function parseCodexToolEvent(event) {
|
|
434
446
|
if (!event || (event.type !== 'event_msg' && event.type !== 'response_item') || !event.payload)
|
|
435
447
|
return null;
|
|
@@ -457,6 +469,8 @@ export function parseCodexToolEvent(event) {
|
|
|
457
469
|
};
|
|
458
470
|
}
|
|
459
471
|
if (payload.type === 'function_call_output' || payload.type === 'custom_tool_call_output') {
|
|
472
|
+
const text = toolOutputText(payload.output);
|
|
473
|
+
const rejection = classifyCodexToolRejection(text);
|
|
460
474
|
return {
|
|
461
475
|
kind: 'result',
|
|
462
476
|
callId,
|
|
@@ -467,8 +481,9 @@ export function parseCodexToolEvent(event) {
|
|
|
467
481
|
category: 'tool_result',
|
|
468
482
|
blocks: [{
|
|
469
483
|
kind: 'tool_result',
|
|
470
|
-
text
|
|
471
|
-
isError: payload.is_error === true || payload.status === 'failed',
|
|
484
|
+
text,
|
|
485
|
+
isError: payload.is_error === true || payload.status === 'failed' || !!rejection,
|
|
486
|
+
...(rejection ? { rejection } : {}),
|
|
472
487
|
}],
|
|
473
488
|
},
|
|
474
489
|
};
|
package/dist/static/app.js
CHANGED
|
@@ -342,6 +342,11 @@ const translations = {
|
|
|
342
342
|
'sessions.block.thinking': '思考',
|
|
343
343
|
'sessions.block.result': '结果',
|
|
344
344
|
'sessions.block.resultError': '结果',
|
|
345
|
+
'sessions.block.rejection.title': '已拦截',
|
|
346
|
+
'sessions.block.rejection.source.policy': 'EvolCore 策略自动拦截',
|
|
347
|
+
'sessions.block.rejection.source.approval': '审批通道拒绝',
|
|
348
|
+
'sessions.block.rejection.notExecuted': '命令未执行',
|
|
349
|
+
'sessions.block.rejection.reason': '底层返回:Rejected("rejected by user")',
|
|
345
350
|
'sessions.content.expand': '展开内容',
|
|
346
351
|
'sessions.content.collapse': '收起内容',
|
|
347
352
|
'sessions.contextTitle': '最后一轮喂给模型的完整上下文大小',
|
|
@@ -1230,6 +1235,11 @@ const translations = {
|
|
|
1230
1235
|
'sessions.block.thinking': 'Thinking',
|
|
1231
1236
|
'sessions.block.result': 'Result',
|
|
1232
1237
|
'sessions.block.resultError': 'Result',
|
|
1238
|
+
'sessions.block.rejection.title': 'Intercepted',
|
|
1239
|
+
'sessions.block.rejection.source.policy': 'EvolCore policy auto-blocked',
|
|
1240
|
+
'sessions.block.rejection.source.approval': 'Approval channel rejected',
|
|
1241
|
+
'sessions.block.rejection.notExecuted': 'Command was not executed',
|
|
1242
|
+
'sessions.block.rejection.reason': 'Backend response: Rejected("rejected by user")',
|
|
1233
1243
|
'sessions.content.expand': 'Expand content',
|
|
1234
1244
|
'sessions.content.collapse': 'Collapse content',
|
|
1235
1245
|
'sessions.contextTitle': 'Full context size sent to the model in the last turn',
|
|
@@ -3682,11 +3692,23 @@ function renderBlocks(blocks, options = {}) {
|
|
|
3682
3692
|
: '';
|
|
3683
3693
|
out += `<details class="blk blk-tool" open><summary class="tool-head">${icon} <span class="tool-name">${esc(tool)}</span></summary>${toolParams}</details>`;
|
|
3684
3694
|
} else if (b.kind === 'tool_result') {
|
|
3685
|
-
const
|
|
3695
|
+
const rejection = b.rejection?.kind === 'approval_rejected' ? b.rejection : undefined;
|
|
3696
|
+
const cls = b.isError ? `blk-result err${rejection ? ' rejection' : ''}` : 'blk-result';
|
|
3686
3697
|
const loadFull = b.truncated && b.resultKey
|
|
3687
3698
|
? `<button class="ctrl-btn result-load-full" type="button" data-result-key="${esc(b.resultKey)}">${t('sessions.loadFullResult') || '加载完整结果'}</button>`
|
|
3688
3699
|
: '';
|
|
3689
|
-
|
|
3700
|
+
const rejectionMeta = rejection
|
|
3701
|
+
? '<div class="result-rejection-meta">' +
|
|
3702
|
+
`<span class="result-rejection-badge">⚠ ${t('sessions.block.rejection.title')}</span>` +
|
|
3703
|
+
`<span>${rejection.source === 'evolcore-policy' ? t('sessions.block.rejection.source.policy') : t('sessions.block.rejection.source.approval')}</span>` +
|
|
3704
|
+
`<span>${t('sessions.block.rejection.notExecuted')}</span>` +
|
|
3705
|
+
`<span class="result-rejection-reason">${t('sessions.block.rejection.reason')}</span>` +
|
|
3706
|
+
'</div>'
|
|
3707
|
+
: '';
|
|
3708
|
+
const resultLabel = rejection
|
|
3709
|
+
? t('sessions.block.rejection.title')
|
|
3710
|
+
: b.isError ? t('sessions.block.resultError') : t('sessions.block.result');
|
|
3711
|
+
out += `<details class="blk ${cls}" open><summary>${b.isError ? '✗ ' : '↳ '}${resultLabel}</summary>${rejectionMeta}` +
|
|
3690
3712
|
`<div class="result-content collapse-content"><pre class="result-body collapse-body">${esc(b.text)}</pre>${loadFull}<button class="collapse-arrow-toggle" type="button" hidden aria-expanded="false"><span class="collapse-arrow-icon" aria-hidden="true"></span></button></div></details>`;
|
|
3691
3713
|
} else if (b.kind === 'subtask') {
|
|
3692
3714
|
const knownStatuses = ['running', 'completed', 'failed', 'stopped', 'killed'];
|
package/dist/static/index.html
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
|
|
49
49
|
</nav>
|
|
50
50
|
<span style="flex:1"></span>
|
|
51
|
-
2026-08-
|
|
51
|
+
2026-08-19 05:07
|
|
52
52
|
<span id="conn-status" class="conn-status" data-i18n="status.connecting">连接中…</span>
|
|
53
53
|
<button id="lang-btn" class="theme-btn" data-i18n-title="language.buttonTitle" title="切换语言">🌐</button>
|
|
54
54
|
<button id="theme-btn" class="theme-btn" data-i18n-title="theme.buttonTitle" title="主题">🌗</button>
|
package/dist/static/style.css
CHANGED
|
@@ -540,6 +540,17 @@ tr:hover td { background: var(--bg2); }
|
|
|
540
540
|
.blk-result { font-size: 12px; }
|
|
541
541
|
.blk-result summary { cursor: pointer; color: var(--dim); }
|
|
542
542
|
.blk-result.err summary { color: var(--red); }
|
|
543
|
+
.result-rejection-meta {
|
|
544
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
|
|
545
|
+
margin-top: 7px; color: var(--dim); font-size: 11px;
|
|
546
|
+
}
|
|
547
|
+
.result-rejection-badge {
|
|
548
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
549
|
+
padding: 2px 7px; border: 1px solid color-mix(in srgb, var(--red) 45%, var(--border));
|
|
550
|
+
border-radius: 4px; color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent);
|
|
551
|
+
font-weight: 600;
|
|
552
|
+
}
|
|
553
|
+
.result-rejection-reason { flex-basis: 100%; overflow-wrap: anywhere; }
|
|
543
554
|
.collapse-content { position: relative; }
|
|
544
555
|
.result-content { --collapse-fade-bg: var(--bg); margin-top: 6px; }
|
|
545
556
|
.collapse-content::after {
|