@sanqianx/claude-ai-workbench 0.13.2 → 0.13.3
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/LICENSE +201 -201
- package/README.md +156 -156
- package/apps/agent-terminal/app.css +636 -613
- package/apps/agent-terminal/app.js +125 -65
- package/apps/agent-terminal/conversation-composer.js +44 -0
- package/apps/agent-terminal/index.html +171 -170
- package/apps/agent-terminal/panel-host-proof.html +152 -152
- package/apps/agent-terminal/panel-proof-content.html +41 -41
- package/apps/agent-terminal/right-workspace-dock.css +187 -159
- package/apps/agent-terminal/right-workspace-dock.js +623 -519
- package/apps/ai-profile-settings-host/index.html +25 -25
- package/apps/ai-profile-settings-host/page.css +1 -1
- package/apps/ai-profile-settings-host/page.js +113 -113
- package/apps/minimal-test-host/README.md +15 -15
- package/apps/minimal-test-host/host.css +2 -2
- package/apps/minimal-test-host/host.js +35 -35
- package/apps/minimal-test-host/index.html +58 -58
- package/apps/minimal-test-host/optional-mock/fault-injection.js +15 -15
- package/docs/sdk/FILE_LAYOUT.md +31 -31
- package/docs/sdk/INTEGRATION.md +126 -126
- package/docs/sdk/README.md +21 -21
- package/docs/sdk/SESSION_EVENTS.md +13 -13
- package/docs/sdk/openapi.yaml +8 -1
- package/package.json +1 -1
- package/packages/client/README.md +29 -29
- package/packages/client/index.d.ts +122 -122
- package/packages/client/index.js +260 -260
- package/packages/client/package.json +2 -2
- package/packages/contracts/README.md +9 -9
- package/packages/contracts/index.d.ts +519 -517
- package/packages/contracts/index.js +312 -312
- package/packages/contracts/package.json +1 -1
- package/packages/core/README.md +8 -8
- package/packages/core/index.d.ts +76 -76
- package/packages/core/index.js +222 -222
- package/packages/core/package.json +2 -2
- package/packages/server/README.md +17 -17
- package/packages/server/bin/agent-terminal-server.js +42 -42
- package/packages/server/bin/claude-workbench.js +225 -225
- package/packages/server/index.d.ts +171 -171
- package/packages/server/index.js +230 -230
- package/packages/server/lib/agent-discovery.js +133 -133
- package/packages/server/lib/agent-registry.js +143 -143
- package/packages/server/lib/agent-spawn-env.js +17 -17
- package/packages/server/lib/attachment-store.js +78 -78
- package/packages/server/lib/bridges/app-server-bridge.js +373 -373
- package/packages/server/lib/bridges/opencode-server-bridge.js +506 -506
- package/packages/server/lib/capture-settings-store.js +35 -35
- package/packages/server/lib/claude-history-recovery.js +87 -87
- package/packages/server/lib/cli-session-recovery.js +28 -28
- package/packages/server/lib/context-resolver.js +55 -55
- package/packages/server/lib/conversation-capture.js +51 -51
- package/packages/server/lib/delegation-phase-store.js +357 -357
- package/packages/server/lib/delegation-store.js +474 -468
- package/packages/server/lib/diagnostics.js +32 -32
- package/packages/server/lib/drivers/cli-json-runner.js +974 -974
- package/packages/server/lib/drivers/codex-driver.js +1442 -1442
- package/packages/server/lib/drivers/opencode-driver.js +1554 -1554
- package/packages/server/lib/drivers/zcode-driver.js +1250 -1250
- package/packages/server/lib/drivers/zcode-profile-runtime.js +71 -71
- package/packages/server/lib/event-stream.js +138 -138
- package/packages/server/lib/folder-picker.js +623 -623
- package/packages/server/lib/http-handler.js +339 -339
- package/packages/server/lib/json-file.js +26 -26
- package/packages/server/lib/knowledge-context.js +33 -33
- package/packages/server/lib/model-detection.js +295 -295
- package/packages/server/lib/parent-context.js +44 -0
- package/packages/server/lib/profile-store.js +283 -283
- package/packages/server/lib/project-store.js +102 -102
- package/packages/server/lib/runtime-loader.js +120 -120
- package/packages/server/lib/session-archive-store.js +53 -53
- package/packages/server/lib/session-history.js +612 -612
- package/packages/server/lib/system-doctor.js +125 -125
- package/packages/server/lib/ui-preferences-store.js +48 -48
- package/packages/server/lib/workbench-service.js +1696 -1675
- package/packages/server/package.json +2 -2
- package/packages/ui/README.md +30 -30
- package/packages/ui/ai-profile-settings.d.ts +45 -45
- package/packages/ui/ai-profile-settings.js +283 -283
- package/packages/ui/claude-terminal.d.ts +31 -31
- package/packages/ui/claude-terminal.js +343 -343
- package/packages/ui/index.d.ts +18 -18
- package/packages/ui/index.js +51 -51
- package/packages/ui/package.json +2 -2
- package/packages/ui/theme.css +13 -13
- package/src/assets/claude-prompts.json +21 -21
- package/src/backend/http/ai-profile-routes.js +61 -61
- package/src/backend/http/claude-routes.js +170 -170
- package/src/backend/http/node-helpers.js +45 -45
- package/src/backend/index.js +21 -21
- package/src/backend/lib/ai-adapter.js +144 -144
- package/src/backend/lib/ai-profile-store.js +259 -259
- package/src/backend/lib/ai-vendor-presets.js +83 -83
- package/src/backend/lib/ai-workspace.js +140 -140
- package/src/backend/lib/automation-config.js +253 -253
- package/src/backend/lib/claude-cli-runner.js +2392 -2392
- package/src/backend/lib/data-dir.js +169 -169
- package/src/backend/lib/llm-client.js +176 -176
- package/src/backend/lib/model-context-windows.js +82 -82
- package/src/backend/lib/native-task-control.js +217 -217
- package/src/backend/lib/native-task-history-index.js +475 -475
- package/src/backend/lib/native-task-history-reader.js +526 -526
- package/src/backend/lib/native-task-messages.js +457 -457
- package/src/backend/lib/native-task-registry.js +325 -325
- package/src/backend/lib/native-task-runtime.js +242 -242
- package/src/backend/lib/native-task-trace.js +440 -440
- package/src/backend/lib/native-task-transcript.js +393 -393
- package/src/backend/lib/prompt-registry.js +166 -166
- package/src/backend/lib/runtime-config.js +121 -121
- package/src/backend/lib/sdk-session-stream.js +143 -143
- package/src/backend/lib/sdk-turn-stream.js +16 -16
- package/src/backend/lib/store-scope.js +131 -131
- package/src/backend/lib/task-identity.js +104 -104
- package/src/backend/lib/task-state-projection.js +58 -58
- package/src/index.js +7 -7
- package/src/sdk-wave-a.ts +1 -1
- package/src/sdk-wave-b.ts +1 -1
- package/src/sdk-wave-c.ts +1 -1
- package/src/sdk-wave-d.ts +1 -1
- package/src/sdk-wave-e.ts +1 -1
|
@@ -1,152 +1,152 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>W3 Panel Host Proof(最小可信宿主)</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root { color-scheme: dark; }
|
|
9
|
-
body { margin: 0; font: 13px/1.5 system-ui, sans-serif; background: #101016; color: #e8e8ee; display: flex; flex-direction: column; height: 100vh; }
|
|
10
|
-
header { padding: 8px 12px; border-bottom: 1px solid #2a2a33; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
11
|
-
header h1 { font-size: 14px; margin: 0 12px 0 0; }
|
|
12
|
-
header .note { color: #9a9aa5; font-size: 11px; }
|
|
13
|
-
button { font: inherit; padding: 3px 10px; border: 1px solid #2a2a33; border-radius: 6px; background: #1a1a22; color: inherit; cursor: pointer; }
|
|
14
|
-
button:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
15
|
-
main { flex: 1; display: flex; min-height: 0; }
|
|
16
|
-
#terminal-frame { flex: 1 1 62%; border: none; background: #14141a; }
|
|
17
|
-
aside { flex: 0 0 38%; border-left: 1px solid #2a2a33; display: flex; flex-direction: column; min-width: 0; }
|
|
18
|
-
.state-head { padding: 6px 10px; border-bottom: 1px solid #2a2a33; display: flex; gap: 8px; align-items: baseline; }
|
|
19
|
-
.state-head strong { font-size: 12px; }
|
|
20
|
-
#panel-status { font-size: 11px; color: #9a9aa5; }
|
|
21
|
-
#state-log { flex: 1; overflow-y: auto; margin: 0; padding: 6px 10px; font: 11px/1.6 ui-monospace, monospace; white-space: pre-wrap; word-break: break-all; }
|
|
22
|
-
#state-log .line { display: block; border-bottom: 1px dashed #22222b; padding: 2px 0; }
|
|
23
|
-
#state-log .dir-host { color: #7fa3e8; }
|
|
24
|
-
#state-log .dir-app { color: #2e9e5b; }
|
|
25
|
-
#state-log .dir-err { color: #d64545; }
|
|
26
|
-
</style>
|
|
27
|
-
</head>
|
|
28
|
-
<body>
|
|
29
|
-
<header>
|
|
30
|
-
<h1>W3 Panel Host Proof</h1>
|
|
31
|
-
<span class="note">同源最小宿主:以 embed 模式加载真实 Agent Terminal,注册同源 knowledge iframe 面板。独立 Workbench 不依赖本页代码。</span>
|
|
32
|
-
</header>
|
|
33
|
-
<header>
|
|
34
|
-
<button id="btn-register" disabled>注册知识面板</button>
|
|
35
|
-
<button id="btn-unregister" disabled>注销</button>
|
|
36
|
-
<button id="btn-open-1" disabled>打开一个</button>
|
|
37
|
-
<button id="btn-open-2" disabled>打开第二个</button>
|
|
38
|
-
<button id="btn-close-last" disabled>关闭最后一个</button>
|
|
39
|
-
<button id="btn-activate-first" disabled>切换激活到第一个</button>
|
|
40
|
-
</header>
|
|
41
|
-
<main>
|
|
42
|
-
<iframe id="terminal-frame" title="Agent Terminal(embed)" src="/agent-terminal/?embed=1"></iframe>
|
|
43
|
-
<aside>
|
|
44
|
-
<div class="state-head"><strong>panel state 事件日志</strong><span id="panel-status">等待 kb:ready…</span></div>
|
|
45
|
-
<pre id="state-log"></pre>
|
|
46
|
-
</aside>
|
|
47
|
-
</main>
|
|
48
|
-
<script>
|
|
49
|
-
(function () {
|
|
50
|
-
'use strict';
|
|
51
|
-
var frame = document.getElementById('terminal-frame');
|
|
52
|
-
var log = document.getElementById('state-log');
|
|
53
|
-
var status = document.getElementById('panel-status');
|
|
54
|
-
var buttons = {
|
|
55
|
-
register: document.getElementById('btn-register'),
|
|
56
|
-
unregister: document.getElementById('btn-unregister'),
|
|
57
|
-
open1: document.getElementById('btn-open-1'),
|
|
58
|
-
open2: document.getElementById('btn-open-2'),
|
|
59
|
-
closeLast: document.getElementById('btn-close-last'),
|
|
60
|
-
activateFirst: document.getElementById('btn-activate-first'),
|
|
61
|
-
};
|
|
62
|
-
var ORIGIN = window.location.origin;
|
|
63
|
-
var PROVIDER_ID = 'kb.proof.knowledge';
|
|
64
|
-
var ready = false;
|
|
65
|
-
var registered = false;
|
|
66
|
-
var panels = [];
|
|
67
|
-
var requestSeq = 0;
|
|
68
|
-
|
|
69
|
-
function line(text, dir) {
|
|
70
|
-
var entry = document.createElement('span');
|
|
71
|
-
entry.className = 'line ' + (dir === 'host' ? 'dir-host' : dir === 'app' ? 'dir-app' : 'dir-err');
|
|
72
|
-
entry.textContent = new Date().toISOString().slice(11, 23) + ' ' + text;
|
|
73
|
-
log.append(entry);
|
|
74
|
-
log.scrollTop = log.scrollHeight;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function send(message) {
|
|
78
|
-
if (!ready) { line('宿主 → 终端:忽略(终端未 ready)', 'err'); return; }
|
|
79
|
-
message.requestId = 'proof-' + (++requestSeq);
|
|
80
|
-
frame.contentWindow.postMessage(message, ORIGIN);
|
|
81
|
-
line('宿主 → 终端 ' + message.type + ' ' + JSON.stringify(message), 'host');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function refreshButtons() {
|
|
85
|
-
var knowledgeOpen = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
86
|
-
buttons.register.disabled = !ready || registered;
|
|
87
|
-
buttons.unregister.disabled = !ready || !registered;
|
|
88
|
-
buttons.open1.disabled = !ready || !registered;
|
|
89
|
-
buttons.open2.disabled = !ready || !registered;
|
|
90
|
-
buttons.closeLast.disabled = knowledgeOpen.length === 0;
|
|
91
|
-
buttons.activateFirst.disabled = knowledgeOpen.length < 2;
|
|
92
|
-
status.textContent = ready
|
|
93
|
-
? (registered ? '已注册 knowledge 面板;当前打开 ' + knowledgeOpen.length + ' 个实例' : '未注册 provider:knowledge 不显示为可用')
|
|
94
|
-
: '等待 kb:ready…';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
window.addEventListener('message', function (ev) {
|
|
98
|
-
if (ev.source !== frame.contentWindow || ev.origin !== ORIGIN) return;
|
|
99
|
-
var data = ev.data;
|
|
100
|
-
if (!data || typeof data !== 'object') return;
|
|
101
|
-
if (data.type === 'kb:ready') {
|
|
102
|
-
ready = true;
|
|
103
|
-
line('终端 → 宿主 kb:ready(注册自此生效)', 'app');
|
|
104
|
-
refreshButtons();
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
if (data.type === 'kb:panel/state') {
|
|
108
|
-
panels = Array.isArray(data.panels) ? data.panels : [];
|
|
109
|
-
var providers = (data.providers || []).map(function (p) { return p.providerId; });
|
|
110
|
-
line('终端 → 宿主 kb:panel/state reason=' + data.reason +
|
|
111
|
-
' panels=' + JSON.stringify(panels.map(function (p) {
|
|
112
|
-
return { id: p.panelId, provider: p.providerId, active: p.active, error: p.error, scope: p.scope };
|
|
113
|
-
})) +
|
|
114
|
-
' providers=' + JSON.stringify(providers), 'app');
|
|
115
|
-
refreshButtons();
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (typeof data.type === 'string' && data.type.indexOf('kb:panel/') === 0) {
|
|
119
|
-
line('终端 → 宿主 ' + data.type + ' ' + JSON.stringify(data), 'app');
|
|
120
|
-
if (data.type === 'kb:panel/registered' && data.ok) registered = true;
|
|
121
|
-
if (data.type === 'kb:panel/unregistered' && data.ok) registered = false;
|
|
122
|
-
refreshButtons();
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
buttons.register.addEventListener('click', function () {
|
|
127
|
-
send({ type: 'kb:panel/register', panel: {
|
|
128
|
-
providerId: PROVIDER_ID,
|
|
129
|
-
panelType: 'knowledge',
|
|
130
|
-
title: '知识引用(proof)',
|
|
131
|
-
url: new URL('panel-proof-content.html?panel=knowledge&source=host-proof', window.location.href).href,
|
|
132
|
-
capabilities: ['read-only', 'proof'],
|
|
133
|
-
multiInstance: 'multiple',
|
|
134
|
-
appliesTo: { projects: '*' },
|
|
135
|
-
} });
|
|
136
|
-
});
|
|
137
|
-
buttons.unregister.addEventListener('click', function () { send({ type: 'kb:panel/unregister', providerId: PROVIDER_ID }); });
|
|
138
|
-
buttons.open1.addEventListener('click', function () { send({ type: 'kb:panel/open', providerId: PROVIDER_ID }); });
|
|
139
|
-
buttons.open2.addEventListener('click', function () { send({ type: 'kb:panel/open', providerId: PROVIDER_ID }); });
|
|
140
|
-
buttons.closeLast.addEventListener('click', function () {
|
|
141
|
-
var open = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
142
|
-
if (open.length) send({ type: 'kb:panel/close', panelId: open[open.length - 1].panelId });
|
|
143
|
-
});
|
|
144
|
-
buttons.activateFirst.addEventListener('click', function () {
|
|
145
|
-
var open = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
146
|
-
if (open.length >= 2) send({ type: 'kb:panel/activate', panelId: open[0].panelId });
|
|
147
|
-
});
|
|
148
|
-
refreshButtons();
|
|
149
|
-
})();
|
|
150
|
-
</script>
|
|
151
|
-
</body>
|
|
152
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>W3 Panel Host Proof(最小可信宿主)</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root { color-scheme: dark; }
|
|
9
|
+
body { margin: 0; font: 13px/1.5 system-ui, sans-serif; background: #101016; color: #e8e8ee; display: flex; flex-direction: column; height: 100vh; }
|
|
10
|
+
header { padding: 8px 12px; border-bottom: 1px solid #2a2a33; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
11
|
+
header h1 { font-size: 14px; margin: 0 12px 0 0; }
|
|
12
|
+
header .note { color: #9a9aa5; font-size: 11px; }
|
|
13
|
+
button { font: inherit; padding: 3px 10px; border: 1px solid #2a2a33; border-radius: 6px; background: #1a1a22; color: inherit; cursor: pointer; }
|
|
14
|
+
button:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
15
|
+
main { flex: 1; display: flex; min-height: 0; }
|
|
16
|
+
#terminal-frame { flex: 1 1 62%; border: none; background: #14141a; }
|
|
17
|
+
aside { flex: 0 0 38%; border-left: 1px solid #2a2a33; display: flex; flex-direction: column; min-width: 0; }
|
|
18
|
+
.state-head { padding: 6px 10px; border-bottom: 1px solid #2a2a33; display: flex; gap: 8px; align-items: baseline; }
|
|
19
|
+
.state-head strong { font-size: 12px; }
|
|
20
|
+
#panel-status { font-size: 11px; color: #9a9aa5; }
|
|
21
|
+
#state-log { flex: 1; overflow-y: auto; margin: 0; padding: 6px 10px; font: 11px/1.6 ui-monospace, monospace; white-space: pre-wrap; word-break: break-all; }
|
|
22
|
+
#state-log .line { display: block; border-bottom: 1px dashed #22222b; padding: 2px 0; }
|
|
23
|
+
#state-log .dir-host { color: #7fa3e8; }
|
|
24
|
+
#state-log .dir-app { color: #2e9e5b; }
|
|
25
|
+
#state-log .dir-err { color: #d64545; }
|
|
26
|
+
</style>
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<header>
|
|
30
|
+
<h1>W3 Panel Host Proof</h1>
|
|
31
|
+
<span class="note">同源最小宿主:以 embed 模式加载真实 Agent Terminal,注册同源 knowledge iframe 面板。独立 Workbench 不依赖本页代码。</span>
|
|
32
|
+
</header>
|
|
33
|
+
<header>
|
|
34
|
+
<button id="btn-register" disabled>注册知识面板</button>
|
|
35
|
+
<button id="btn-unregister" disabled>注销</button>
|
|
36
|
+
<button id="btn-open-1" disabled>打开一个</button>
|
|
37
|
+
<button id="btn-open-2" disabled>打开第二个</button>
|
|
38
|
+
<button id="btn-close-last" disabled>关闭最后一个</button>
|
|
39
|
+
<button id="btn-activate-first" disabled>切换激活到第一个</button>
|
|
40
|
+
</header>
|
|
41
|
+
<main>
|
|
42
|
+
<iframe id="terminal-frame" title="Agent Terminal(embed)" src="/agent-terminal/?embed=1"></iframe>
|
|
43
|
+
<aside>
|
|
44
|
+
<div class="state-head"><strong>panel state 事件日志</strong><span id="panel-status">等待 kb:ready…</span></div>
|
|
45
|
+
<pre id="state-log"></pre>
|
|
46
|
+
</aside>
|
|
47
|
+
</main>
|
|
48
|
+
<script>
|
|
49
|
+
(function () {
|
|
50
|
+
'use strict';
|
|
51
|
+
var frame = document.getElementById('terminal-frame');
|
|
52
|
+
var log = document.getElementById('state-log');
|
|
53
|
+
var status = document.getElementById('panel-status');
|
|
54
|
+
var buttons = {
|
|
55
|
+
register: document.getElementById('btn-register'),
|
|
56
|
+
unregister: document.getElementById('btn-unregister'),
|
|
57
|
+
open1: document.getElementById('btn-open-1'),
|
|
58
|
+
open2: document.getElementById('btn-open-2'),
|
|
59
|
+
closeLast: document.getElementById('btn-close-last'),
|
|
60
|
+
activateFirst: document.getElementById('btn-activate-first'),
|
|
61
|
+
};
|
|
62
|
+
var ORIGIN = window.location.origin;
|
|
63
|
+
var PROVIDER_ID = 'kb.proof.knowledge';
|
|
64
|
+
var ready = false;
|
|
65
|
+
var registered = false;
|
|
66
|
+
var panels = [];
|
|
67
|
+
var requestSeq = 0;
|
|
68
|
+
|
|
69
|
+
function line(text, dir) {
|
|
70
|
+
var entry = document.createElement('span');
|
|
71
|
+
entry.className = 'line ' + (dir === 'host' ? 'dir-host' : dir === 'app' ? 'dir-app' : 'dir-err');
|
|
72
|
+
entry.textContent = new Date().toISOString().slice(11, 23) + ' ' + text;
|
|
73
|
+
log.append(entry);
|
|
74
|
+
log.scrollTop = log.scrollHeight;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function send(message) {
|
|
78
|
+
if (!ready) { line('宿主 → 终端:忽略(终端未 ready)', 'err'); return; }
|
|
79
|
+
message.requestId = 'proof-' + (++requestSeq);
|
|
80
|
+
frame.contentWindow.postMessage(message, ORIGIN);
|
|
81
|
+
line('宿主 → 终端 ' + message.type + ' ' + JSON.stringify(message), 'host');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function refreshButtons() {
|
|
85
|
+
var knowledgeOpen = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
86
|
+
buttons.register.disabled = !ready || registered;
|
|
87
|
+
buttons.unregister.disabled = !ready || !registered;
|
|
88
|
+
buttons.open1.disabled = !ready || !registered;
|
|
89
|
+
buttons.open2.disabled = !ready || !registered;
|
|
90
|
+
buttons.closeLast.disabled = knowledgeOpen.length === 0;
|
|
91
|
+
buttons.activateFirst.disabled = knowledgeOpen.length < 2;
|
|
92
|
+
status.textContent = ready
|
|
93
|
+
? (registered ? '已注册 knowledge 面板;当前打开 ' + knowledgeOpen.length + ' 个实例' : '未注册 provider:knowledge 不显示为可用')
|
|
94
|
+
: '等待 kb:ready…';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
window.addEventListener('message', function (ev) {
|
|
98
|
+
if (ev.source !== frame.contentWindow || ev.origin !== ORIGIN) return;
|
|
99
|
+
var data = ev.data;
|
|
100
|
+
if (!data || typeof data !== 'object') return;
|
|
101
|
+
if (data.type === 'kb:ready') {
|
|
102
|
+
ready = true;
|
|
103
|
+
line('终端 → 宿主 kb:ready(注册自此生效)', 'app');
|
|
104
|
+
refreshButtons();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (data.type === 'kb:panel/state') {
|
|
108
|
+
panels = Array.isArray(data.panels) ? data.panels : [];
|
|
109
|
+
var providers = (data.providers || []).map(function (p) { return p.providerId; });
|
|
110
|
+
line('终端 → 宿主 kb:panel/state reason=' + data.reason +
|
|
111
|
+
' panels=' + JSON.stringify(panels.map(function (p) {
|
|
112
|
+
return { id: p.panelId, provider: p.providerId, active: p.active, error: p.error, scope: p.scope };
|
|
113
|
+
})) +
|
|
114
|
+
' providers=' + JSON.stringify(providers), 'app');
|
|
115
|
+
refreshButtons();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (typeof data.type === 'string' && data.type.indexOf('kb:panel/') === 0) {
|
|
119
|
+
line('终端 → 宿主 ' + data.type + ' ' + JSON.stringify(data), 'app');
|
|
120
|
+
if (data.type === 'kb:panel/registered' && data.ok) registered = true;
|
|
121
|
+
if (data.type === 'kb:panel/unregistered' && data.ok) registered = false;
|
|
122
|
+
refreshButtons();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
buttons.register.addEventListener('click', function () {
|
|
127
|
+
send({ type: 'kb:panel/register', panel: {
|
|
128
|
+
providerId: PROVIDER_ID,
|
|
129
|
+
panelType: 'knowledge',
|
|
130
|
+
title: '知识引用(proof)',
|
|
131
|
+
url: new URL('panel-proof-content.html?panel=knowledge&source=host-proof', window.location.href).href,
|
|
132
|
+
capabilities: ['read-only', 'proof'],
|
|
133
|
+
multiInstance: 'multiple',
|
|
134
|
+
appliesTo: { projects: '*' },
|
|
135
|
+
} });
|
|
136
|
+
});
|
|
137
|
+
buttons.unregister.addEventListener('click', function () { send({ type: 'kb:panel/unregister', providerId: PROVIDER_ID }); });
|
|
138
|
+
buttons.open1.addEventListener('click', function () { send({ type: 'kb:panel/open', providerId: PROVIDER_ID }); });
|
|
139
|
+
buttons.open2.addEventListener('click', function () { send({ type: 'kb:panel/open', providerId: PROVIDER_ID }); });
|
|
140
|
+
buttons.closeLast.addEventListener('click', function () {
|
|
141
|
+
var open = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
142
|
+
if (open.length) send({ type: 'kb:panel/close', panelId: open[open.length - 1].panelId });
|
|
143
|
+
});
|
|
144
|
+
buttons.activateFirst.addEventListener('click', function () {
|
|
145
|
+
var open = panels.filter(function (p) { return p.providerId === PROVIDER_ID; });
|
|
146
|
+
if (open.length >= 2) send({ type: 'kb:panel/activate', panelId: open[0].panelId });
|
|
147
|
+
});
|
|
148
|
+
refreshButtons();
|
|
149
|
+
})();
|
|
150
|
+
</script>
|
|
151
|
+
</body>
|
|
152
|
+
</html>
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>Panel Proof Content</title>
|
|
6
|
-
<style>
|
|
7
|
-
:root { color-scheme: dark; }
|
|
8
|
-
body { margin: 0; padding: 12px; font: 12px/1.6 system-ui, sans-serif; background: #14141a; color: #e8e8ee; }
|
|
9
|
-
h1 { font-size: 13px; margin: 0 0 8px; }
|
|
10
|
-
dl { display: grid; grid-template-columns: 110px 1fr; gap: 4px 10px; margin: 0; }
|
|
11
|
-
dt { color: #9a9aa5; }
|
|
12
|
-
dd { margin: 0; word-break: break-all; }
|
|
13
|
-
#marker { color: #2e9e5b; font-weight: 600; }
|
|
14
|
-
#sandbox-state { color: #7fa3e8; }
|
|
15
|
-
</style>
|
|
16
|
-
</head>
|
|
17
|
-
<body>
|
|
18
|
-
<h1>知识引用面板内容(proof)</h1>
|
|
19
|
-
<dl>
|
|
20
|
-
<dt>稳定 marker</dt><dd id="marker">KB-PANEL-PROOF-CONTENT-v1</dd>
|
|
21
|
-
<dt>自身 query</dt><dd id="query"></dd>
|
|
22
|
-
<dt>自身 href</dt><dd id="href"></dd>
|
|
23
|
-
<dt>sandbox 状态</dt><dd id="sandbox-state"></dd>
|
|
24
|
-
<dt>自身 origin</dt><dd id="origin"></dd>
|
|
25
|
-
</dl>
|
|
26
|
-
<script>
|
|
27
|
-
(function () {
|
|
28
|
-
'use strict';
|
|
29
|
-
document.getElementById('query').textContent = window.location.search || '(无 query)';
|
|
30
|
-
document.getElementById('href').textContent = window.location.href;
|
|
31
|
-
document.getElementById('origin').textContent = window.location.origin;
|
|
32
|
-
// The dock mounts panels with sandbox="allow-scripts" (no allow-same-origin):
|
|
33
|
-
// reaching the parent must throw, proving the frame is credibly contained.
|
|
34
|
-
var contained = '未知';
|
|
35
|
-
try { if (window.parent && window.parent !== window) { void window.parent.location.href; contained = '否(可访问父窗口,sandbox 未生效)'; } else contained = '无父窗口'; }
|
|
36
|
-
catch (error) { contained = '是(父窗口不可达:' + (error && error.name ? error.name : 'Error') + ')'; }
|
|
37
|
-
document.getElementById('sandbox-state').textContent = contained;
|
|
38
|
-
})();
|
|
39
|
-
</script>
|
|
40
|
-
</body>
|
|
41
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Panel Proof Content</title>
|
|
6
|
+
<style>
|
|
7
|
+
:root { color-scheme: dark; }
|
|
8
|
+
body { margin: 0; padding: 12px; font: 12px/1.6 system-ui, sans-serif; background: #14141a; color: #e8e8ee; }
|
|
9
|
+
h1 { font-size: 13px; margin: 0 0 8px; }
|
|
10
|
+
dl { display: grid; grid-template-columns: 110px 1fr; gap: 4px 10px; margin: 0; }
|
|
11
|
+
dt { color: #9a9aa5; }
|
|
12
|
+
dd { margin: 0; word-break: break-all; }
|
|
13
|
+
#marker { color: #2e9e5b; font-weight: 600; }
|
|
14
|
+
#sandbox-state { color: #7fa3e8; }
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<h1>知识引用面板内容(proof)</h1>
|
|
19
|
+
<dl>
|
|
20
|
+
<dt>稳定 marker</dt><dd id="marker">KB-PANEL-PROOF-CONTENT-v1</dd>
|
|
21
|
+
<dt>自身 query</dt><dd id="query"></dd>
|
|
22
|
+
<dt>自身 href</dt><dd id="href"></dd>
|
|
23
|
+
<dt>sandbox 状态</dt><dd id="sandbox-state"></dd>
|
|
24
|
+
<dt>自身 origin</dt><dd id="origin"></dd>
|
|
25
|
+
</dl>
|
|
26
|
+
<script>
|
|
27
|
+
(function () {
|
|
28
|
+
'use strict';
|
|
29
|
+
document.getElementById('query').textContent = window.location.search || '(无 query)';
|
|
30
|
+
document.getElementById('href').textContent = window.location.href;
|
|
31
|
+
document.getElementById('origin').textContent = window.location.origin;
|
|
32
|
+
// The dock mounts panels with sandbox="allow-scripts" (no allow-same-origin):
|
|
33
|
+
// reaching the parent must throw, proving the frame is credibly contained.
|
|
34
|
+
var contained = '未知';
|
|
35
|
+
try { if (window.parent && window.parent !== window) { void window.parent.location.href; contained = '否(可访问父窗口,sandbox 未生效)'; } else contained = '无父窗口'; }
|
|
36
|
+
catch (error) { contained = '是(父窗口不可达:' + (error && error.name ? error.name : 'Error') + ')'; }
|
|
37
|
+
document.getElementById('sandbox-state').textContent = contained;
|
|
38
|
+
})();
|
|
39
|
+
</script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|