basant307/AI_Governance_Project
048
1/**2 * @license3 * Copyright 2026 Qwen Team4 * SPDX-License-Identifier: Apache-2.05 */6import { describe, expect, it } from 'vitest';7import { SessionNotFoundError } from './acp-session-bridge.js';8import { createWorkspaceRegistry, createSingleWorkspaceRegistry, } from './workspace-registry.js';9function bridgeWithSummary(getSessionSummary) {10 return { getSessionSummary };11}12function makeRuntime(workspaceCwd, overrides = {}) {13 const bridge = bridgeWithSummary(() => {14 throw new SessionNotFoundError('missing');15 });16 return {17 workspaceId: `id:${workspaceCwd}`,18 workspaceCwd,19 primary: false,20 trusted: true,21 env: { mode: 'parent-process', overlayKeys: [] },22 bridge,23 workspaceService: {},24 routeFileSystemFactory: {},25 clientMcpSenderRegistry: {},26 ...overrides,27 };28}29describe('createSingleWorkspaceRegistry', () => {30 it('exposes the supplied runtime as the primary and only runtime', () => {31 const runtime = makeRuntime('/work/primary', { primary: true });32 const registry = createSingleWorkspaceRegistry(runtime);33 expect(registry.primary).toBe(runtime);34 expect(registry.list()).toEqual([runtime]);35 expect(registry.list()[0]).toBe(runtime);36 });37 it('looks up only the exact canonical workspace string', () => {38 const runtime = makeRuntime('/work/primary', { primary: true });39 const registry = createSingleWorkspaceRegistry(runtime);40 expect(registry.getByWorkspaceCwd('/work/primary')).toBe(runtime);41 expect(registry.getByWorkspaceCwd('/work')).toBeUndefined();42 expect(registry.getByWorkspaceCwd('/work/primary/child')).toBeUndefined();43 expect(registry.getByWorkspaceCwd('/work/primary/')).toBeUndefined();44 expect(registry.getByWorkspaceCwd('/other')).toBeUndefined();45 });46 it('looks up by workspace id and resolves omitted workspace to primary', () => {47 const runtime = makeRuntime('/work/primary', {48 workspaceId: 'ws-primary',49 primary: true,50 });51 const registry = createSingleWorkspaceRegistry(runtime);52 expect(registry.getByWorkspaceId('ws-primary')).toBe(runtime);53 expect(registry.getByWorkspaceId('missing')).toBeUndefined();54 expect(registry.resolveWorkspaceCwd(undefined)).toBe(runtime);55 expect(registry.resolveWorkspaceCwd('/work/primary')).toBe(runtime);56 expect(registry.resolveWorkspaceCwd('/work/primary/')).toBeUndefined();57 });58});59describe('createWorkspaceRegistry', () => {60 it('keeps runtime order frozen and uses the marked primary runtime', () => {61 const primary = makeRuntime('/work/primary', {62 workspaceId: 'ws-primary',63 primary: true,64 });65 const secondary = makeRuntime('/work/secondary', {66 workspaceId: 'ws-secondary',67 });68 const registry = createWorkspaceRegistry([primary, secondary]);69 expect(registry.primary).toBe(primary);70 expect(registry.list()).toEqual([primary, secondary]);71 expect(() => registry.list().push(primary)).toThrow(TypeError);72 expect(registry.getByWorkspaceCwd('/work/secondary')).toBe(secondary);73 expect(registry.getByWorkspaceId('ws-secondary')).toBe(secondary);74 expect(registry.resolveWorkspaceCwd('/work/missing')).toBeUndefined();75 });76 it('rejects invalid registry construction', () => {77 const primary = makeRuntime('/work/primary', {78 workspaceId: 'ws-primary',79 primary: true,80 });81 const otherPrimary = makeRuntime('/work/other', {82 workspaceId: 'ws-other',83 primary: true,84 });85 expect(() => createWorkspaceRegistry([])).toThrow(/at least one workspace runtime/);86 expect(() => createWorkspaceRegistry([makeRuntime('/work/no-primary')])).toThrow(/exactly one primary workspace runtime/);87 expect(() => createWorkspaceRegistry([primary, otherPrimary])).toThrow(/exactly one primary workspace runtime/);88 expect(() => createWorkspaceRegistry([89 primary,90 makeRuntime('/work/primary', { workspaceId: 'ws-duplicate-cwd' }),91 ])).toThrow(/Duplicate workspace runtime cwd/);92 expect(() => createWorkspaceRegistry([93 primary,94 makeRuntime('/work/secondary', { workspaceId: 'ws-primary' }),95 ])).toThrow(/Duplicate workspace runtime id/);96 });97 it('resolves live session owners without falling back to primary', () => {98 const primary = makeRuntime('/work/primary', {99 workspaceId: 'ws-primary',100 primary: true,101 bridge: bridgeWithSummary(() => {102 throw new SessionNotFoundError('sess-secondary');103 }),104 });105 const secondary = makeRuntime('/work/secondary', {106 workspaceId: 'ws-secondary',107 bridge: bridgeWithSummary((sessionId) => {108 if (sessionId !== 'sess-secondary') {109 throw new SessionNotFoundError(sessionId);110 }111 return { sessionId, workspaceCwd: '/work/secondary' };112 }),113 });114 const registry = createWorkspaceRegistry([primary, secondary]);115 expect(registry.resolveLiveSessionOwner('sess-secondary')).toEqual({116 kind: 'found',117 runtime: secondary,118 });119 expect(registry.resolveLiveSessionOwner('missing')).toEqual({120 kind: 'not_found',121 });122 });123 it('fails closed when live session owner resolution is ambiguous', () => {124 const first = makeRuntime('/work/primary', {125 workspaceId: 'ws-primary',126 primary: true,127 bridge: bridgeWithSummary((sessionId) => ({128 sessionId,129 workspaceCwd: '/work/primary',130 })),131 });132 const second = makeRuntime('/work/secondary', {133 workspaceId: 'ws-secondary',134 bridge: bridgeWithSummary((sessionId) => ({135 sessionId,136 workspaceCwd: '/work/secondary',137 })),138 });139 const registry = createWorkspaceRegistry([first, second]);140 expect(registry.resolveLiveSessionOwner('sess-ambiguous')).toEqual({141 kind: 'ambiguous',142 runtimes: [first, second],143 });144 });145 it('propagates unexpected live session lookup errors', () => {146 const lookupError = new Error('bridge unavailable');147 const primary = makeRuntime('/work/primary', {148 workspaceId: 'ws-primary',149 primary: true,150 bridge: bridgeWithSummary(() => {151 throw lookupError;152 }),153 });154 const registry = createWorkspaceRegistry([primary]);155 expect(() => registry.resolveLiveSessionOwner('sess')).toThrow(lookupError);156 });157});158//# sourceMappingURL=workspace-registry.test.js.map