Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
9eb4bc0
docs(ui): add harness-informed interaction roadmap
SakuraRoxy Aug 19, 2026
2804501
refactor(chat): introduce kernel renderer and surface boundaries
SakuraRoxy Aug 20, 2026
929edd6
test(chat): enforce lifecycle and consumer contracts
SakuraRoxy Aug 20, 2026
d95741b
docs(ui): record harness architecture and roadmap
SakuraRoxy Aug 20, 2026
341c881
refactor(chat): establish stream session authority
SakuraRoxy Aug 20, 2026
688923d
refactor(chat): route streams through owned consumers
SakuraRoxy Aug 20, 2026
6fb1f03
refactor(chat): require explicit render capabilities
SakuraRoxy Aug 20, 2026
4e6f882
refactor(chat): compose main chat through surface adapter
SakuraRoxy Aug 20, 2026
de37c0b
refactor(chat): retire duplicate stream terminal paths
RoxyAsahi Aug 20, 2026
3b0a77c
test(chat): enforce facade consumer ownership
RoxyAsahi Aug 20, 2026
a5dcabf
test(chat): refresh reviewed architecture gates
RoxyAsahi Aug 20, 2026
9adc2be
refactor(chat): enforce owned stream surface lifecycles
RoxyAsahi Aug 20, 2026
b4e5ae4
fix(chat): revoke late stream projection authority
RoxyAsahi Aug 20, 2026
18d15dc
test(chat): admit reviewed stream runtime evidence
RoxyAsahi Aug 20, 2026
863095e
refactor(chat): establish explicit stream and renderer providers
RoxyAsahi Aug 20, 2026
cd9369a
fix(chat): silence queued projection after failure
RoxyAsahi Aug 20, 2026
8040f75
refactor(chat): use explicit providers in main renderer
RoxyAsahi Aug 20, 2026
cf12c8d
refactor(chat): remove global renderer reads from internal surfaces
RoxyAsahi Aug 20, 2026
551cf08
refactor(chat): expose explicit chat manager provider
RoxyAsahi Aug 20, 2026
a23b161
refactor(chat): retire unconsumed renderer and stream globals
RoxyAsahi Aug 20, 2026
3f77ecd
refactor(chat): inject stream state into middle click handler
RoxyAsahi Aug 20, 2026
7fb728c
refactor(chat): retire chat manager global facade
RoxyAsahi Aug 20, 2026
a87275c
refactor(chat): narrow renderer message capabilities
RoxyAsahi Aug 20, 2026
6db2a67
test(chat): enforce provider retirement and real creation flow
RoxyAsahi Aug 20, 2026
07dd27f
refactor(chat): centralize durable history mutations
RoxyAsahi Aug 20, 2026
8f27a70
fix(chat): carry producer stream operation identity
RoxyAsahi Aug 20, 2026
1b77a0f
fix(flowlock): require ready chat history provider
RoxyAsahi Aug 20, 2026
9e7b41e
docs(chat): record provider and stream identity progress
RoxyAsahi Aug 20, 2026
a3905da
refactor(chat): route auxiliary history writes through authority
RoxyAsahi Aug 20, 2026
263d518
test(chat): scan all production kernel consumers
RoxyAsahi Aug 20, 2026
38d8ba8
refactor(chat): close flowlock history persistence bypass
RoxyAsahi Aug 20, 2026
0912f34
refactor(chat): settle auxiliary streams before close
RoxyAsahi Aug 20, 2026
36d8dd4
refactor(chat): remove legacy history ipc fallbacks
RoxyAsahi Aug 20, 2026
b1d250d
test(chat): cover auxiliary window terminal persistence
RoxyAsahi Aug 20, 2026
743801e
fix(chat): isolate interactive stream ownership
RoxyAsahi Aug 20, 2026
1ac64e5
fix(chat): persist auxiliary window histories
RoxyAsahi Aug 20, 2026
5c60f51
fix(chat): wire surface interrupt capability
RoxyAsahi Aug 20, 2026
e3e9553
test(chat): cover concurrent and auxiliary stream ownership
RoxyAsahi Aug 20, 2026
21ec35d
test(flowlock): cover real non-stream terminal
RoxyAsahi Aug 20, 2026
a439fc3
docs(chat): record real surface terminal evidence
RoxyAsahi Aug 20, 2026
a8c7d39
refactor(chat): remove unused window renderer capability
RoxyAsahi Aug 20, 2026
a4f3c2f
refactor(chat): inject internal surface capabilities
RoxyAsahi Aug 20, 2026
e639ec1
refactor(chat): isolate render generations by surface
RoxyAsahi Aug 20, 2026
751ed34
refactor(chat): create surface-owned message renderers
RoxyAsahi Aug 20, 2026
35897e5
refactor(chat): isolate renderer presentation providers
RoxyAsahi Aug 20, 2026
c81ced6
refactor(chat): own desktop push stream effects
RoxyAsahi Aug 20, 2026
2e87cd9
refactor(chat): give internal surfaces owned renderers
RoxyAsahi Aug 20, 2026
fc4c800
fix(chat): drain operations before surface teardown
RoxyAsahi Aug 20, 2026
c5830ce
refactor(chat): scope stream projection by surface
RoxyAsahi Aug 20, 2026
fa38cb5
refactor(chat): inject surface conversation capabilities
RoxyAsahi Aug 20, 2026
738bd56
refactor(chat): inject stream projection realm capabilities
RoxyAsahi Aug 20, 2026
f3ca081
refactor(chat): close renderer realm capability
RoxyAsahi Aug 20, 2026
3999cfc
test(chat): enforce surface capability boundaries
RoxyAsahi Aug 20, 2026
cd7c6dc
docs(chat): record surface projection ownership
RoxyAsahi Aug 20, 2026
4e741e4
refactor(chat): retire renderer edit facades
RoxyAsahi Aug 20, 2026
1f2506d
fix(chat): keep auxiliary actions on owning surface
RoxyAsahi Aug 20, 2026
a44620e
fix(chat): scope audio controls to renderer root
RoxyAsahi Aug 20, 2026
eb23718
refactor(chat): remove dom builder global facade
RoxyAsahi Aug 20, 2026
572d1d3
refactor(chat): isolate renderer roots and styles
RoxyAsahi Aug 20, 2026
4b85553
refactor(chat): add owned stream view authority
RoxyAsahi Aug 20, 2026
28b71d3
refactor(chat): narrow internal surface capabilities
RoxyAsahi Aug 20, 2026
785cfb1
docs(chat): record stream ownership boundary
RoxyAsahi Aug 20, 2026
70f21aa
refactor(chat): route stream history through owner capability
RoxyAsahi Aug 20, 2026
ca7a94f
test(chat): prove owned stream navigation authority
RoxyAsahi Aug 20, 2026
a30cc19
test(chat): refresh architecture boundary evidence
RoxyAsahi Aug 20, 2026
e40b831
fix(chat): make stream projection timers quiescent
RoxyAsahi Aug 20, 2026
356d7a6
refactor(chat): move main unload ownership into adapter
RoxyAsahi Aug 20, 2026
ab1424b
test(chat): refresh stream quiescence baseline
RoxyAsahi Aug 20, 2026
4bc48f2
test(chat): refresh canonical stream baseline
RoxyAsahi Aug 20, 2026
c4d970a
refactor(chat): extract main chat composition
RoxyAsahi Aug 20, 2026
4ad03a2
refactor(chat): close non-streaming terminal boundary
RoxyAsahi Aug 20, 2026
6990440
refactor(chat): close surface stream history boundary
RoxyAsahi Aug 20, 2026
e259f8b
test(ui): admit chat kernel boundary evidence
RoxyAsahi Aug 20, 2026
5347b54
docs(chat): record injected surface send capability
RoxyAsahi Aug 20, 2026
ed196ee
refactor(chat): inject main send action capability
RoxyAsahi Aug 20, 2026
cd94ed9
refactor(chat): carry producer operation identity into projection
RoxyAsahi Aug 20, 2026
4bc90e9
test(chat): prove projection operation identity isolation
RoxyAsahi Aug 20, 2026
7d8fc5c
docs(chat): refresh consumer evidence after operation scoping
RoxyAsahi Aug 20, 2026
1dc67f9
fix(chat): preserve fallback topic after deletion races
RoxyAsahi Aug 20, 2026
609ff99
fix(chat): persist selection intent before recovery
RoxyAsahi Aug 20, 2026
65db343
refactor(chat): scope stream projection runtime by operation
RoxyAsahi Aug 20, 2026
4506cba
test(chat): allow bounded renderer recovery window
RoxyAsahi Aug 20, 2026
8f7680e
docs(chat): record operation-scoped projection runtime
RoxyAsahi Aug 20, 2026
5ac5a27
docs(chat): refresh operation consumer report
RoxyAsahi Aug 20, 2026
46932bf
refactor(chat): scope renderer scheduling to surface realm
RoxyAsahi Aug 20, 2026
17a8f3c
test(chat): review renderer realm boundary baseline
RoxyAsahi Aug 20, 2026
b02ed30
docs(chat): refresh renderer consumer line evidence
RoxyAsahi Aug 20, 2026
6705d94
refactor(chat): own renderer preload subscriptions
RoxyAsahi Aug 20, 2026
418a494
fix(ui): reconcile embedded session before reopen
RoxyAsahi Aug 20, 2026
e5faae1
refactor(renderer): own group topic subscription
RoxyAsahi Aug 20, 2026
99c05a3
docs(chat): record recovery and soak evidence
RoxyAsahi Aug 20, 2026
a61799b
test(ui): gate connected lifecycle dom
RoxyAsahi Aug 20, 2026
bf8b414
docs(ui): align current state with chat kernel progress
RoxyAsahi Aug 20, 2026
4f64a08
test(ui): terminate windows stress process trees
RoxyAsahi Aug 20, 2026
81ef7ef
refactor(chat): keep send state out of stream projection
RoxyAsahi Aug 20, 2026
26fd239
refactor(chat): remove stream projection init facade
RoxyAsahi Aug 20, 2026
26821f3
fix(chat): settle main send state from stream consumer
RoxyAsahi Aug 20, 2026
3d44eba
docs(chat): align projection lifecycle evidence
RoxyAsahi Aug 20, 2026
39e7649
test(chat): await topic list before reset selection
RoxyAsahi Aug 20, 2026
28c1c52
test(chat): refresh consumer evidence after stream facade removal
RoxyAsahi Aug 20, 2026
2e1e7cf
test(ui): admit owned preload lifecycle evidence
RoxyAsahi Aug 20, 2026
66f4796
docs(chat): record completed main chat soak matrix
RoxyAsahi Aug 20, 2026
4922308
docs(ui): align current state with soak evidence
RoxyAsahi Aug 20, 2026
15e83bd
fix(chat): keep scoped styles within surface namespace
RoxyAsahi Aug 20, 2026
1a06cad
test(chat): refresh consumer report after surface isolation
RoxyAsahi Aug 20, 2026
0a009f9
test(chat): refresh renderer boundary after surface isolation
RoxyAsahi Aug 20, 2026
2929d5f
test(chat): prove desktop push subscription ownership
RoxyAsahi Aug 20, 2026
858add1
test(chat): exercise concurrent auxiliary surfaces
RoxyAsahi Aug 20, 2026
fb7ca7c
docs(chat): record extended lifecycle stress evidence
RoxyAsahi Aug 20, 2026
3cf046e
test(chat): exercise concurrent auxiliary surfaces
RoxyAsahi Aug 20, 2026
8a482fe
test(chat): await auxiliary context binding
RoxyAsahi Aug 20, 2026
ab84d80
fix(chat): deliver assistant context after renderer load
RoxyAsahi Aug 20, 2026
5279409
refactor(renderer): own canonical dom bindings at composition edge
RoxyAsahi Aug 20, 2026
1489d9b
refactor(chat): inject topic selection readiness capability
RoxyAsahi Aug 20, 2026
54c6e6d
test(chat): provide topic readiness in manager fixture
RoxyAsahi Aug 20, 2026
4649a16
refactor(chat): replace mutable selection globals with state capability
RoxyAsahi Aug 20, 2026
bbe93f6
docs(chat): record explicit state capability migration
RoxyAsahi Aug 20, 2026
bc4c755
refactor(chat): own projection runtime per surface
RoxyAsahi Aug 20, 2026
432b0a1
test(chat): clean assistant readiness gate
RoxyAsahi Aug 20, 2026
96d8ba0
refactor(chat): inject middle-click surface capabilities
RoxyAsahi Aug 20, 2026
95b60c6
refactor(chat): wire surface forward and audio capabilities
RoxyAsahi Aug 20, 2026
f1b106e
docs(chat): record capability and extended stress evidence
RoxyAsahi Aug 20, 2026
2a259e3
refactor(chat): complete D5 D6 kernel decoupling
RoxyAsahi Aug 21, 2026
05dd7c2
ci(chat): gate kernel and UI review checks
RoxyAsahi Aug 21, 2026
6b23966
merge: sync chat kernel draft with upstream main
RoxyAsahi Aug 21, 2026
2e7151c
docs(chat): refresh consumer report after upstream sync
RoxyAsahi Aug 21, 2026
bf8bd2a
fix(ui): use owned emoticon fixer in Ask Nova
RoxyAsahi Aug 21, 2026
0265c01
ci(ui): install Electron runtime for contract tests
RoxyAsahi Aug 21, 2026
4c2c885
docs(chat): plan typed event producer consumer graph
RoxyAsahi Aug 21, 2026
3d16a4d
fix(chat): tighten stream terminal handling and send accessibility state
RoxyAsahi Aug 22, 2026
b1cddab
test(chat): add contract evidence graph invariants and snapshots
RoxyAsahi Aug 22, 2026
ddbd3c2
ci(chat): publish contract and artifact evidence bundle
RoxyAsahi Aug 22, 2026
f5003ad
test(ui): record Electron evidence and update consumer report
RoxyAsahi Aug 22, 2026
b6a2e30
docs(chat): update decoupling audit and current state
RoxyAsahi Aug 22, 2026
99acbb9
fix chat stream recovery across topic switches
RoxyAsahi Aug 22, 2026
9b3f08d
chore: register evidence gate scripts
RoxyAsahi Aug 22, 2026
efca5ba
fix ui: hide internal chat surfaces from launchpad
RoxyAsahi Aug 22, 2026
55967de
Merge branch 'main' into codex/chat-kernel-deep-decoupling-draft-2026…
lioensky Aug 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions .github/workflows/chat_kernel_ui.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Chat Kernel and UI gates

on:
workflow_dispatch:
pull_request:
paths:
- 'renderer.js'
- 'main.html'
- 'modules/**'
- 'preloads/**'
- 'styles/**'
- 'tests/**'
- 'scripts/**'
- 'docs/chat-kernel-*.md'
- 'docs/contracts/**'
- 'docs/next-ui-current-state.md'
- 'package.json'
- 'package-lock.json'
- '.github/workflows/chat_kernel_ui.yml'

permissions:
contents: read

jobs:
contracts:
name: Chat Kernel and UI contracts
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0

- name: Setup Node 22
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: npm

- name: Setup Rust for built-artifact evidence
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable 2026-08-11

- name: Install dependencies (including Electron runtime)
env:
PUPPETEER_SKIP_DOWNLOAD: 'true'
# Electron's postinstall script downloads the runtime used by the
# embedded-app contract tests. Do not suppress lifecycle scripts here;
# this job does not perform native addon rebuilds.
run: npm ci --omit=optional

- name: Verify Electron runtime
run: node -e "const electron = require('electron'); if (typeof electron !== 'string') { throw new Error('Electron runtime path was not installed'); } console.log(electron)"

- name: Run Chat Kernel tests
run: npm run test:chat-kernel

- name: Run Chat contract evidence gate
env:
VCPCHAT_PACKAGED_ARTIFACT_SMOKE_OUTPUT: ${{ runner.temp }}/packaged-artifact-smoke.json
run: npm run check:chat-evidence

- name: Write Chat evidence manifest
env:
VCPCHAT_PACKAGED_ARTIFACT_EVIDENCE_INPUT: ${{ runner.temp }}/packaged-artifact-smoke.json
run: npm run write:chat-evidence-manifest -- "$RUNNER_TEMP/chat-evidence-manifest.json"

- name: Publish Chat evidence summary
env:
CHAT_EVIDENCE_MANIFEST: ${{ runner.temp }}/chat-evidence-manifest.json
run: node -e "const fs=require('fs'); const m=JSON.parse(fs.readFileSync(process.env.CHAT_EVIDENCE_MANIFEST,'utf8')); fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, ['## Chat evidence','', '- status: `'+m.status+'`','- contracts/events: `'+m.checks.contracts+'/'+m.checks.generatedEvents+'`','- dynamic sites: registered `'+m.checks.dynamicSites.registered+'`, undiscovered `'+m.checks.dynamicSites.undiscovered+'`','- artifact plane: `'+m.checks.artifactPlane+'`','- packaged artifact: `'+m.checks.packagedArtifact+'`','- Windows matrix: `'+m.checks.windowsMatrix+'`','- manual soak: `'+m.checks.manualSoak+'`','- real Electron: `'+m.checks.realElectronSequence+'` (manual/platform evidence remains separate)',''].join('\\n'));"

- name: Upload Chat evidence manifest
uses: actions/upload-artifact@v4
with:
name: chat-evidence-manifest
path: |
${{ runner.temp }}/chat-evidence-manifest.json
${{ runner.temp }}/packaged-artifact-smoke.json

- name: Upload Chat evidence bundle
uses: actions/upload-artifact@v4
with:
name: chat-evidence-bundle
if-no-files-found: error
path: |
docs/contracts/chat-contract.schema.json
docs/contracts/chat-contracts.json
docs/contracts/generated/chat-event-graph.json
docs/contracts/snapshots/*.json

- name: Run complete UI system gate
run: npm run check:ui-system
91 changes: 55 additions & 36 deletions Flowlockmodules/flowlock-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
// 多 Agent 并发架构:续写不再依赖当前 UI 状态,而是按指定 Agent/Topic 后台执行。

console.log('[Flowlock Integration] Loading integration script (multi-session)...');
let chatManagerProvider = null;
let historyMutationAuthorityProvider = null;
let settingsProvider = null;
const mainChatSnapshot = () => window.VCPMainChatState?.snapshot?.() || { selectedItem: null, topicId: null };

/**
* 初始化Flowlock模块
Expand All @@ -23,7 +27,7 @@ function initializeFlowlock() {
electronAPI: electronAPI,
uiHelper: window.uiHelperFunctions,
globalSettingsRef: {
get: () => window.globalSettings || {}
get: () => settingsProvider?.get?.() || {}
},
continueWritingForContext: continueWritingForContext
});
Expand Down Expand Up @@ -58,7 +62,7 @@ function normalizeFlowlockHeartbeatPrompt(prompt) {
async function continueWritingForContext(params) {
const { agentId, topicId, prompt, messageId } = params;
const chatAPI = window.chatAPI || window.electronAPI;
const globalSettings = window.globalSettings || {};
const globalSettings = settingsProvider?.get?.() || {};

if (!agentId || !topicId) {
console.error('[Flowlock] continueWritingForContext: missing agentId or topicId');
Expand Down Expand Up @@ -211,8 +215,7 @@ async function continueWritingForContext(params) {
avatarColor: agentConfig?.avatarCalculatedColor
};

const currentSelectedItem = window.currentSelectedItem;
const currentTopicId = window.currentTopicId;
const { selectedItem: currentSelectedItem, topicId: currentTopicId } = mainChatSnapshot();
const isForCurrentView = currentSelectedItem?.id === agentId && currentTopicId === topicId;

// 构建上下文。后台流也必须带完整身份,streamManager 才能写入正确历史。
Expand All @@ -225,29 +228,21 @@ async function continueWritingForContext(params) {
avatarColor: agentConfig?.avatarCalculatedColor
};

// 流式消息必须在发送请求前初始化,无论它当前是否可见。
// streamManager 自己负责“当前视图渲染 / 后台只写历史”的分流。
if (useStreaming) {
const streamStarter = window.streamManager?.startStreamingMessage
|| window.messageRenderer?.startStreamingMessage;
if (typeof streamStarter !== 'function') {
throw new Error('流式消息管理器未就绪');
}

await streamStarter({
...thinkingMessage,
content: '',
agentId,
topicId,
context
});
} else {
// Streaming lifecycle is now started by the VCP stream bridge when the
// producer publishes its first owned event. This prevents Flowlock from
// creating a second terminal state machine for the same message.
if (!useStreaming) {
let historyWithThinking = await chatAPI.getChatHistory(agentId, topicId);
if (!historyWithThinking || historyWithThinking.error) {
historyWithThinking = [];
}
historyWithThinking.push(thinkingMessage);
await chatAPI.saveChatHistory(agentId, topicId, historyWithThinking);
await historyMutationAuthorityProvider.replace({
itemId: agentId,
itemType: 'agent',
topicId,
category: 'flowlock-start'
}, historyWithThinking);
}

// 发送到 VCP
Expand Down Expand Up @@ -284,10 +279,15 @@ async function continueWritingForContext(params) {
if (historyForSave && !historyForSave.error) {
const finalHistory = historyForSave.filter(msg => msg.id !== thinkingMessageId && !msg.isThinking);
finalHistory.push(assistantMessage);
await chatAPI.saveChatHistory(agentId, topicId, finalHistory);

if (isForCurrentView && window.chatManager?.loadChatHistory) {
await window.chatManager.loadChatHistory(agentId, 'agent', topicId);
await historyMutationAuthorityProvider.replace({
itemId: agentId,
itemType: 'agent',
topicId,
category: 'flowlock-terminal'
}, finalHistory);

if (isForCurrentView && chatManagerProvider?.loadChatHistory) {
await chatManagerProvider.loadChatHistory(agentId, 'agent', topicId);
}
}

Expand Down Expand Up @@ -323,8 +323,7 @@ function setupFlowlockInteractions() {

e.preventDefault();

const currentItem = window.currentSelectedItem;
const currentTopic = window.currentTopicId;
const { selectedItem: currentItem, topicId: currentTopic } = mainChatSnapshot();

if (!currentItem || !currentItem.id || !currentTopic) {
if (window.uiHelperFunctions?.showToastNotification) {
Expand All @@ -351,8 +350,7 @@ function setupFlowlockInteractions() {

if (!window.flowlockManager) return;

const currentItem = window.currentSelectedItem;
const currentTopic = window.currentTopicId;
const { selectedItem: currentItem, topicId: currentTopic } = mainChatSnapshot();

if (window.flowlockManager.isAgentLocked(currentItem.id)) {
// 如果已激活,则停止
Expand Down Expand Up @@ -384,8 +382,7 @@ function setupFlowlockShortcuts() {

if (!window.flowlockManager) return;

const currentItem = window.currentSelectedItem;
const currentTopic = window.currentTopicId;
const { selectedItem: currentItem, topicId: currentTopic } = mainChatSnapshot();

if (!currentItem || !currentItem.id || !currentTopic) {
if (window.uiHelperFunctions?.showToastNotification) {
Expand All @@ -410,18 +407,40 @@ function setupFlowlockShortcuts() {
/**
* 主初始化函数
*/
function initializeFlowlockIntegration() {
function initializeFlowlockIntegration(dependencies = {}) {
try {
const provider = dependencies.chatManager;
if (!provider || typeof provider.loadChatHistory !== 'function' || provider.isReady?.() === false) {
throw new TypeError('Flowlock integration requires a ready ChatManager provider.');
}
const mutationAuthority = dependencies.historyMutationAuthority;
if (!mutationAuthority || typeof mutationAuthority.replace !== 'function') {
throw new TypeError('Flowlock integration requires a history mutation authority.');
}
if (chatManagerProvider && chatManagerProvider !== provider) {
throw new Error('Flowlock ChatManager provider is already registered.');
}
if (historyMutationAuthorityProvider && historyMutationAuthorityProvider !== mutationAuthority) {
throw new Error('Flowlock history mutation authority is already registered.');
}
if (!dependencies.settings || typeof dependencies.settings.get !== 'function') {
throw new TypeError('Flowlock integration requires a settings provider.');
}
chatManagerProvider = provider;
historyMutationAuthorityProvider = mutationAuthority;
settingsProvider = dependencies.settings;
initializeFlowlock();
setupFlowlockInteractions();
setupFlowlockShortcuts();

// 页面卸载时清理
window.addEventListener('beforeunload', () => {
const cleanup = () => {
if (window.flowlockManager) {
window.flowlockManager.cleanup();
}
});
};
if (dependencies.listenerOwner?.add) dependencies.listenerOwner.add(window, 'beforeunload', cleanup, { once: true });
else window.addEventListener('beforeunload', cleanup, { once: true });

console.log('[Flowlock Integration] Full integration complete (multi-session).');
} catch (error) {
Expand All @@ -432,4 +451,4 @@ function initializeFlowlockIntegration() {
// 导出到全局作用域
window.initializeFlowlockIntegration = initializeFlowlockIntegration;

console.log('[Flowlock Integration] Integration script loaded (multi-session).');
console.log('[Flowlock Integration] Integration script loaded (multi-session).');
10 changes: 5 additions & 5 deletions Flowlockmodules/flowlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class FlowlockManager {
*/
async stop(agentId) {
// 兼容旧插件 stop():优先停止当前可见 Agent,不再错误地停止其他并发 Session。
const resolvedAgentId = agentId || window.currentSelectedItem?.id;
const resolvedAgentId = agentId || window.VCPMainChatState?.snapshot?.()?.selectedItem?.id;
const session = this.sessions.get(resolvedAgentId);
agentId = resolvedAgentId;
if (!session) {
Expand Down Expand Up @@ -635,7 +635,7 @@ class FlowlockManager {
* 切换 Agent 后也可无参数调用,以当前可见 Agent 的真实 Session 为准。
*/
syncCurrentHeaderIndicator() {
const currentItem = window.currentSelectedItem;
const currentItem = window.VCPMainChatState?.snapshot?.()?.selectedItem;
const header = document.getElementById('currentChatAgentName');
if (!header) return;

Expand All @@ -651,7 +651,7 @@ class FlowlockManager {
}

updateCurrentHeaderIndicator(agentId, active) {
const currentItem = window.currentSelectedItem;
const currentItem = window.VCPMainChatState?.snapshot?.()?.selectedItem;
if (currentItem?.type !== 'agent' || currentItem.id !== agentId) return;

const header = document.getElementById('currentChatAgentName');
Expand All @@ -667,7 +667,7 @@ class FlowlockManager {
}

triggerCurrentHeaderHeartbeat(agentId) {
const currentItem = window.currentSelectedItem;
const currentItem = window.VCPMainChatState?.snapshot?.()?.selectedItem;
if (currentItem?.type !== 'agent' || currentItem.id !== agentId) return;

const header = document.getElementById('currentChatAgentName');
Expand Down Expand Up @@ -747,4 +747,4 @@ const flowlockManager = new FlowlockManager();
// 导出到window对象供其他模块使用
window.flowlockManager = flowlockManager;

console.log('[Flowlock] Manager instance created and exposed globally (multi-session).');
console.log('[Flowlock] Manager instance created and exposed globally (multi-session).');
2 changes: 1 addition & 1 deletion VCPDistributedServer/Plugin/VChatAutoTTS/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}

function currentAgent() {
const item = window.currentSelectedItem;
const item = window.VCPMainChatState?.snapshot?.()?.selectedItem;
return item?.type === 'agent' && item.id ? item : null;
}

Expand Down
3 changes: 1 addition & 2 deletions Voicechatmodules/voicechat.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ <h3 id="currentChatAgentName">语音聊天</h3>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="24" height="24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
</button>
</footer>
<script type="module" src="../modules/messageRenderer.js"></script>
<script type="module" src="voicechat.js"></script>
</body>
</html>
</html>
Loading
Loading