feat: add HoloLake personal channel module runtime

This commit is contained in:
冰朔 2026-08-09 14:14:07 +08:00
commit a106b23f9b
21 changed files with 786 additions and 31 deletions

View file

@ -32,6 +32,8 @@ function toolCall(id: string, name: string, args: Record<string, unknown> = {}):
function fakeGit(overrides: Record<string, unknown> = {}) {
return {
getRepositoryStatus: async () => ({}),
getChannelState: async () => ({ revision: 0, modules: [{ id: 'HL-MOD-KNOWLEDGE-001', installed: true, mounted: true, order: 0 }] }),
applyChannelPatch: async () => ({ id: 'HL-CHANNEL-RCPT-TEST', after: { revision: 1 } }),
getDoc: async (path: string) => ({
meta: { id: path, title: path, updatedAt: '2026-08-09T00:00:00Z' },
body: '正文',
@ -115,6 +117,29 @@ test('confirmed write receipt never leaks an orphan tool message into the next t
});
});
test('channel module changes use the same confirmation gate as document writes', { concurrency: false }, async () => {
let executed = 0;
await withMockModel([
toolCall('call-channel', 'set_channel_module_state', { moduleId: 'HL-MOD-KNOWLEDGE-001', mounted: false }),
{ content: '频道动作等待确认。' },
], async () => {
const agent = createDefaultPersona(fakeGit({
applyChannelPatch: async () => {
executed += 1;
return { id: 'HL-CHANNEL-RCPT-TEST', after: { revision: 1 } };
},
}));
const staged = await agent.chat('收起知识库');
assert.equal(staged.activities[0]?.status, 'pending');
assert.equal(executed, 0);
const pending = agent.getPendingActions()[0];
assert.equal(pending.target, 'HL-MOD-KNOWLEDGE-001');
const receipt = await agent.confirmAction(pending.id);
assert.equal(executed, 1);
assert.match(receipt.output, /HL-CHANNEL-RCPT-TEST/);
});
});
test('persona wake route is resolved and read dynamically without a fixed step count', { concurrency: false }, async () => {
const routePath = 'personas/TCS-0002/WAKE-CURRENT.md';
await withMockModel([